Skip to content

Ice and Fire

BonsUnleashed edited this page Oct 7, 2026 · 5 revisions

Ice and Fire

Minecraft 1.20.1 / Forge: this page documents that build and its measurements. For the separate 170-control Minecraft 1.21.1 port, see Minecraft 1.21.1 NeoForge.

Six controls for Ice and Fire 2.1.13-1.20.1-beta-5 (mod id iceandfire). Two are world-generation fixes: the lake guard checks structures inside the generation region (a server freeze), and pixie villages read the difficulty inside it (a generation exception). Background on Generation context fixes. Four are optimizations: reference lists allocated only when used, entity tag checks that reuse their tag keys, model files found without searching every jar, and a pathfinding debug context that is prepared only at the render stages that use it. Every switch checks the code it would change against the tested build; another build is left untouched with one WARN line (see How the patches are applied).

Key Target Side Since Kind Result
iceandfire_entity_tag_keys Ice and Fire 2.1.13-1.20.1-beta-5 BOTH 1.0.30 opt 33.9 → 20.3 ns and 24 → 0 bytes per chicken check
iceandfire_lake_guard_region Ice and Fire 2.1.13-1.20.1-beta-5 BOTH 1.0.11 fix fixes a server freeze
iceandfire_lazy_reference_lists Ice and Fire 2.1.13-1.20.1-beta-5 BOTH 1.0.12 opt 84 → 56 B mixed initialise
iceandfire_path_debug_stage_gate Ice and Fire 2.1.13-1.20.1-beta-5 CLIENT 1.0.30 opt debug context prepared only at the render stages that use it
iceandfire_pixie_village_difficulty Ice and Fire 2.1.13-1.20.1-beta-5 BOTH 1.0.11 fix fixes a generation exception
iceandfire_tabula_lookup_index Ice and Fire 2.1.13-1.20.1-beta-5 CLIENT 1.0.30 opt 192 model lookups 244-327 → 10-14 ms

iceandfire_lake_guard_region

