The thermal rule engine determines when and how blocks transform under thermal exposure. Rules are evaluated in scripts/rules.js and executed by scripts/simulation.js.


1. Rule Architecture: Exact vs. Pattern Matching

Rules are split into two complementary collections to ensure both high lookup performance and broad coverage across block families:

  1. EXACT_RULES: A Map mapping specific block type IDs (e.g. minecraft:sand, minecraft:glass) directly to a rule object. Has $O(1)$ lookup time and highest evaluation priority.
  2. PATTERN_RULES: An array of predicate test functions evaluated sequentially if no exact match is found. Used for multi-color block groups (16 wool colors, carpets, concrete), wood types, stairs, slabs, and copper families.

Rule lookups are cached in RULE_CACHE to eliminate redundant string pattern matching during simulation cycles.


2. Rule Schema (TransformRule)

A rule object is structured as follows:

interface TransformRule {
  feature?: string;        // Feature toggle key in config.js (e.g. "glassShatter", "charWood")
  threshold: number;       // Minimum accumulated heat required to trigger transformation
  chance: number;          // Probability per cycle (0.0 to 1.0) once threshold is met
  minSourceHeat?: number;  // Minimum heat source rating required (bypassed in hard difficulty)
  result: string | string[] | ((id: string) => string | string[]); // Target block type ID(s)
  preserveState?: boolean; // Whether to preserve orientation and state attributes
  spill?: boolean;         // Whether to drop container contents onto ground prior to replacement
  sound?: string;          // Sound event ID played upon transformation
  particle?: string;       // Particle ID spawned upon transformation
  drop?: {                 // Additional item drop spawned upon transformation
    item: string;
    chance: number;
    amount?: number;
  };
}

Property Details

Property Type Description
feature string Key in CONFIG.features. If disabled via /bf:firefeature <feature> false, the rule is ignored.
threshold number Minimum heat accumulated in heatMap before evaluation occurs.
chance number Probability of triggering the transformation per cycle tick (e.g., 0.25 = 25% chance).
minSourceHeat number Minimum base heat rating of the source block. Sources below this rating cannot advance the rule (e.g., campfires cannot shatter glass or crack stone). Bypassed in hard difficulty mode.
result `string string[]
preserveState boolean If true, the transformation computes state key intersections between source and target permutations (preserving facing direction, hinges, halves, etc.).
spill boolean If true, container contents drop onto the ground as item entities before block replacement.

3. Heat Source Registries

Heat sources are categorized into base sources and hard-difficulty sources in scripts/rules.js:

Base Heat Sources (BASE_HEAT_SOURCES)

Active across all difficulty modes:

export const BASE_HEAT_SOURCES = [
  { id: "minecraft:lava", heat: 26, radius: 3, ignite: true },
  { id: "minecraft:flowing_lava", heat: 20, radius: 3, ignite: true },
  { id: "minecraft:soul_fire", heat: 26, radius: 2, ignite: true },
  { id: "minecraft:fire", heat: 18, radius: 2, ignite: true },
  { id: "minecraft:lava_cauldron", heat: 10, radius: 2, ignite: false },
  { id: "minecraft:soul_campfire", heat: 10, radius: 2, ignite: false },
  { id: "minecraft:campfire", heat: 8, radius: 2, ignite: false },
  { id: "minecraft:lit_blast_furnace", heat: 8, radius: 1, ignite: false },
  { id: "minecraft:magma", heat: 7, radius: 2, ignite: false },
  { id: "minecraft:lit_furnace", heat: 5, radius: 1, ignite: false },
  { id: "minecraft:lit_smoker", heat: 5, radius: 1, ignite: false },
];

Hard-Difficulty Heat Sources (HARD_HEAT_SOURCES)