Environment Attributes Modifiers - MehVahdJukaar/polytone GitHub Wiki
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.
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_distanceattribute 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_colorto the sky_color at that position (See Colormaps Section) - Setting to a random value to
sun_angleusing aMath Expression(See Math Expresison Section) - all modifications are applied to the
baselayer as a Layer has not been specified. More on this below
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.
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
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.
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_soundsminecraft:audio/background_musicminecraft:visual/cloud_colorminecraft:visual/cloud_heightminecraft:visual/fog_colorminecraft:visual/sky_color
Biome Layer Group
These vary from biome to domension. Example: minecraft:forest. Only client ones are shown.
minecraft:audio/background_musicminecraft: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_soundsminecraft:visual/cloud_colorminecraft:visual/fog_colorminecraft:visual/cloud_colorminecraft:visual/moon_angleminecraft:visual/sky_colorminecraft:visual/sky_light_colorminecraft:visual/sky_light_factorminecraft: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_colorminecraft:visual/fog_colorminecraft:visual/star_brightnessminecraft:gameplay/sky_light_levelminecraft:visual/cloud_colorminecraft:visual/sky_light_factorminecraft:visual/sky_light_colorminecraft:visual/sky_color
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.
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.
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
Modifierobject. EachModifierhas aargumentand amodifierfield (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
overridealpha_blendaddsubtractmultiplyblend_to_grayminimummaximumandnandornorxorxnor
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 theAttributeTypeoffloatorrgb_colororargb_colorwill be able to use not only a number but also aMath Expressionasargument, allowing for very rich and contextual customization options. - Layers that modify an
EnvironmentAttributes of theAttributeTypeofrgb_colororargb_colorcan use a Colormap as theirargumentor 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)
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)
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
}
}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.
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.