Target: Ice and Fire 2.1.13-1.20.1-beta-5 · Side: BOTH · Since: 1.0.11 (first as a patched JAR 2026-09-09) · Kind: fix Patched: com.github.alexthe666.iceandfire.mixin.gen.NoLakesInStructuresMixin.iaf_noLakesInMausoleum (Ice and Fire's own Mixin into LakeFeature.place) — 1.0.19 script bons_and_furious-NoLakesInStructuresMixin.js Mixin (since 1.0.20): LakeGuardRegionMixin

What upstream did. Ice and Fire keeps lakes out of its structures. Its lake check fetched the structure manager of the live ServerLevel even when the lake was being placed in a generation region, so every protection check could force live chunks to load on the server thread. Under Distant Horizons generation this froze the server.

What the patch does. Binds the structure manager to the supplied region with StructureManager.forWorldGenRegion, which is exactly what vanilla features do.

What stays the same. Every lake-protection check and its result. Contexts that are not a generation region take the original path.

Measured. Fixes a server freeze (Spark tcY7ssqYNr: 93.9 % of 411.6 sampled seconds in blocking chunk requests; the reproduction froze for 98 s with 11 Ice and Fire workers and then 12 Structure Gel workers blocked). With this and structure_gel_lake_guard_region applied: 3,700 ticks in 185.001 s (20 TPS), zero live-chunk waits in 60 Distant Horizons worker observations.

Since 1.0.34. A lake placed off the centre chunk of its generation region (a jigsaw lake with an offset) asks the live level as before. Looked up inside the region, such a lake could reach a structure start 9 chunks from the centre, outside the region, and stop world generation. Lakes in the centre chunk, and every lake in Distant Horizons' regions, keep the region lookup. structure_gel_lake_guard_region follows the same rule.


iceandfire_pixie_village_difficulty

Target: Ice and Fire 2.1.13-1.20.1-beta-5 · Side: BOTH · Since: 1.0.11 (first as a patched JAR 2026-09-10) · Kind: fix Patched: com.github.alexthe666.iceandfire.world.gen.WorldGenPixieVillage.place — 1.0.19 script bons_and_furious-WorldGenPixieVillage.js; helper agentcraft.iceandfire.PixieDifficultyCompat Mixin (since 1.0.20): PixieVillageDifficultyMixin

What upstream did. Pixie village placement asks the level for the local difficulty at each house. Distant Horizons supplies extra temporary chunks around a region, but the inherited vanilla WorldGenRegion.getCurrentDifficultyAt checks the base region's bounds and throws for those positions, so pixie villages failed to generate there with an exception.

What the patch does. Changes that one call site (five bytes of a 658-byte method) to PixieDifficultyCompat.get, which reads the difficulty at the region's centre when the position is outside the region.

What stays the same. Vanilla derives a region's difficulty from global values with zero inhabited time, so the result is the same at every position of the region; in-bounds positions and non-region levels make the original call.

Measured. Fixes a generation exception. 1,663 assertions under JVM verification; on an actual Distant Horizons region the vanilla out-of-bounds call throws while the helper returns the same difficulty as bracketing centre reads, and natural pixie feature calls returned through the repaired branch.


iceandfire_lazy_reference_lists

Since: 1.0.12 · Scripts (1.0.19 and earlier): furious10-chains.js (ChainData), furious10-scepters.js (MiscData) Patched: com.github.alexthe666.iceandfire.entity.props.ChainData.initialize / serialize and MiscData.initialize Mixins (since 1.0.20): ChainDataMixin, MiscDataMixin

What upstream did. The chain and scepter capability data allocated entity lists in initialize before knowing whether any saved reference resolves, and ChainData.serialize created a UUID ListTag even when chainedTo was null, a tag that was never inserted anywhere.

What the patch does. Starts with no list and allocates on the first accepted entity; moves the UUID tag construction inside the existing non-null branch.

What stays the same. Lookup order, duplicates, ID/UUID precedence, missing-reference handling, initialisation flags and the UUID path's client-update flag even when nothing resolves; the empty chainedData compound and all NBT keys and types; chains, scepter behaviour, network timing and update flags.

Measured. chain-mixed-initialize 28.05 → 24.54 ns (−12.5 %, 84 → 56 B) and chain-mixed-serialize 340.64 → 318.15 ns (−6.6 %, 1,475 → 1,412 B). Two specialised cases are slightly slower and save nothing warm: chain-empty-initialize 7.12 → 8.03 ns and chain-null-serialize 268.69 → 274.63 ns. This is a load, synchronisation and save opportunity, not an every-tick saving.


iceandfire_tabula_lookup_index

Since: 1.0.30 · Target: Ice and Fire 2.1.13-1.20.1-beta-5 · Side: CLIENT · Kind: opt

Mixin: IceAndFireTabulaLookupMixin

Ice and Fire model files found without searching every jar. While the game starts, Ice and Fire loads about 190 dragon and sea-serpent model files, and Forge finds each one by asking all ~530 jars (about 1.4 s in our own recording). Now each model folder is listed once in every jar and the lookups read those lists. Ice and Fire reads exactly the same files; jars cannot change while the game runs, and anything the lists cannot answer exactly is still asked directly.

Idea: lazyyyyy (faster Ice and Fire model loading), idea text only

Measured: offline on Forge's own class loader over this pack's 506 jars, 66,640 checks identical; the 192 model lookups 244-327 -> 10-14 ms.

Since 1.0.33. In 1.0.30 this control switched itself off at every start. The lookup index it shares with two other controls first checks the versions of two Forge libraries, and it could not read the version of one of them, so it logged game-layer resource index off and left the original lookups in place. It reads that version correctly now and the control runs.


iceandfire_entity_tag_keys

Since: 1.0.30 · Target: Ice and Fire 2.1.13-1.20.1-beta-5 · Side: BOTH (works on the server tick) · Kind: opt

Mixins: ServerEventsTagKeyMixin, DragonUtilsTagKeyMixin

Ice and Fire: entity tag checks reuse their tag keys. Ice and Fire asks "is this mob a chicken?" (its rotten-egg feature) for every mob on every server tick, and asks the same kind of question for livestock, sheep, villagers, cockatrice targets and dragon targets. Each question built a new tag key from the same fixed tag name and looked it up in a shared table of tag keys. The key made the first time is now kept and handed back. A tag key is just the tag's name, so the answers are the same, and they still follow the current tags after a /reload or a datapack change (only the key is kept, never the answer).

Measured: offline on Ice and Fire's own classes with Forge's tag manager, 120,000 checks over 400 tag reloads gave the same answers; the chicken check 33.9 -> 20.3 ns and 24 -> 0 bytes per call. Before, it was 0.4-0.8% of the server thread in our pack.


iceandfire_path_debug_stage_gate

Since: 1.0.30 · Target: Ice and Fire 2.1.13-1.20.1-beta-5 · Side: CLIENT · Kind: opt

Mixin: PathDebugStageGateMixin

Ice and Fire: the pathfinding debug context is prepared only at the render stages that use it. Ice and Fire's world-render listener handed every one of Forge's eleven render stages per frame to its pathfinding debug context, which copied seven values into its fields, pushed a pose, moved it to the camera and popped it again. Only two stages use any of it: the one that draws the debug paths and the one that ends their batch. At the other stages the call now stops right after fetching the buffer source, which is where the original starts. What is left out only reads values and writes fields that are read nowhere else before the next used stage rewrites them, and the pushed pose is popped again, so the pose stack is left exactly as before. Whenever the original would fail (no player, no or an empty pose stack) it still runs and fails at the same stage.

Measured: offline on Ice and Fire's own classes, 360 frame pairs (4,320 stage calls each way, with the buffer source made lazily, no player and an empty pose stack): the same outcome, pose stack bits, buffer source and batches, and the same context at the stages that use it; 718 -> 195 ns and 1,864 -> 496 bytes per frame (median of 7 rounds).

Bons and Furious

Minecraft 1.20.1 / Forge 1.0.35

Compatibility

Controls by mod

Links

Clone this wiki locally