Syntax

_images/icon22.webp

Pretty colors

The syntax describes how OptiFine's resource pack features will behave and operate.

Different formats and types of values are used within files used by OptiFine-specific features. Rather than describe these common types separately in each feature's section, they are summarized here instead.

File structure

Many OptiFine features use properties files to control how OptiFine-specific elements will work within a resource pack.

Properties files are simple text files similar to the Windows INI format. Each line is a property, specified as name=value.

# Comments begin with a hashtag and are ignored.
property1=value
property2=some_other_value

# Blank lines are allowed.
property3=yet_another_value

All property names are case-sensitive; renderpass is not the same as renderPass. The order of properties within the file does not matter. Many properties have default values and can be omitted, and in some cases, the entire properties file is optional.

Paths, file locations

Often, OptiFine requires specifying a path to a texture or other file within the resource pack. A path is a "location" of where a file is.

All paths must match the regex ^[a-z0-9_.\/-]+$ (Test this pattern on Regex101).

Hint

Must be lowercase, no spaces, a through z, 0 through 9, and _ . / - only.

The folder structure within a resource pack is deeply nested, so OptiFine has some shortcuts to make paths easier to write. Any of these options can be used to specify the same path.

Always use the forward slash "/" to separate folders.

Caution

Regardless of the operating system, do not use the backslash "\", or the game will not properly recognize the path.

The below table summarizes path shortcuts:

Symbol

Resolves to

None

/assets/minecraft/optifine/

.

File's folder

..

Not valid syntax

~

/assets/minecraft/optifine/

<namespace>:

/assets/<namespace>/

Bare filenames with no slashes will refer to the file relative to /assets/minecraft/optifine/, ignoring subfolders.

texture=texture.png
# Resolves to /assets/minecraft/optifine/texture.png

You can use . to denote the current directory, regardless of location. This does work in subfolders.

texture=./texture.png
texture=./subdirectory/texture.png

The tilde character ~ can be used to refer to /assets/minecraft/optifine/.

texture=~/texture.png
texture=~/subfolder/texture.png

An optional "namespace" prefix can be added. This example refers to exactly the same "creeper.png" file as default:

texture=minecraft:textures/entity/creeper/creeper.png

For textures used by mods, the namespace will be something other than minecraft:

texture=MODID:subfolder/texture.png

This refers to /assets/MODID/subfolder/texture.png, not to /assets/minecraft/MODID/subfolder/texure.png.

Important

In this documentation, a green box captioned "File location" tells you where the respective file(s) should be. It uses bash syntax. In summary:

  • GLOBSTAR: ** will match infinitely many directories, including zero.

  • STAR PATTERN: * will match all filenames. *.png will match "anynamehere.png" but not "notpng.jpeg".

  • BRACE EXPANSION: {a,b} will match both a and b. *.{png,json} will match "file.png" and "thing.json".

Biomes

See also

See this page for the 1.13 biome changes.

For features that call for a list of biomes, use this page. Biomes added by mods can also be used.

biomes=ocean deep_ocean river beach modid:biome

Components, NBT

OptiFine supports conditions based on an item's data. These are most often used in Custom Item Textures.

Components are the newest format, added in Minecraft 1.20.5. Prior to this, the format was NBT.

For general behavior that applies to both components and NBT, this documentation uses the name "data rules" to refer to both format types.

Entities (such as Random Entities) still use the NBT format.

Hint

To view the data of something, use the command /data get. For example, to inspect the item you are holding in your main hand, use /data get entity @s SelectedItem. For more details, see Commands/data - Minecraft Wiki.

General behavior

If multiple data rules are provided, all of them must match.

A value starting with an exclamation mark "!" negates the match (match the opposite of this). Multiple exclamations do nothing; !!0 is not equivalent to 0.

Important

If components are expected, NBT rules should not be used.

  • If components and nbt rules are both specified, the NBT rules are ignored and a warning will be logged.

  • If there are no components rules and not every nbt rule can be mapped to a component, the entire file is skipped as invalid.

