Environment Attributes Modifiers - MehVahdJukaar/polytone GitHub Wiki

Environment Attributes

Environment attributes are a very powerful Vanilla Minecraft concept added in 1.21.11 which allow to customize many of the game parameters (called EnvironmentAttribute) through a standardized, unified and modular system that automatically supports both Spacial and Temporal Lerp of its attributes.

Polytone makes uses of this system to allow arbitrary client-sided customization of the game EnvironmentAttributes through designated fields in BiomeModifiers and DimensionModifiers.

This system is very intricate but understanding it will allow you to unlock a lot of customization option for your resource pack so bare with me. Some example are allowing customization of:

  • fog
  • sun angle
  • cloud height
  • sunset color
  • much much more

The strenght of the system is its MODULARITY, allowing different effect to be applied one ontop of the other. As a concrete example, imagine you have a certain dimension and a biome. You want the base sky color to be defined by the biome, then make it get more blue in your particular dimension only and then make it get darker when it rains ontop of that. All those effects will stack one after the other and blend automatically.

BEFORE WE START You should first be aware that there is a dedicated page on official Minecraft WIki HERE. Many of the information here will relay you as the info provided will not be exhaustive and more explanatory in nature.

Example, TLDR:

Given this page is very information dense, to show that this isn't rocket science, here's a quick example of how a Biome Modifier attribute_modifier field might look like:

"attributes_modifiers": {
    "minecraft:visual/water_fog_color": "#332211",
    "minecraft:visual/water_fog_end_distance": "REMOVE",
    "minecraft:visual/cloud_height": {
      "argument": 2.0,
      "modifier": "multiply"
    },
    "minecraft:visual/sky_color": "my_pack:swamp_sky_color",
    "minecraft:visual/sun_angle": "rand() + 0.1"
}

This modifier will target a particular biome and do the following:

  • set its water fog color to a specific value
  • remove the water_fog_end_distance attribute modification that it was otherwise applying (i.e. Swamps).
  • multiply the cloud height level by 2.
  • Assign the value gotten from our own colormap my_pack:swamp_sky_color to the sky_color at that position (See Colormaps Section)
  • Setting to a random value to sun_angle using a Math Expression (See Math Expresison Section)
  • all modifications are applied to the base layer as a Layer has not been specified. More on this below

Environment Attribute Types

As mentioned previously the system core idea is to allow customization of various ingame attributes. These are called EnvironmentAttributes.

Each attribute can represent a parameter the game uses and can be purely visual, like visual/moon_angle or have a gameplay function, like gameplay/water_evaporates.

While Polytone technically allows editing both, given the modification is client side (as opposed to what one can do by editing the Biome or Dimension .jsons definitions directly), it only makes sense to alter the client side ones.

Each attribute also has a AttributeType, this is merely the data type of the attribute, for instance boolean, rgb_color, background_music...

For a complete list of each Environment Attribute please consult the Official Wiki page linked above.

Layers

This is the core concept to understand.

Each attribute is not simply set with a static value, the system is built to allow an arbitrary amount of Layers per each EnvironmentAttribute.

Each layer can do one of 2 things:

  • Set the value of the EnvironmentAttribute
  • Modify the previously assigned value of the EnvironmentAttribute

In its most simple form you can think of a layer as an arithmetic operation on the attribute value.

Lets make this clear with an ficticious example where for simplicity we'll take the attribute visual/cloud_height that we'll call X for brevity.

  • Layer 1: X = 130
  • Layer 2: X = X + 20
  • Layer 3: X = X * 2

In this example the final value of X will thus be (128+20)*2 = 300

Layers Modularity

You might be wondering What are layers for?, since we could have achieved the same result with 1 layer X = 300. Well here's where the system shines, each layer can be applied conditionally, for instance we could have layer 2 just be on when in a Taiga biome and layer 3 be on when it rains.

Vanilla Layer Ordering

Since we'll move to modify vanilla layers soon, we first need to understand how these look like. In particular given the application order of the layers mataters its important to understand it.

The game layers are many bug can be simplified in the following groups, listed in application order. Note each group can contain between 0 or 1 layer for eachEnvironmentAttribute.

Name Can Be Changed By Content
DIMENSION LAYER GROUP Dimension Modifiers Base dimension attributes
BIOME LAYER GROUP Biome Modifiers Biome-changing attributes
DIMENSION TIMELINE GROUP Dimension timeline data
WEATHER GROUP Dimension Modifiers Weather attributes. Can either berain orthunder
BIOME POST PROCESS GROUP Biome Modifiers Empty (added by Polytone)
DIMENSION POST PROCESS GROUP Dimension Modifiers Empty (added by Polytone)

Note that usually the First layer of each AttributeType will be a SET operation (basically setting its base value). For instance the dimension group might set visual/cloud_height at 128 and then the biome layer could modify that by adding 20 to it.

Following is a list of one example for each of the EnvironmentAttributes that are part of each group.

Dimension Layer Group

