Syntax

_images/icon21.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.

This page also details the rules and other resource pack-related technical information.

File name

For any file in a resource pack to be visible to the game, it must match the regular expression ^[a-z0-9_.]+$ (r101).

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.

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 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

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 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.

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

NBT

From NBT format - Minecraft Wiki:

The Named Binary Tag (NBT) is a tree data structure used by Minecraft in many save files to store arbitrary data.
The format is comprised of a handful of tags. Tags have a numeric ID, a name, and a payload.
A user-accessible version in the form of strings is the stringified Named Binary Tag (SNBT) format.

OptiFine supports conditions based on an item's NBT.

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

A value starting with an exclamation mark "!" negates the match (match the opposite of 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 a specific value: nbt.X=Y

  • Match X in range: nbt.X=range:0-100

  • Match if Y is the 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.

# 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.

Exact SNBT values may be matched by using the raw: prefix. Raw can be used to match types explicitly, such as bytes, shorts, floats, doubles, etc.

All values for raw: must match exactly as the game reports it, except that the spaces in between values must be removed.

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

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

New in version I1.

Range

Ranges of numbers can be matched by using the range: prefix. They use a simple a-b syntax:

nbt.N=range:A-B
nbt.number=range:0-100

New in version I1: pre1

Strings

This section is about matching strings and values using different matching methods.

By default, any formatting (like color or bold) is stripped out. To test specifically for the presence of this formatting, use Raw. 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+ (missing a backslash for \d)

  • nbt.display.name=regex:\\ (for matching \\\\; would match \ alone)

  • nbt.display.name=/\/\\ (missing a backslash for \/)

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.

The wildcard * is equivalent to the regular expression .* (0 or more).
The wildcard ? 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 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 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:.

A case-sensitive 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 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

Client-side data

Not all NBT tags 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 NBT 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 NBT tag visibly alters the entity, it can likely be used.

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

Numbers, ranges

Numbers can be specified simply by typing them. Additionally, you can match more than one number with lists, ranges, or both.

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

# Negative numbers in range
# -3, -2, -1
numbers=(-3)-(-1)

Since 1.18 (with OptiFine H5), negative values may also be specified. When used in a range, they must be surrounded by parentheses to prevent ambiguity.

Important

There is no range for less than or equal to; use a full range: 0-100, not -100 to match ≤100.

Lists

Lists are defined with a space between each item. An item can be any text that is not used in the NBT selection. Multiple values are listed separately, split with a space.

For example,

numbers=1 2 3 4 5 6
biomes=ocean plains flower_forest
blocks=bricks gold end_portal_frame oak_stairs:facing=west,north:half=top

A list can have only 1 element.

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

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.

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.

Item NBT can only be specified (if available) through the nbt.X=Y rules.

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 and only simple on/off transparency.

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

\(RGB_{new} = (1 - RGB_{current}) * RGB_{previous}\)

screen

\(RGB_{new} = 1 - (1 - RGB_{current}) * (1 - RGB_{previous})\)


Assumes the latest OptiFine version.
Updated to commit dc7b4aca.

Last update: 2024 March 13