Example
  • If value of X is Y: X=Y

  • If Y is in list X: X.*=Y

  • If Y is the first entry of list X: X.0=Y

  • If list X has 5 elements: X.count=5

  • If X is in range: X=range:0-100

  • If X exists: X=exists:true

  • If Y key exists in any compound in list X: X.*.Y=exists:true

  • Name: components.item_name="My Sword"

  • Escapes: components.item_name="\u00a74\u00a7oMy Sword"

  • First line of lore: components.lore.0=My Lore Text

  • Any line of lore: components.lore.*=My Lore Text

Component format

Components are specified as keys with the components. syntax.

Components may include a namespace. To specify a namespace, the first : must be escaped - prefixed with a backslash \\. If no namespace is specified, it defaults to minecraft:.

Components and component keys that use the minecraft: namespace can be shortened with a tilde (~) instead. For example, components.enchantments.levels.~thorns becomes components.minecraft\:enchantments.levels.minecraft\:thorns.

  • components.minecraft\:custom_name

  • components.custom_name

  • components.mod\:coolness_factor

  • components.enchantments.levels.minecraft:thorns

  • components.minecraft:custom_name

  • components.minecraft\\:custom_name

  • components.mod.coolness_factor

Legacy

Some legacy NBT checks are automatically converted into Component format for backwards-compatibility only.

  • nbt.display.Name becomes components.minecraft\:custom_name

  • nbt.display.Lore becomes components.minecraft\:lore

Do not rely on this functionality for new packs.

NBT format

NBT are specified as keys with the nbt. syntax.

For older versions of Minecraft and for entities, the NBT format is used instead of the Component format.

Types

Strings

A string is text, optionally wrapped in double- or single-quotes " '.

If a strings contains only the characters 0-9 A-Z a-z _ - . +, it does not need to be wrapped in quotes. You can test this on Regex101.

All characters can be escaped with the Unicode codepoints, like \u2605 for , This is recommended for characters with a codepoint above U+007E TILDE ~.

Hint

If the character isn't on your keyboard, it's likely above U+007E and should be escaped!

When matching strings, any formatting (like color or bold) is stripped out. To test specifically for this formatting, use raw instead.

Important

Any backslashes must be escaped with another backslash. Matching backslashes within a regular expression or wildcard must be quadrupled.

  • regex:\\d+

  • regex:\\\\

  • /\\/\\

  • regex:\d+ (missing a backslash for \d)

  • regex:\\ (for matching \\\\; would match \ alone)

  • /\/\\ (missing a backslash for \/)

Example

  • "All your base are belong to us"

  • '{looks:"like something fancy",but:"alas, this is just a string!"}'

  • "Oh hello, \"Jeanine\"..."

  • 'My reflection \"winked\" at me. I covered the mirror in the attic just to be safe.'

Lists

A list (or array) is a sequence of elements wrapped in brackets [ ] and delimited by commas: [E0,E1,E2,...].

They are an ordered collection of data of the same type.

Each element can be accessed with its index, its position in the list. Lists are zero-indexed; this means that 0 refers to the first element, and 1 is the second.

The length of a list (the number of elements in it) can be accessed with the count attribute: components.banner_patterns.count=range:0-9

  • [1,2,3,4]

  • []

  • ["strings","too",and,"emacs is superior"]

  • [["can nest other lists in lists","like this!"],[1,2,3,4,-5],["vim is superior"]]

  • [{emacs:"is bad",vim:"is bad",ed:"is best"},{'but also':"pen and paper","can be...":"stronger"}]

  • [true,false,true,true]

  • [1,"string",64s]

  • [{"mixing types in lists":"is no good"},"-Sonic Sez"]

Compounds

A compound (or object, map, dictionary) is a sequence of key-value pairs wrapped in braces { } with pairs delimited by commas and split by colons :: {key:value,a:b,...}.

Each key is unique and points to a value. Keys are always Strings.

Unlike Lists, values do not have to be of the same type in a compound. For example, {a:1,b:"string",c:64s} is valid, while the list [1,"string",64s] would not be.

Each value can be accessed with its key. With lists, elements are accessed with their index. Likewise, values are accessed with their key as the "index".

  • {key:value,fishy:anchovies}

  • {"who owes me money":nephew}

  • {1:"key is actually a string","another type":[1,2,3]}

  • {"I'm getting":{"a sense of":{"deja-vu":true},"with all of these":confusing},"nesting":"Matryoshka dolls"}

  • {}

  • {this needs to be quoted:"I took his advice"}

  • {1, 2, 3}

