Skip to main content

steel_core/inventory/
fuel_values.rs

1//! Furnace fuel durations.
2
3use std::sync::LazyLock;
4
5use steel_registry::items::{Item, ItemRef};
6use steel_registry::vanilla_item_tags::ItemTag;
7use steel_registry::vanilla_items;
8use steel_registry::{REGISTRY, RegistryEntry as _, RegistryExt as _, TaggedRegistryExt as _};
9use steel_utils::Identifier;
10
11/// Fuel durations indexed by item registry ID.
12pub struct FuelValues {
13    burn_durations: Vec<i32>,
14}
15
16impl FuelValues {
17    /// Creates an empty table sized for the currently frozen item registry.
18    #[must_use]
19    pub fn builder() -> FuelValuesBuilder {
20        FuelValuesBuilder {
21            burn_durations: vec![0; REGISTRY.items.len()],
22        }
23    }
24
25    /// Returns whether `item` is furnace fuel.
26    #[must_use]
27    pub fn is_fuel(&self, item: ItemRef) -> bool {
28        self.burn_duration(item) > 0
29    }
30
31    /// Returns the item's burn duration in game ticks, or zero when it is not fuel.
32    #[must_use]
33    pub fn burn_duration(&self, item: ItemRef) -> i32 {
34        self.burn_durations.get(item.id()).copied().unwrap_or(0)
35    }
36}
37
38/// Mutable construction phase for [`FuelValues`].
39pub struct FuelValuesBuilder {
40    burn_durations: Vec<i32>,
41}
42
43impl FuelValuesBuilder {
44    /// Assigns one item a burn duration.
45    #[must_use]
46    pub fn add(mut self, item: ItemRef, burn_duration: i32) -> Self {
47        self.put(item, burn_duration);
48        self
49    }
50
51    /// Assigns every item in a tag a burn duration.
52    #[must_use]
53    pub fn add_tag(mut self, tag: &Identifier, burn_duration: i32) -> Self {
54        for item in REGISTRY.items.iter_tag(tag) {
55            self.put(item, burn_duration);
56        }
57        self
58    }
59
60    /// Removes every item in a tag from the table.
61    #[must_use]
62    pub fn remove_tag(mut self, tag: &Identifier) -> Self {
63        for item in REGISTRY.items.iter_tag(tag) {
64            self.put(item, 0);
65        }
66        self
67    }
68
69    /// Finishes the immutable table.
70    #[must_use]
71    pub fn build(self) -> FuelValues {
72        FuelValues {
73            burn_durations: self.burn_durations,
74        }
75    }
76
77    fn put(&mut self, item: &'static Item, burn_duration: i32) {
78        assert!(burn_duration >= 0, "fuel duration cannot be negative");
79        self.burn_durations[item.id()] = burn_duration;
80    }
81}
82
83/// Vanilla 26.2 fuel values, built from the generated item registry and tags.
84pub static VANILLA_FUEL_VALUES: LazyLock<FuelValues> = LazyLock::new(|| {
85    const BASE: i32 = 200;
86
87    FuelValues::builder()
88        .add(&vanilla_items::LAVA_BUCKET, BASE * 100)
89        .add(&vanilla_items::COAL_BLOCK, BASE * 8 * 10)
90        .add(&vanilla_items::BLAZE_ROD, BASE * 12)
91        .add(&vanilla_items::COAL, BASE * 8)
92        .add(&vanilla_items::CHARCOAL, BASE * 8)
93        .add_tag(&ItemTag::LOGS, BASE * 3 / 2)
94        .add_tag(&ItemTag::BAMBOO_BLOCKS, BASE * 3 / 2)
95        .add_tag(&ItemTag::PLANKS, BASE * 3 / 2)
96        .add(&vanilla_items::BAMBOO_MOSAIC, BASE * 3 / 2)
97        .add_tag(&ItemTag::WOODEN_STAIRS, BASE * 3 / 2)
98        .add(&vanilla_items::BAMBOO_MOSAIC_STAIRS, BASE * 3 / 2)
99        .add_tag(&ItemTag::WOODEN_SLABS, BASE * 3 / 4)
100        .add(&vanilla_items::BAMBOO_MOSAIC_SLAB, BASE * 3 / 4)
101        .add_tag(&ItemTag::WOODEN_TRAPDOORS, BASE * 3 / 2)
102        .add_tag(&ItemTag::WOODEN_PRESSURE_PLATES, BASE * 3 / 2)
103        .add_tag(&ItemTag::WOODEN_SHELVES, BASE * 3 / 2)
104        .add_tag(&ItemTag::WOODEN_FENCES, BASE * 3 / 2)
105        .add_tag(&ItemTag::FENCE_GATES, BASE * 3 / 2)
106        .add(&vanilla_items::NOTE_BLOCK, BASE * 3 / 2)
107        .add(&vanilla_items::BOOKSHELF, BASE * 3 / 2)
108        .add(&vanilla_items::CHISELED_BOOKSHELF, BASE * 3 / 2)
109        .add(&vanilla_items::LECTERN, BASE * 3 / 2)
110        .add(&vanilla_items::JUKEBOX, BASE * 3 / 2)
111        .add(&vanilla_items::CHEST, BASE * 3 / 2)
112        .add(&vanilla_items::TRAPPED_CHEST, BASE * 3 / 2)
113        .add(&vanilla_items::CRAFTING_TABLE, BASE * 3 / 2)
114        .add(&vanilla_items::DAYLIGHT_DETECTOR, BASE * 3 / 2)
115        .add_tag(&ItemTag::BANNERS, BASE * 3 / 2)
116        .add(&vanilla_items::BOW, BASE * 3 / 2)
117        .add(&vanilla_items::FISHING_ROD, BASE * 3 / 2)
118        .add(&vanilla_items::LADDER, BASE * 3 / 2)
119        .add_tag(&ItemTag::SIGNS, BASE)
120        .add_tag(&ItemTag::HANGING_SIGNS, BASE * 4)
121        .add(&vanilla_items::WOODEN_SHOVEL, BASE)
122        .add(&vanilla_items::WOODEN_SWORD, BASE)
123        .add(&vanilla_items::WOODEN_SPEAR, BASE)
124        .add(&vanilla_items::WOODEN_HOE, BASE)
125        .add(&vanilla_items::WOODEN_AXE, BASE)
126        .add(&vanilla_items::WOODEN_PICKAXE, BASE)
127        .add_tag(&ItemTag::WOODEN_DOORS, BASE)
128        .add_tag(&ItemTag::BOATS, BASE * 6)
129        .add_tag(&ItemTag::WOOL, BASE / 2)
130        .add_tag(&ItemTag::WOODEN_BUTTONS, BASE / 2)
131        .add(&vanilla_items::STICK, BASE / 2)
132        .add_tag(&ItemTag::SAPLINGS, BASE / 2)
133        .add(&vanilla_items::BOWL, BASE / 2)
134        .add_tag(&ItemTag::WOOL_CARPETS, 1 + BASE / 3)
135        .add(&vanilla_items::DRIED_KELP_BLOCK, 1 + BASE * 20)
136        .add(&vanilla_items::CROSSBOW, BASE * 3 / 2)
137        .add(&vanilla_items::BAMBOO, BASE / 4)
138        .add(&vanilla_items::DEAD_BUSH, BASE / 2)
139        .add(&vanilla_items::SHORT_DRY_GRASS, BASE / 2)
140        .add(&vanilla_items::TALL_DRY_GRASS, BASE / 2)
141        .add(&vanilla_items::SCAFFOLDING, BASE / 4)
142        .add(&vanilla_items::LOOM, BASE * 3 / 2)
143        .add(&vanilla_items::BARREL, BASE * 3 / 2)
144        .add(&vanilla_items::CARTOGRAPHY_TABLE, BASE * 3 / 2)
145        .add(&vanilla_items::FLETCHING_TABLE, BASE * 3 / 2)
146        .add(&vanilla_items::SMITHING_TABLE, BASE * 3 / 2)
147        .add(&vanilla_items::COMPOSTER, BASE * 3 / 2)
148        .add(&vanilla_items::AZALEA, BASE / 2)
149        .add(&vanilla_items::FLOWERING_AZALEA, BASE / 2)
150        .add(&vanilla_items::MANGROVE_ROOTS, BASE * 3 / 2)
151        .add(&vanilla_items::LEAF_LITTER, BASE / 2)
152        .remove_tag(&ItemTag::NON_FLAMMABLE_WOOD)
153        .build()
154});
155
156#[cfg(test)]
157mod tests {
158    use steel_registry::{init_vanilla_registry, vanilla_items};
159
160    use super::VANILLA_FUEL_VALUES;
161
162    #[test]
163    fn vanilla_fuels_respect_specific_values_and_non_flammable_wood_removal() {
164        init_vanilla_registry();
165
166        assert_eq!(
167            VANILLA_FUEL_VALUES.burn_duration(&vanilla_items::COAL),
168            1600
169        );
170        assert_eq!(
171            VANILLA_FUEL_VALUES.burn_duration(&vanilla_items::STICK),
172            100
173        );
174        assert_eq!(
175            VANILLA_FUEL_VALUES.burn_duration(&vanilla_items::CRIMSON_PLANKS),
176            0
177        );
178    }
179}