These vary from dimension to domension. Example: minecraft:overworld. Only client ones are shown.

  • minecraft:audio/ambient_sounds
  • minecraft:audio/background_music
  • minecraft:visual/cloud_color
  • minecraft:visual/cloud_height
  • minecraft:visual/fog_color
  • minecraft:visual/sky_color
Biome Layer Group

These vary from biome to domension. Example: minecraft:forest. Only client ones are shown.

  • minecraft:audio/background_music
  • minecraft:visual/sky_color
Dimension Timeline Group

This one here is special and here we need to open a parenthesys. Timelines are basically like an animation, a set of keyframes. These are defined inside a dimension_type json. It's not important to know how they work since Polytone does NOT allow to edit them (yet) as we have other ways to achieve similar things like Expressions. The only thing we should know is that each timeline can control various attributes, for instance the sun_angle or sunset_color, following intricate time driven patterns.

  • minecraft:audio/firefly_bush_sounds
  • minecraft:visual/cloud_color
  • minecraft:visual/fog_color
  • minecraft:visual/cloud_color
  • minecraft:visual/moon_angle
  • minecraft:visual/sky_color
  • minecraft:visual/sky_light_color
  • minecraft:visual/sky_light_factor
  • minecraft:visual/star_angle
Weather Group

There are 2 groups for Weather. One is THUNDER and one is RAIN. The game automatically applies only the relevant one when it rains or thunder or none at all if it doesnt rain.

  • minecraft:visual/sunrise_sunset_color
  • minecraft:visual/fog_color
  • minecraft:visual/star_brightness
  • minecraft:gameplay/sky_light_level
  • minecraft:visual/cloud_color
  • minecraft:visual/sky_light_factor
  • minecraft:visual/sky_light_color
  • minecraft:visual/sky_color

Datapack Parallel

As mentioned previously these attribute layers are normally defined in 3 places: biome .json, dimension_type .json and hardcoded in the game code.

As such if you want to see exactly what is being modified by those (for instance if you want to override or remove a layer) you can consult those 2 json files. As for the code ones a brief non exaustive list will be provided down below.