Numbers

A number is a byte, short, integer, long, float, or double. This term is used to refer to all of these types collectively, so "number" itself is not a real type.

Type

Details

Byte

Suffixed with b, or B. Signed 8-bit integer, ranges from -128 to +127.

Short

Suffixed with s, or S. Signed 16-bit integer, ranges from -32768 to +32767.

Integer

No suffix. Also known as int. Signed 32-bit integer, ranges from -2147483648 to +2147483647.

Long

Suffixed with l, or L. Signed 64-bit integer, ranges from -9223372036854775808 to +9223372036854775807.

Float

Suffixed with f, or F. Signed 32-bit decimal, ranges from -3.4E38 to +3.4E38.

Double

Suffixed with no suffix, d, or D. Signed 64-bit decimal, ranges from -1.7E308 to +1.7E308.

Important

Values like components.dyed_color.rgb are stored as integers representing colors. They are commonly formatted as #RRGGBB, where R, G, B are hexadecimal values for red, green, and blue. For instance, #FFAA00 equals the integer 16755200.

For convenience, you can match these values using the same format. For example, components.dyed_color.rgb=#ffaa00 would match if rgb was 16755200.

This does not work for integers above #FFFFFF, 16777215.

Example
  • 120b

  • 31045s

  • -32768S

  • -64

  • 3579687596278847L

  • #ced357

  • 0.333f

  • 0.4525D

Booleans

A boolean is either true or false.

NBT does not have a boolean type, however. The values true and false are simply aliases for 1b and 0b, respectively (byte 1 and byte 0).

Typed Arrays

A typed array is a byte array, int array, or long array. This term is used to refer to all of these types collectively, so "typed array" itself is not a real type.

They are wrapped in brackets [ ] and the first element is an identifier of their type. For example, [N;e,e,e,...] where N is the identifier and e are elements.

Important

These are special types in NBT and are not the same as lists, although they do look similar! Note that [I;1,2,3,4] and [1,2,3,4] are not the same thing.

Identifier is B;: [B;1b,2B,3b]

Identifier is I;: [I;53,63872,-258973,0]

Identifier is L;: [L;0L, 5245757867447459784747l, -258965432855427280L, 35l]

Prefixes

A prefix can be used to change how a key or value is tested. Some prefixes can be combined with other prefixes.

Exists

The prefix exists: checks if a key is defined at all. It takes 1 value, true or false.

  • true will apply if the key exists.

  • false will apply if the key does not exist - it is not defined.

Example
components.lore=exists:true
components.item_name=exists:false
components.pot_decorations.0=exists:true
components.potion_contents.custom_effects.*.show_icon=exists:false

Pattern

The prefix pattern: and ipattern: match with wildcards.

Wildcards are shorter versions of regular expressions - they only support two special symbols:

  • The symbol ? matches any one character.

  • The symbol * matches any number of characters.

The wildcard ? is equivalent to the regular expression . (1 of anything).
The wildcard * is equivalent to the regular expression .* (0 or more of anything).
  • pattern is case-sensitive; pattern:a will not match "A".

  • ipattern is case-insensitive; pattern:a will match both "A" and "a".

pattern:*

Test this pattern on Regex101

The wildcard * matches 0 or more of anything. This includes nothing at all.

  • a

  • One must always reign beneath Dusk

  • Get to the choppah

  • *

pattern:?at

Test this pattern on Regex101

The wildcard ? matches just 1 character.

  • bat

  • Cat

  • sat

  • 5at

  • Mat

  • at

  • stat

  • Hats for everyone

ipattern:look at me

Test this pattern on Regex101

ipattern makes the search case-insensitive.

  • look at me

  • LOOK AT ME

  • look at ME

  • LOOK at me

  • lOOk at me

  • Look at me!

  • Don't look at me

  • LookAtMe

pattern:Lamp oil, rope, bombs you want it\\? It's yours, my friend, as long as you have enough rupees.

Test this pattern on Regex101

