Syntax¶

A snippet of a properties file.¶
This page details the rules and formats for specifying how OptiFine features work in a resource pack.
File naming rules¶
For any file in a resource pack to be visible to the game, it must match the regular expression ^[a-z0-9_.]+$
.
Hint
Must be lowercase, no spaces, a through z, 0 through 9, and _ only.
Textures must be in PNG format with the .png
extension.
All text files must be encoded in UTF-8 without BOM. Do not use an ASCII encoding.
JSON files must follow the JSON specification strictly and have the .json
extension.
File structure¶
Many OptiFine features use properties files to control how OptiFine-specific elements will work within a resourcepack.
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.
Certain types of objects are used within properties files by different OptiFine features. Rather than describe these common types separately in each feature section, they are summarized here instead.
Paths¶
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.
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 forward slashes "/
" to separate folders.
Caution
Regardless of operating system, do not use backslashes "\
", or the game will not properly recognize the path.
The below table summarises path shortcuts:
Symbol |
Resolves to |
---|---|
None |
|
|
|
|
Not valid syntax |
|
|
|
|
Bare filename¶
Bare filenames with no slashes will refer to the file relative to /assets/minecraft/optifine/
, ignoring sub-folders.
texture=texture.png
Dot and dot-dot¶
You can use ./
to denote the current directory, regardless of location. This does work in subfolders.
..
can be used to travel up a folder, into the parent directory.
texture=./texture.png
texture=../texture.png
texture=../../subfolder/texture.png
Tildes¶
The tilde character ~
can be used to refer to /assets/minecraft/optifine/
.
texture=~/texture.png
texture=~/subfolder/texture.png
Namespaces¶
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 other 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
.
Namespaces can also apply to blocks, items, and biome IDs.
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
NBT¶
OptiFine supports conditions based off of an item's NBT.
If multiple NBT rules are provided, all of them must match.
A value starting with !
negates the match (match all EXCEPT this).
List indexes start at 0; 0 is the first element, 1 is the second.
All Unicode codepoints can be escaped with \uXXXX
,
but this is not required and is recommended for non-visible characters or characters above U+007E TILDE ~.
Some examples include:
Match if Y is in list X:
nbt.X.*=Y
Match specific value:
nbt.X=Y
Match number in range:
nbt.X=range:0-100
Match if Y is first entry of list X:
nbt.X.0=Y
Match if X exists:
nbt.X=exists:true
Match item display name:
nbt.display.Name=My Sword
Match item display name with escapes:
nbt.display.Name=\u00a74\u00a7oMy Sword
Match item lore (first line only):
nbt.display.Lore.0=My Lore Text
Match item lore (any line):
nbt.display.Lore.*=My Lore Text
Exists¶
You can check for the presence of an NBT value for a given tag by using the exists:
prefix.
It takes only two values: true
and false
.
true
will apply if the NBT key given has any value associated with it.
false
will apply if the NBT key given is not present in the item's NBT.
# Apply to items that have any lore
nbt.display.Lore=exists:true
# Apply to items that have no lore at all
nbt.display.Lore=exists:false
New in version I1.
Raw¶
See also
Familiarize yourself with (S)NBT data types.
Raw exact values may be matched by using the raw:
prefix.
All values for raw:
must be typed exactly as they are shown in the game's output log.
Raw can be used to match types explicitly, such as bytes, shorts, floats, doubles, etc.
nbt.display.Name=raw:'[{"text":"Dark red italics","italic":true,"color":"dark_red"}]'
nbt.3.OnGround=raw:1b
nbt.1.UUID=raw:'[I;-1668711424,-1434628111,-1613745989,1749596493]'
nbt.someRandomShort=raw:64s
The value must match exactly as the game reports it.
raw:
can also be combined with all other prefixes. For example: raw:pattern:
, raw:regex:
, etc.
New in version I1.
Blocks and items¶
See also
Danger
Do not use 1.7- IDs in 1.13+ packs!
In 1.13, many variant blocks were "flattened" to several simple blocks, and the block metadata was removed from their ID.
The block name format is [namespace:]name[:property1=value1,...:property2=value1,...]
.
Optional parts are in angle brackets [ ]
. The default namespace is minecraft
.
Before 1.7, items can only be specified by ID.
Since 1.7, items can also be specified by name, alongside ID.
Since 1.13, items can only be specified by name, not ID.
The block IDs continue to exist within the game internally, but can no longer be specified in the configuration files as they are unstable.
For example, Stone used to be ID 1
, but is now named minecraft:stone
.
As with textures, the "minecraft:
" prefix is optional, so just "stone
" will also work, as "minecraft:
" is the default.
In the event of mods, they will likely use a namespace other than minecraft:
, so the prefix will be required for referring to modded items.
blocks=minecraft:oak_stairs:facing=east,west:half=bottom
blocks=oak_stairs:facing=east,west:half=bottom
The above will apply to oak stairs that are east or west facing, and are the bottom half.
The minecraft:
namespace is optional, so it can also be omitted.
Strings¶
This section is about matching strings and values using different matching methods. Strings can be matched in several ways.
Important
Any backslashes must be doubled. Matching backslashes within a regular expression or wildcard must be quadrupled.
nbt.display.name=regex:\\d+
nbt.display.name=regex:\\\\
nbt.display.name=/\\/\\
nbt.display.name=regex:\d+
nbt.display.name=regex:\\
(for matching \\)nbt.display.name=/\/\\
(missing a backslash)
Exact value¶
For strings, you may either type the string directly: Letter to Herobrine
matches the exact string Letter to Herobrine
and nothing else.
You may also use the Raw syntax.
Wildcards¶
Wildcards are shorter versions of regular expressions, in that they only support two unique constructs:
The symbol
?
matches any text, as long as it exists.The symbol
*
matches any text, regardless of its presence.
*
is equivalent to the regular expression .*
(0 or more).?
is equivalent to the regular expression .+
(1 or more).Wildcard patterns must start with either pattern:
or ipattern:
.
Note
The meanings of ?
and *
are swapped in contrast to regular expressions. It is unknown if this is a bug.
pattern¶
pattern
is case-sensitive.
Example: pattern:*Letter to ?
Letter to Herobrine
Letter to a creeper
My Letter to John
(note the uppercase L)letter to Herobrine
(case sensitivity)Letter from Herobrine
(doesn't match "to")Letter to
(doesn't match "?")
ipattern¶
ipattern
is case-insensitive, meaning that "ABC" and "abc" are viewed the same.
Example: ipattern:*Letter to ?
Letter to Herobrine
My letter to Herobrine
Letter to a creeper
letter to Herobrine
letter to STEVE!
A letter from CJ
Letter from Herobrine
Regular expressions¶
Regular expressions are strings that create "patterns" that other strings can be matched against.
Patterns can be as simple as .
, to IP address validation.
OptiFine supports two types of regular expressions, depending on the case-sensitivity.
In addition, OptiFine does not support
expression flags.
The syntax understood by OptiFine is the Java syntax. OptiFine regular expressions are not multiline and are not global ("/gm").
Regular expressions must start with either regex:
or iregex:
.
regex¶
A regular expression.
Example: regex:Letter (to|from) .*
Letter to Herobrine
Letter from Herobrine
letter to Herobrine
(letter case)A Letter to Herobrine
(A
is not in expression)
iregex¶
iregex
is similar to regex
, except that it is case-insensitive.
Example: iregex:Letter (to|from) .*
Letter to Herobrine
Letter from Herobrine
letter to Herobrine
LETTER TO HEROBRINE
A Letter to Herobrine
(A is not in expression)LETTER TOFROM HEROBRINE
Numbers¶
Numbers can be matched simply by typing the number. Additionally, you can match more than one number as well as a range of numbers with lists and ranges.
Ranges¶
Important
There is no range for less than or equal to; use a full range: 0-100
, not -100
to match ≤100.
Inclusive ranges between numbers are defined with a -
between those digits.
If there is no number present on the right side of the -
, the range will match to positive infinity.
Ranges can be combined and intermixed with lists.
For example,
# 1, 2, 3
numbers=1-3
# Multiple ranges
# 1 through 3, or 6, or 8, or 10 through 15
# 1, 2, 3, 6, 8, 10, 11, 12, 13, 14, 15
numbers=1-3 6 8 10-15
# Greater than or equal to
# 100, or 200, or 5340, or 25902, etc.
numbers=100-
# Negative number, not a range
# Only matches negative 100, not -4, -7, or -101
numbers=-100
Since 1.18 (with OptiFine H5), negative values may be specified also. When used in a range, they must be surrounded by parentheses.
To use negative numbers in a range, parentheses must be around those negative numbers.
list=(-3)-(-1)
These can be combined to create vast ranges of possible numeric values.
Range¶
Note
range: was added in 1.19.2 I1 pre1.
Ranges of numbers can also be matched by using the range: prefix. They use the same syntax as the above, except they explicitly have range:.
nbt.N=range:A-B
nbt.number=range:0-100
Lists¶
Lists are defined with a space between each number. Multiple values are listed separately, split with spaces.
Each "entry" in the list can be either a single number, or a range.
For example,
numbers=1 2 3 4 5 6
numbers=10 70 23 -6 210
numbers=(-100)-200 500 900-
Colors¶
Note
There is no support for HSL, CMYK, etc.
Color values are specified in hexadecimal RGB format, without the leading hashtag:
# White
color=ffffff
# Black
color=000000
# Red
color=ff0000
# Green
color=00ff00
# Blue
color=0000ff
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.
"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 the previous layer entirely with the current bitmap. No blending and only simple on/off transparency. |
|
Blend the two textures using this texture's alpha value. This is the most common type of blending. |
|
RGB value > 0.5 brightens the previous image, < 0.5 darkens. color is a synonym for this method. |
|
Add this texture's RGB values multiplied by alpha to the previous layer. |
|
Subtract this texture's RGB values from the previous layer. |
|
Multiply the previous RGB values by this texture's RGB values |
|
Add this texture's RGB values to the previous layer. |
|
\(RGB_{new} = (1 - RGB_{current}) * RGB_{previous}\) |
|
\(RGB_{new} = 1 - (1 - RGB_{current}) * (1 - RGB_{previous})\) |