Here is an example of the exact values that these have in the Dimensionminecraft:overworld (as you can see under the attribute field.

  "attributes": {
    "minecraft:audio/ambient_sounds": {
      "mood": {
        "block_search_extent": 8,
        "offset": 2.0,
        "sound": "minecraft:ambient.cave",
        "tick_delay": 6000
      }
    },
    "minecraft:audio/background_music": {
      "creative": {
        "max_delay": 24000,
        "min_delay": 12000,
        "sound": "minecraft:music.creative"
      },
      "default": {
        "max_delay": 24000,
        "min_delay": 12000,
        "sound": "minecraft:music.game"
      }
    },
    "minecraft:gameplay/bed_rule": {
      "can_set_spawn": "always",
      "can_sleep": "when_dark",
      "error_message": {
        "translate": "block.minecraft.bed.no_sleep"
      }
    },
    "minecraft:gameplay/nether_portal_spawns_piglin": true,
    "minecraft:gameplay/respawn_anchor_works": false,
    "minecraft:visual/cloud_color": "#ccffffff",
    "minecraft:visual/cloud_height": 192.33,
    "minecraft:visual/fog_color": "#c0d8ff",
    "minecraft:visual/sky_color": "#78a7ff"
  }

And here is what a Biome one looks like, in this case minecraft:swamp

  "attributes": {
    "minecraft:audio/background_music": {
      "default": {
        "max_delay": 24000,
        "min_delay": 12000,
        "sound": "minecraft:music.overworld.swamp"
      }
    },
    "minecraft:gameplay/increased_fire_burnout": true,
    "minecraft:visual/sky_color": "#78a7ff",
    "minecraft:visual/water_fog_color": "#232317",
    "minecraft:visual/water_fog_end_distance": {
      "argument": 0.85,
      "modifier": "multiply"
    }
  }

Finally here is what the hardcoded Weather Rain group would look like if it was editable in json.

{
  "minecraft:visual/sunrise_sunset_color": {
    "argument": -12632244,
    "modifier": "multiply"
  },
  "minecraft:visual/fog_color": {
    "argument": "#3f3f4c",
    "modifier": "multiply"
  },
  "minecraft:visual/star_brightness": 0.0,
  "minecraft:gameplay/sky_light_level": {
    "argument": {
      "value": 4.0,
      "alpha": 0.52734375
    },
    "modifier": "alpha_blend"
  },
  "minecraft:visual/cloud_color": {
    "argument": {
      "brightness": 0.095,
      "factor": 0.94
    },
    "modifier": "blend_to_gray"
  },
  "minecraft:visual/sky_light_factor": {
    "argument": {
      "value": 0.24,
      "alpha": 0.52734375
    },
    "modifier": "alpha_blend"
  },
  "minecraft:visual/sky_light_color": {
    "argument": "#867a7aff",
    "modifier": "alpha_blend"
  },
  "minecraft:gameplay/bees_stay_in_hive": true,
  "minecraft:visual/sky_color": {
    "argument": {
      "brightness": 0.24,
      "factor": 0.94
    },
    "modifier": "blend_to_gray"
  }
}

This syntax is very similar to what polytone will require you to use when, precisely, targeting these very files.

Attribute Modifications

Well you made it!

Here is where we'll actually see how to modify all this stuff described above.

We have 2 places to do so, BiomeModifiers and DimensionModifiers's attributes_modifiers field.

Vanilla Syntax

First lets explain how vanilla Attribute Layers syntax works. (More info on MC WIKI linked above) Inside an attributes or attributes_modifiers field you'll see a map whose keys are the EnvironmentAttributes IDs.

Their value can be one of two:

  • A static value (simple SET operation)
  • A Modifier object. Each Modifier has a argument and a modifier field (MODIFY operation)

Here is a simple example where we multiply fog color by two and set sun angle to 0.

{
  "minecraft:visual/fog_color": {
    "argument": 0.2,
    "modifier": "multiply"
  },
  "minecraft:visual/sun_angle": 0
}

There are many modifier values that can be used, each representing a different Math operation to merge argument and input (previos value). Below is a list of all their allowed values. Note that the argument value object type could change based off the operation so refer to the vanilla files for more examples. Moreover some operations only make sense with certain AttributeTypes

Allowed Operation values for modifier field
  • override
  • alpha_blend
  • add
  • subtract
  • multiply
  • blend_to_gray
  • minimum
  • maximum
  • and
  • nand
  • or
  • nor
  • xor
  • xnor

Polytone Syntax

For the most part the syntax will be VERY similar to the one explained above thats visible in Vanilla fiels with the following 3 additions

  • An Attribute Layer can have the value of REMOVED. If it does Polytone will remove the attribute layer that could be present.
  • Layers that modify an EnvironmentAttributes of the AttributeType of float or rgb_color or argb_color will be able to use not only a number but also a Math Expression as argument, allowing for very rich and contextual customization options.
  • Layers that modify an EnvironmentAttributes of the AttributeType of rgb_color or argb_color can use a Colormap as their argument or value.

Example:

{
  "minecraft:visual/sun_angle": {
    "argument": "0.2 * RAIN",
    "modifier": "override"
  },
  "minecraft:visual/cloud_height": "0.2 * RAIN",
  "minecraft:visual/fog_color": "my_pack:fog_colormap"
  "minecraft:visual/sky_color": {
    "argument": "my_pack:sky_colormap",
    "modifier": "ADD"
  },
}

Note here that since we used the override modifier types, the first 2 attribute values are essentially equal.

You might have also noticed that expressions can do all that those modifier operations do but as a single line. For instance addition. To gain access to the previous value of the attribute you can use the variable "THIS". I.e.: THIS + 3 would be equilvanet to an ADD modifier operation with argument 3. (WIP, THIS is not implemented yet)

In Biome Modifiers

This is the simplest of the two. the field content will be a simple map of attribute key to its valyes, just like the vanilla examples shown above. We have already covered all there is to know here, an example could be very well the example from right above inside the attribute_modifiers field but here's one anyways:

{
"attributes_modifiers": {
   "minecraft:visual/sky_color": 0
 }
}

Similar to dimension modifiers biome modifiers can also optionally have a post_process group. The normal attributs would then be stored in the base field. This will allow you to have easy biome-varying parameters without needing to use colormaps or complex expressions that will be able to override attributes defined in later grups like Weather or Timelines (i.e. sunset color)

In Dimension Modifiers

Tese are a bit more complicated but nothing crazy.

The main difference is that here we can target more than 1 Group at the same time. Inside attributes_modifiers we'll then find the fields:

  • base: targeting the base dimension Group
  • rain: targeting the rain weather Group
  • thunder: targeting the thunder weather Group
  • post_process: a final Group added by Polytone that will be applied after all the others. Here removals dont make sense.

Here's an example

{
  "attributes_modifiers": {
    "base": {
      "minecraft:visual/sun_angle": 0
    },
    "rain": {
      "minecraft:visual/sun_angle": {
      "argument": "0.2 * TIME",
      "modifier": "ADD"
    },
    "post_process": {
      "minecraft:visual/sky_color": -1
    }
  }
}

You can also omit the inner keys and just use the same syntax as Biome Modifiers. In that case the modifications will be applied to the base Group.

{
"attributes_modifiers": {
   "minecraft:visual/sky_color": -1
 }
}

Timelines Modifications

The before mentioned Timelines can be found and viewed in the timeline data folder. I won't paste one here since they can be very big and are not really relevant to what we are doing. Timenline modification has not yet been added as one can also do this stuff through Polytone Math Expressions by adding a Layer to your desired attribute in the post_process group in Dimension Modifiers

Timelines define many time varying values like visual/sunrise_sunset_color or visual/star_brightness. If you tried to change these with no avail in biome or dimension base group you now know why. Timeline group is applied later on! Use one of the post process groups.

Tips

Generally if you want to just edit single values you are better off adding stuff in the post_process layers. This will make sure that no other modification happen after yours, possibly overriding them.

⚠️ **GitHub.com Fallback** ⚠️