To use a wildcard character as normal, escape it by prefixing it with a backslash. Backslashes must be doubled to be recognized correctly.

  • Lamp oil, rope, bombs you want it? It's yours, my friend, as long as you have enough rupees.

  • lamp oil, rope, bombs you want it? it's yours, my friend, as long as you have enough rupees.

  • Sorry, Link, I can't give credit! Come back whey you're a little mmmm richer.

  • I wonder what's for dinner.

pattern:* letter to my grand?a

Test this pattern on Regex101

You can use any combination of wildcards.

  • A letter to my grandma

  • The letter to my grandpa

  • Some letter to my grandda

  • No letter to my grand!a

  • I didn't write a letter to my grand a

  • letter to my grandpa

  • A letter to my grandfather

  • A letter to my grandma.

ipattern:Mr. *, I'm * at street ?, looking for *p!

Test this pattern on Regex101

Wildcards can be surrounded by other non-wildcard characters to create accomodating patterns.

  • Mr. Leno, I'm indeed at street A, looking for soup!

  • Mr. Bruce Wayne, I'm not at street 9, looking for shoes with !

  • Mr. Spock, I'm on a mysterious planet... I'm near street 1, looking for some food in the ship!

  • Mr. I'll have you know, I'm somewhere at street 23, looking for a lollipop!

  • Mr. Crosh, hi, I'm uh, at a street 2, looking for your bipartisanship!

  • Well, Gordon Freeman! And about time, too.

Range

The prefix range: checks if an integer value is within a list of other integers or integer ranges.

Items are delimited by a space, as in range:1 2 3 9-15 4. Items do not need to be in order.

Example
components.max_damage=range:(-50)-(-25) 200 0-100
components.instrument.*.range=range:3-18
components.potion_contents.*.custom_effects.*.duration=range:(-1)-3 5 10 26

Integers that are not in a range match that integer only.

A range between two integers is written as X-Y.

  • If Y is absent, the upper bound is 65535.

  • If X is absent, it's a negative number and not a range.

  • If X and Y are absent, the range is invalid; - alone is not valid.

Negative bounds must be enclosed in parentheses. For instance, range:(-9)-(-5) matches -9, -8, -7, -6, -5.

Note

To match values less than or equal to a number, use a full range like 0-100, not -100.

Raw

The prefix raw: matches exact SNBT values.

Raw can be used to match types explicitly, such as bytes, shorts, floats, doubles, and typed arrays. It can also be used to match formatted text, since formatting is normally removed for checks against Strings.

raw: can also be combined with all other prefixes. For example: raw:pattern:, raw:iregex:, etc.

Important

Spaces in between elements must be removed. For example, [1,2,3,4] and not [1, 2, 3, 4].

Example
components.item_name=raw:'[{"text":"Dark red italics","italic":true,"color":"dark_red"}]'
components.bucket_entity_data.Health=raw:10.0f
nbt.1.UUID=raw:[I;-1668711424,-1434628111,-1613745989,1749596493]
nbt.5.someRandomShort=raw:64s

Regex

The prefix regex: and iregex: match with regular expressions.

Regular expressions (or regex) are patterns that can match complex text succinctly.

Regexes can be a simple Hi, .*! or a complex ^(?:(?:25[0-5]|2[0-4]\d|1?\\d{1,2})(?:\\.(?!$)|$)){4}$.

The syntax understood by OptiFine is the Java syntax. OptiFine regular expressions are not multiline and are not global ("/gm").

To match a string with regular expressions, use the regex: or iregex: prefix;

  • regex is case-sensitive; regex:a{4} will not match "AAAA".

  • iregex is case-insensitive; iregex:a{4} will match both "AaAA", "aaaa", "aaAA", etc.

regex:.*

Test this pattern on Regex101

This regex is equivalent to the wildcard *.

Note

iregex would be useless here, as there is no case-sensitivity applicable in the pattern.

  • Mmmm. Steamed Clams!

  • No, it's an Albany expression.

  • Enough! You are indeed... worthy.

  • Blue Skull Key

  • Who are you calling pinhead?

iregex:[ae]ffect

Test this pattern on Regex101

[] matches any one of the characters in between the brackets.
Create ranges with -, like [A-Z].
Negate the group by prefixing it with ^: [^abc].
  • affect

  • AFFECT

  • Effect

  • effect

  • affecT

  • aeffect

  • A bad effect

  • Effecting

  • affect someone else

regex:\\d{4,}

Test this pattern on Regex101

\d matches any digit.
{n,} matches the previous element if it occurs at least n times.

Hint

Remember that backslashes must be doubled.

  • 1234

  • 3580

  • 00001

  • 11113587

  • 3589638974389676434574675098

  • 000

  • Room number 5567

  • 55555.

regex:Something fishe?y is(n't)? brewing\\.+

Test this pattern on Regex101

Unlike wildcards, ? matches the previous character 0 or 1 times. In other words, it's optional.
Using a group () is needed for the ? to apply to that whole group; isn't? is not the same as is(n't)?.
+ matches the previous character 1 or more times.
Since its escaped, \. is a literal period, not a metacharacter.

Hint

Remember that backslashes must be doubled.

  • Something fishey is brewing.

  • Something fishy is brewing.....

  • Something fishey isn't brewing...

  • Something fishy isn't brewing.

  • Something fishy is brewing.

  • Something fishey isn't brewing

  • something fishy is brewing...

  • A smelly smell that smells.... smelly. Anchovies.

iregex:i want more (apple|orange)s[.!?]

Test this pattern on Regex101

You can use the | character for "OR". It will match the element before or after it.
Metacharacters like . ? do not need to be escaped when in a character class ([]).
  • I want more apples!

  • i want more oranges.

  • I WANT MORE ORANGES?

  • i want MORE apples!

  • i want more apples.

  • I want more apples

  • I don't want any apples

  • Grapes are far better.

regex:\\(\\d{3}\\) \\d{3}-\\d{4}

Test this pattern on Regex101

Groups can also be escaped to match parentheses literally.

  • (345) 867-5309

  • (000) 000-0000

  • (123) 456-7890

  • Left on read

Client-side data

Not all data can be detected.

Minecraft operates on a server/client model, even when in singleplayer mode. As OptiFine functions as a client-side mod, it only has access to data transmitted from the server to the client. If the data is exclusively server-side and not mirrored on the client side, it cannot be tested under NBT rules.

A general guideline is as follows: if the component/NBT visibly alters it, it can likely be used.

There is no definitive list yet of what data tags are client-side and which ones are not.

Blocks, items

Blocks and items can be specified in the same way that they are in Minecraft, by name.

The block name format is [namespace:]name[:property1=value1:property2=value2:...]. Optional parts are in brackets [ ]. The default namespace is minecraft.

Example

This will apply to oak stairs that are east- or west-facing and are the bottom half.

blocks=minecraft:oak_stairs:facing=east,west:half=bottom
blocks=oak_stairs:facing=east,west:half=bottom

The minecraft: namespace is optional, so it can also be omitted.

Block states

Block states are extra data attached to a block. They are simple key-value pairs.

Block states can be specified in addition to the block name.

Block states are specified after a block name and are delimited by the : character. Each block state that follows is a simple key=value pair. To match more than one possible value for the key, split the value's options by a ,. For example, facing=west,east will match a block state where facing is equal to either west or east.

Block state keys and values themselves can only be simple strings. An infinite number of block states may be specified. Any invalid block states (states not applicable to a block) are ignored.

Blending methods

See also

See Blend modes on Wikipedia for some illustrations.

When two or more textures are combined, OptiFine offers several options for specifying the blending operation, if applicable.

"This" or "current" texture refers to the texture currently being applied. "Previous" refers to whatever has been rendered so far, which could be a single texture or the result of an earlier blending operation.

replace

Replace the previous layer entirely with the current bitmap. No blending.

alpha

Blend the two textures using this texture's alpha value. This is the most common type of blending.

overlay

RGB value > 0.5 brightens the previous image, < 0.5 darkens. color is a synonym for this method.

add

Add this texture's RGB values multiplied by alpha to the previous layer.

subtract

Subtract this texture's RGB values from the previous layer.

multiply

Multiply the previous RGB values by this texture's RGB values

dodge

Add this texture's RGB values to the previous layer.

burn

New RGB = (1 - Current RGB) * Previous RGB

screen

New RGB = 1 - (1 - Current RGB) * (1 - Previous RGB)


Assumes the latest OptiFine & Minecraft versions.
Updated to commit 83d482c3.