Compare commits

...

15 Commits

Author SHA1 Message Date
MayaTheShy
71db1d9973 Add structured logging functionality to enhance debugging capabilities 2026-03-22 01:59:15 -04:00
MayaTheShy
0e4d184059 Add structured logging functionality to inventory manager 2026-03-22 01:59:08 -04:00
MayaTheShy
11c38dbabb Refactor monitor setup and drawing functions to utilize shared UI module 2026-03-22 01:58:13 -04:00
MayaTheShy
39b95b3663 Refactor crafting helpers to delegate functionality to shared UI module 2026-03-22 01:56:40 -04:00
MayaTheShy
8cdb2d3b98 Refactor dashboard drawing functions to use setDrawTarget for improved clarity 2026-03-22 01:56:34 -04:00
MayaTheShy
338af14b6b Refactor drawing helpers to utilize shared UI module functions 2026-03-22 01:56:15 -04:00
MayaTheShy
50fa771ca4 Refactor touch zone functions to utilize shared UI helpers 2026-03-22 01:56:07 -04:00
MayaTheShy
4dc06184de Refactor monitor setup functions to use shared UI helpers 2026-03-22 01:55:47 -04:00
MayaTheShy
1dca61eece Add shared UI helpers for inventory management and client interaction 2026-03-22 01:55:41 -04:00
MayaTheShy
c78e25deb2 Add smeltable items configuration for auto-smelting in inventory management 2026-03-22 01:55:05 -04:00
MayaTheShy
688db466ac Add fuel items configuration with burn times for inventory management 2026-03-22 01:55:00 -04:00
MayaTheShy
293dc7925b Add crafting recipes for various items in the inventory manager 2026-03-22 01:54:55 -04:00
MayaTheShy
9da5db084e Add compostable items list and trash items for inventory management 2026-03-22 01:54:51 -04:00
MayaTheShy
4b38a793c6 Add low-stock alerts configuration for inventory monitoring 2026-03-22 01:54:47 -04:00
MayaTheShy
7404e73fd3 Refactor smelting and composting logic: load data tables from external files for better maintainability 2026-03-22 01:54:44 -04:00
9 changed files with 895 additions and 853 deletions

20
data/alerts.lua Normal file
View File

@@ -0,0 +1,20 @@
-- Low-stock alerts.
-- When a tracked item drops below 'min', an alert
-- is shown on the inventory monitor.
-- Each entry: { name = "mod:item", min = N, label = "Display Name" }
return {
{ name = "minecraft:coal", min = 64, label = "Coal" },
{ name = "minecraft:charcoal", min = 64, label = "Charcoal" },
{ name = "minecraft:torch", min = 64, label = "Torches" },
{ name = "minecraft:arrow", min = 64, label = "Arrows" },
{ name = "minecraft:cooked_beef", min = 32, label = "Steak" },
{ name = "minecraft:cooked_porkchop",min = 32, label = "Porkchops" },
{ name = "minecraft:bread", min = 32, label = "Bread" },
{ name = "minecraft:iron_ingot", min = 64, label = "Iron" },
{ name = "minecraft:gold_ingot", min = 32, label = "Gold" },
{ name = "minecraft:diamond", min = 16, label = "Diamond" },
{ name = "minecraft:bone_meal", min = 32, label = "Bone Meal" },
{ name = "minecraft:oak_planks", min = 64, label = "Planks" },
{ name = "minecraft:cobblestone", min = 128, label = "Cobblestone" },
}

121
data/compostable.lua Normal file
View File

@@ -0,0 +1,121 @@
-- Compostable items (pushed into dropper, which distributes to composters via hoppers).
-- Bone meal returns through hopper.
-- Each entry is a Minecraft item ID string.
local items = {
-- Seeds & crops
"minecraft:wheat_seeds",
"minecraft:beetroot_seeds",
"minecraft:pumpkin_seeds",
"minecraft:melon_seeds",
"minecraft:torchflower_seeds",
"minecraft:pitcher_pod",
"minecraft:wheat",
"minecraft:beetroot",
"minecraft:carrot",
"minecraft:melon_slice",
"minecraft:pumpkin",
"minecraft:carved_pumpkin",
"minecraft:sweet_berries",
"minecraft:glow_berries",
-- Plant blocks
"minecraft:tall_grass",
"minecraft:short_grass",
"minecraft:fern",
"minecraft:large_fern",
"minecraft:dead_bush",
"minecraft:vine",
"minecraft:hanging_roots",
"minecraft:small_dripleaf",
"minecraft:big_dripleaf",
"minecraft:moss_block",
"minecraft:moss_carpet",
"minecraft:azalea",
"minecraft:flowering_azalea",
"minecraft:spore_blossom",
"minecraft:seagrass",
"minecraft:sea_pickle",
"minecraft:lily_pad",
"minecraft:sugar_cane",
"minecraft:kelp",
"minecraft:dried_kelp",
"minecraft:cactus",
"minecraft:nether_wart",
"minecraft:crimson_fungus",
"minecraft:warped_fungus",
"minecraft:crimson_roots",
"minecraft:warped_roots",
"minecraft:shroomlight",
"minecraft:weeping_vines",
"minecraft:twisting_vines",
-- Leaves
"minecraft:oak_leaves",
"minecraft:spruce_leaves",
"minecraft:birch_leaves",
"minecraft:jungle_leaves",
"minecraft:acacia_leaves",
"minecraft:dark_oak_leaves",
"minecraft:mangrove_leaves",
"minecraft:cherry_leaves",
"minecraft:azalea_leaves",
"minecraft:flowering_azalea_leaves",
-- Flowers
"minecraft:dandelion",
"minecraft:poppy",
"minecraft:blue_orchid",
"minecraft:allium",
"minecraft:azure_bluet",
"minecraft:red_tulip",
"minecraft:orange_tulip",
"minecraft:white_tulip",
"minecraft:pink_tulip",
"minecraft:oxeye_daisy",
"minecraft:cornflower",
"minecraft:lily_of_the_valley",
"minecraft:sunflower",
"minecraft:lilac",
"minecraft:rose_bush",
"minecraft:peony",
"minecraft:wither_rose",
"minecraft:torchflower",
"minecraft:pitcher_plant",
-- Saplings
"minecraft:oak_sapling",
"minecraft:spruce_sapling",
"minecraft:birch_sapling",
"minecraft:jungle_sapling",
"minecraft:acacia_sapling",
"minecraft:dark_oak_sapling",
"minecraft:mangrove_propagule",
"minecraft:cherry_sapling",
-- Food waste
"minecraft:rotten_flesh",
"minecraft:spider_eye",
"minecraft:poisonous_potato",
"minecraft:fermented_spider_eye",
"minecraft:apple",
"minecraft:bread",
"minecraft:cookie",
"minecraft:cake",
"minecraft:pumpkin_pie",
-- Farmer's Delight compostables
"farmersdelight:tree_bark",
"farmersdelight:straw",
"farmersdelight:canvas",
"farmersdelight:rice",
"farmersdelight:rice_panicle",
"farmersdelight:onion",
"farmersdelight:tomato",
"farmersdelight:cabbage",
"farmersdelight:cabbage_leaf",
}
-- Trash items: compostables with zero reserve (always fully composted)
local trash = {
["minecraft:rotten_flesh"] = true,
["minecraft:spider_eye"] = true,
["minecraft:poisonous_potato"] = true,
["minecraft:fermented_spider_eye"] = true,
}
return { items = items, trash = trash }

219
data/craftable.lua Normal file
View File

@@ -0,0 +1,219 @@
-- Crafting recipes (for networked crafting turtle).
-- grid: 9 entries mapping to turtle slots 1-3, 5-7, 9-11
-- Each recipe: { output = "mod:item", count = N, grid = { ... } }
return {
-- Basic materials
{
output = "minecraft:oak_planks",
count = 4,
grid = {
"minecraft:oak_log", nil, nil,
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:spruce_planks",
count = 4,
grid = {
"minecraft:spruce_log", nil, nil,
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:birch_planks",
count = 4,
grid = {
"minecraft:birch_log", nil, nil,
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:stick",
count = 4,
grid = {
"minecraft:oak_planks", nil, nil,
"minecraft:oak_planks", nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:oak_slab",
count = 6,
grid = {
"minecraft:oak_planks", "minecraft:oak_planks", "minecraft:oak_planks",
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:torch",
count = 4,
grid = {
"minecraft:coal", nil, nil,
"minecraft:stick", nil, nil,
nil, nil, nil,
},
},
-- Crafting & storage
{
output = "minecraft:crafting_table",
count = 1,
grid = {
"minecraft:oak_planks", "minecraft:oak_planks", nil,
"minecraft:oak_planks", "minecraft:oak_planks", nil,
nil, nil, nil,
},
},
{
output = "minecraft:chest",
count = 1,
grid = {
"minecraft:oak_planks", "minecraft:oak_planks", "minecraft:oak_planks",
"minecraft:oak_planks", nil, "minecraft:oak_planks",
"minecraft:oak_planks", "minecraft:oak_planks", "minecraft:oak_planks",
},
},
{
output = "minecraft:barrel",
count = 1,
grid = {
"minecraft:oak_planks", "minecraft:oak_slab", "minecraft:oak_planks",
"minecraft:oak_planks", nil, "minecraft:oak_planks",
"minecraft:oak_planks", "minecraft:oak_slab", "minecraft:oak_planks",
},
},
{
output = "minecraft:hopper",
count = 1,
grid = {
"minecraft:iron_ingot", nil, "minecraft:iron_ingot",
"minecraft:iron_ingot", "minecraft:chest", "minecraft:iron_ingot",
nil, "minecraft:iron_ingot", nil,
},
},
-- Building
{
output = "minecraft:furnace",
count = 1,
grid = {
"minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone",
"minecraft:cobblestone", nil, "minecraft:cobblestone",
"minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone",
},
},
{
output = "minecraft:ladder",
count = 3,
grid = {
"minecraft:stick", nil, "minecraft:stick",
"minecraft:stick", "minecraft:stick", "minecraft:stick",
"minecraft:stick", nil, "minecraft:stick",
},
},
{
output = "minecraft:glass_pane",
count = 16,
grid = {
"minecraft:glass", "minecraft:glass", "minecraft:glass",
"minecraft:glass", "minecraft:glass", "minecraft:glass",
nil, nil, nil,
},
},
{
output = "minecraft:iron_bars",
count = 16,
grid = {
"minecraft:iron_ingot", "minecraft:iron_ingot", "minecraft:iron_ingot",
"minecraft:iron_ingot", "minecraft:iron_ingot", "minecraft:iron_ingot",
nil, nil, nil,
},
},
-- Tools & combat
{
output = "minecraft:bucket",
count = 1,
grid = {
"minecraft:iron_ingot", nil, "minecraft:iron_ingot",
nil, "minecraft:iron_ingot", nil,
nil, nil, nil,
},
},
{
output = "minecraft:arrow",
count = 4,
grid = {
"minecraft:flint", nil, nil,
"minecraft:stick", nil, nil,
"minecraft:feather", nil, nil,
},
},
-- Redstone
{
output = "minecraft:piston",
count = 1,
grid = {
"minecraft:oak_planks", "minecraft:oak_planks", "minecraft:oak_planks",
"minecraft:cobblestone", "minecraft:iron_ingot", "minecraft:cobblestone",
"minecraft:cobblestone", "minecraft:redstone", "minecraft:cobblestone",
},
},
{
output = "minecraft:rail",
count = 16,
grid = {
"minecraft:iron_ingot", nil, "minecraft:iron_ingot",
"minecraft:iron_ingot", "minecraft:stick", "minecraft:iron_ingot",
"minecraft:iron_ingot", nil, "minecraft:iron_ingot",
},
},
{
output = "minecraft:powered_rail",
count = 6,
grid = {
"minecraft:gold_ingot", nil, "minecraft:gold_ingot",
"minecraft:gold_ingot", "minecraft:stick", "minecraft:gold_ingot",
"minecraft:gold_ingot", "minecraft:redstone", "minecraft:gold_ingot",
},
},
-- Food & misc
{
output = "minecraft:bread",
count = 1,
grid = {
"minecraft:wheat", "minecraft:wheat", "minecraft:wheat",
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:paper",
count = 3,
grid = {
"minecraft:sugar_cane", "minecraft:sugar_cane", "minecraft:sugar_cane",
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:compass",
count = 1,
grid = {
nil, "minecraft:iron_ingot", nil,
"minecraft:iron_ingot", "minecraft:redstone", "minecraft:iron_ingot",
nil, "minecraft:iron_ingot", nil,
},
},
{
output = "minecraft:clock",
count = 1,
grid = {
nil, "minecraft:gold_ingot", nil,
"minecraft:gold_ingot", "minecraft:redstone", "minecraft:gold_ingot",
nil, "minecraft:gold_ingot", nil,
},
},
}

21
data/fuel.lua Normal file
View File

@@ -0,0 +1,21 @@
-- Fuel items, ordered by preference (best first).
-- burn_time = how many items one fuel smelts.
-- Add/remove entries to change which fuels are accepted.
return {
{ name = "minecraft:coal", burn_time = 8 },
{ name = "minecraft:charcoal", burn_time = 8 },
{ name = "minecraft:coal_block", burn_time = 80 },
{ name = "minecraft:blaze_rod", burn_time = 12 },
{ name = "minecraft:dried_kelp_block", burn_time = 20 },
{ name = "minecraft:lava_bucket", burn_time = 100 },
{ name = "minecraft:oak_planks", burn_time = 1.5 },
{ name = "minecraft:spruce_planks",burn_time = 1.5 },
{ name = "minecraft:birch_planks", burn_time = 1.5 },
{ name = "minecraft:jungle_planks",burn_time = 1.5 },
{ name = "minecraft:acacia_planks",burn_time = 1.5 },
{ name = "minecraft:dark_oak_planks",burn_time = 1.5 },
{ name = "minecraft:mangrove_planks",burn_time = 1.5 },
{ name = "minecraft:cherry_planks",burn_time = 1.5 },
{ name = "minecraft:stick", burn_time = 0.5 },
}

156
data/smeltable.lua Normal file
View File

@@ -0,0 +1,156 @@
-- Smeltable items: input -> output
-- Items in chests matching a key here get auto-smelted.
-- Add/remove entries to control what gets cooked.
--
-- Each entry: ["mod:item"] = { result = "mod:output", furnaces = { ... } }
-- Valid furnace types: "minecraft:furnace", "minecraft:smoker", "minecraft:blast_furnace"
return {
-- Ores (furnace + blast furnace only)
["minecraft:raw_iron"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:raw_gold"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:raw_copper"] = { result = "minecraft:copper_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:iron_ore"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:gold_ore"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:copper_ore"] = { result = "minecraft:copper_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:deepslate_iron_ore"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:deepslate_gold_ore"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:deepslate_copper_ore"] = { result = "minecraft:copper_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:ancient_debris"] = { result = "minecraft:netherite_scrap",furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-- Sand / stone / clay (regular furnace only — blast furnace rejects these)
["minecraft:sand"] = { result = "minecraft:glass", furnaces = {"minecraft:furnace"} },
["minecraft:red_sand"] = { result = "minecraft:glass", furnaces = {"minecraft:furnace"} },
["minecraft:cobblestone"] = { result = "minecraft:stone", furnaces = {"minecraft:furnace"} },
["minecraft:stone"] = { result = "minecraft:smooth_stone", furnaces = {"minecraft:furnace"} },
["minecraft:clay_ball"] = { result = "minecraft:brick", furnaces = {"minecraft:furnace"} },
["minecraft:netherrack"] = { result = "minecraft:nether_brick", furnaces = {"minecraft:furnace"} },
["minecraft:sandstone"] = { result = "minecraft:smooth_sandstone", furnaces = {"minecraft:furnace"} },
-- Food (furnace + smoker only)
["minecraft:beef"] = { result = "minecraft:cooked_beef", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:porkchop"] = { result = "minecraft:cooked_porkchop", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:chicken"] = { result = "minecraft:cooked_chicken", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:mutton"] = { result = "minecraft:cooked_mutton", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:rabbit"] = { result = "minecraft:cooked_rabbit", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:cod"] = { result = "minecraft:cooked_cod", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:salmon"] = { result = "minecraft:cooked_salmon", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:potato"] = { result = "minecraft:baked_potato", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:kelp"] = { result = "minecraft:dried_kelp", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
-- Misc (furnace only)
["minecraft:wet_sponge"] = { result = "minecraft:sponge", furnaces = {"minecraft:furnace"} },
["minecraft:cactus"] = { result = "minecraft:green_dye", furnaces = {"minecraft:furnace"} },
["minecraft:sea_pickle"] = { result = "minecraft:lime_dye", furnaces = {"minecraft:furnace"} },
["minecraft:log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:oak_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:spruce_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:birch_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:jungle_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:acacia_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:dark_oak_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:mangrove_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:cherry_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
-------------------------------------------------
-- Mythic Metals — raw ores (furnace + blast furnace)
-------------------------------------------------
["mythicmetals:raw_adamantite"] = { result = "mythicmetals:adamantite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_aquarium"] = { result = "mythicmetals:aquarium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_banglum"] = { result = "mythicmetals:banglum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_carmot"] = { result = "mythicmetals:carmot_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_kyber"] = { result = "mythicmetals:kyber_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_manganese"] = { result = "mythicmetals:manganese_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_midas_gold"] = { result = "mythicmetals:midas_gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_mythril"] = { result = "mythicmetals:mythril_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_orichalcum"] = { result = "mythicmetals:orichalcum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_palladium"] = { result = "mythicmetals:palladium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_prometheum"] = { result = "mythicmetals:prometheum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_quadrillum"] = { result = "mythicmetals:quadrillum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_runite"] = { result = "mythicmetals:runite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_star_platinum"] = { result = "mythicmetals:star_platinum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_stormyx"] = { result = "mythicmetals:stormyx_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_tin"] = { result = "mythicmetals:tin_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_silver"] = { result = "mythicmetals:silver_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- Mythic Metals — ore blocks (furnace + blast furnace)
-------------------------------------------------
["mythicmetals:adamantite_ore"] = { result = "mythicmetals:adamantite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_adamantite_ore"] = { result = "mythicmetals:adamantite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:aquarium_ore"] = { result = "mythicmetals:aquarium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:banglum_ore"] = { result = "mythicmetals:banglum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_banglum_ore"] = { result = "mythicmetals:banglum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:nether_banglum_ore"] = { result = "mythicmetals:banglum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:carmot_ore"] = { result = "mythicmetals:carmot_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_carmot_ore"] = { result = "mythicmetals:carmot_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:kyber_ore"] = { result = "mythicmetals:kyber_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_kyber_ore"] = { result = "mythicmetals:kyber_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:manganese_ore"] = { result = "mythicmetals:manganese_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_manganese_ore"] = { result = "mythicmetals:manganese_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:midas_gold_ore"] = { result = "mythicmetals:midas_gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:mythril_ore"] = { result = "mythicmetals:mythril_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_mythril_ore"] = { result = "mythicmetals:mythril_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:orichalcum_ore"] = { result = "mythicmetals:orichalcum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_orichalcum_ore"] = { result = "mythicmetals:orichalcum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:end_stone_orichalcum_ore"] = { result = "mythicmetals:orichalcum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:palladium_ore"] = { result = "mythicmetals:palladium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:prometheum_ore"] = { result = "mythicmetals:prometheum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_prometheum_ore"] = { result = "mythicmetals:prometheum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:quadrillum_ore"] = { result = "mythicmetals:quadrillum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_quadrillum_ore"] = { result = "mythicmetals:quadrillum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:runite_ore"] = { result = "mythicmetals:runite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_runite_ore"] = { result = "mythicmetals:runite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:star_platinum_ore"] = { result = "mythicmetals:star_platinum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:end_stone_star_platinum_ore"] = { result = "mythicmetals:star_platinum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:stormyx_ore"] = { result = "mythicmetals:stormyx_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:end_stone_stormyx_ore"] = { result = "mythicmetals:stormyx_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:tin_ore"] = { result = "mythicmetals:tin_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_tin_ore"] = { result = "mythicmetals:tin_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:silver_ore"] = { result = "mythicmetals:silver_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_silver_ore"] = { result = "mythicmetals:silver_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- Ad Astra — raw ores + planetary ores (furnace + blast furnace)
-------------------------------------------------
["ad_astra:raw_desh"] = { result = "ad_astra:desh_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:raw_ostrum"] = { result = "ad_astra:ostrum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:raw_calorite"] = { result = "ad_astra:calorite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:moon_desh_ore"] = { result = "ad_astra:desh_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:deepslate_desh_ore"] = { result = "ad_astra:desh_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:mars_ostrum_ore"] = { result = "ad_astra:ostrum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:deepslate_ostrum_ore"] = { result = "ad_astra:ostrum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:venus_calorite_ore"] = { result = "ad_astra:calorite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:deepslate_calorite_ore"] = { result = "ad_astra:calorite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:moon_iron_ore"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:mars_iron_ore"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:venus_gold_ore"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:venus_diamond_ore"] = { result = "minecraft:diamond", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:mars_diamond_ore"] = { result = "minecraft:diamond", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:moon_ice_shard_ore"] = { result = "ad_astra:ice_shard", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- Create — zinc + crushed ores (furnace + blast furnace)
-------------------------------------------------
["create:raw_zinc"] = { result = "create:zinc_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:zinc_ore"] = { result = "create:zinc_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:deepslate_zinc_ore"] = { result = "create:zinc_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:crushed_raw_iron"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:crushed_raw_gold"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:crushed_raw_copper"] = { result = "minecraft:copper_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:crushed_raw_zinc"] = { result = "create:zinc_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- BetterEnd — thallasium (furnace + blast furnace)
-------------------------------------------------
["betterend:thallasium_raw"] = { result = "betterend:thallasium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["betterend:thallasium_ore"] = { result = "betterend:thallasium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- Farmer's Delight — food (furnace + smoker)
-------------------------------------------------
["farmersdelight:chicken_cuts"] = { result = "farmersdelight:cooked_chicken_cuts", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:bacon"] = { result = "farmersdelight:cooked_bacon", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:cod_slice"] = { result = "farmersdelight:cooked_cod_slice", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:salmon_slice"] = { result = "farmersdelight:cooked_salmon_slice", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:mutton_chops"] = { result = "farmersdelight:cooked_mutton_chops", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:ham"] = { result = "farmersdelight:smoked_ham", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:minced_beef"] = { result = "farmersdelight:beef_patty", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
}

View File

@@ -88,6 +88,12 @@ local CRAFTABLE = {} -- populated from master broadcast
local craftTurtleOk = false
local connected = false -- true once first state received
-------------------------------------------------
-- Shared UI helpers
-------------------------------------------------
local ui = dofile("lib/ui.lua")
-------------------------------------------------
-- UI State (local to client)
-------------------------------------------------
@@ -135,47 +141,13 @@ local smelterMonName = nil
local networkModem = nil
local function setupMonitor()
mon = peripheral.wrap(MONITOR_SIDE)
if mon and mon.setTextScale then
monName = MONITOR_SIDE
else
mon = nil
end
if not mon then
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" and name ~= SMELTER_MONITOR_SIDE then
mon = peripheral.wrap(name)
monName = name
break
end
end
end
if not mon then return false end
mon.setTextScale(0.5)
mon.clear()
return true
mon, monName = ui.setupMonitor(MONITOR_SIDE, SMELTER_MONITOR_SIDE)
return mon ~= nil
end
local function setupSmelterMonitor()
smelterMon = peripheral.wrap(SMELTER_MONITOR_SIDE)
if smelterMon and smelterMon.setTextScale then
smelterMonName = SMELTER_MONITOR_SIDE
else
smelterMon = nil
end
if not smelterMon then
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" and name ~= monName then
smelterMon = peripheral.wrap(name)
smelterMonName = name
break
end
end
end
if not smelterMon then return false end
smelterMon.setTextScale(0.5)
smelterMon.clear()
return true
smelterMon, smelterMonName = ui.setupSmelterMonitor(SMELTER_MONITOR_SIDE, monName)
return smelterMon ~= nil
end
-------------------------------------------------
@@ -183,18 +155,7 @@ end
-------------------------------------------------
local function getFilteredItems()
local filtered = {}
for _, item in ipairs(cache.itemList) do
if searchQuery == "" then
table.insert(filtered, item)
else
local lower = item.name:lower():gsub("minecraft:", ""):gsub("_", " ")
if lower:find(searchQuery:lower(), 1, true) then
table.insert(filtered, item)
end
end
end
return filtered
return ui.getFilteredItems(cache.itemList, searchQuery)
end
-------------------------------------------------
@@ -202,140 +163,69 @@ end
-------------------------------------------------
local function addZone(x1, y1, x2, y2, action, data)
table.insert(pendingZones, {
x1 = x1, y1 = y1, x2 = x2, y2 = y2,
action = action, data = data
})
ui.addZone(pendingZones, x1, y1, x2, y2, action, data)
end
local function hitTest(x, y)
for _, zone in ipairs(touchZones) do
if x >= zone.x1 and x <= zone.x2 and y >= zone.y1 and y <= zone.y2 then
return zone.action, zone.data
end
end
return nil, nil
return ui.hitTest(touchZones, x, y)
end
-------------------------------------------------
-- Crafting helpers (display-only, no peripheral calls)
-- Crafting helpers (delegated to shared ui module)
-------------------------------------------------
local function getRecipeIngredients(recipe)
local ingredients = {}
for _, item in ipairs(recipe.grid) do
if item then
ingredients[item] = (ingredients[item] or 0) + 1
end
--- Get stock total for an item from itemList
local function getItemTotal(itemName)
for _, item in ipairs(cache.itemList) do
if item.name == itemName then return item.total end
end
return ingredients
return 0
end
local function getRecipeIngredients(recipe)
return ui.getRecipeIngredients(recipe)
end
local function canCraftRecipe(recipe)
local ingredients = getRecipeIngredients(recipe)
local itemTotals = {}
for _, item in ipairs(cache.itemList) do
itemTotals[item.name] = item.total
end
for itemName, needed in pairs(ingredients) do
if (itemTotals[itemName] or 0) < needed then return false end
end
return true
return ui.canCraftRecipe(recipe, getItemTotal)
end
local function maxCraftBatches(recipe)
local ingredients = getRecipeIngredients(recipe)
local itemTotals = {}
for _, item in ipairs(cache.itemList) do
itemTotals[item.name] = item.total
end
local minBatches = math.huge
for itemName, needed in pairs(ingredients) do
local batches = math.floor((itemTotals[itemName] or 0) / needed)
if batches < minBatches then minBatches = batches end
end
if minBatches == math.huge then return 0 end
return minBatches
return ui.maxCraftBatches(recipe, getItemTotal)
end
local function getMissingIngredients(recipe)
local ingredients = getRecipeIngredients(recipe)
local itemTotals = {}
for _, item in ipairs(cache.itemList) do
itemTotals[item.name] = item.total
end
local missing = {}
for itemName, needed in pairs(ingredients) do
local have = itemTotals[itemName] or 0
if have < needed then
table.insert(missing, { name = itemName, have = have, need = needed })
end
end
return missing
return ui.getMissingIngredients(recipe, getItemTotal)
end
-------------------------------------------------
-- Touch zone helpers
-- Smelter touch zone helpers
-------------------------------------------------
local function addSmelterZone(x1, y1, x2, y2, action, data)
table.insert(smelterPendingZones, {
x1 = x1, y1 = y1, x2 = x2, y2 = y2,
action = action, data = data
})
ui.addZone(smelterPendingZones, x1, y1, x2, y2, action, data)
end
local function smelterHitTest(x, y)
for _, zone in ipairs(smelterTouchZones) do
if x >= zone.x1 and x <= zone.x2 and y >= zone.y1 and y <= zone.y2 then
return zone.action, zone.data
end
end
return nil, nil
return ui.hitTest(smelterTouchZones, x, y)
end
-------------------------------------------------
-- Drawing helpers
-- Drawing helpers (delegated to shared ui module)
-------------------------------------------------
local draw = nil
local function monWrite(x, y, text, fg, bg)
draw.setCursorPos(x, y)
if fg then draw.setTextColor(fg) end
if bg then draw.setBackgroundColor(bg) end
draw.write(text)
local function setDrawTarget(target)
draw = target
ui.draw = target
end
local function monFill(y, color)
local w, _ = draw.getSize()
draw.setCursorPos(1, y)
draw.setBackgroundColor(color)
draw.write(string.rep(" ", w))
end
local function monCenter(y, text, fg, bg)
local w, _ = draw.getSize()
local x = math.floor((w - #text) / 2) + 1
monWrite(x, y, text, fg, bg)
end
local function monBar(x, y, width, ratio, barColor, bgColor)
local filled = math.floor(ratio * width)
draw.setCursorPos(x, y)
draw.setBackgroundColor(barColor)
draw.write(string.rep(" ", filled))
draw.setBackgroundColor(bgColor)
draw.write(string.rep(" ", width - filled))
end
local function drawButton(x, y, text, fg, bg, padLeft, padRight)
padLeft = padLeft or 1
padRight = padRight or 1
local full = string.rep(" ", padLeft) .. text .. string.rep(" ", padRight)
monWrite(x, y, full, fg, bg)
return x, y, x + #full - 1, y
end
local function monWrite(x, y, text, fg, bg) ui.monWrite(x, y, text, fg, bg) end
local function monFill(y, color) ui.monFill(y, color) end
local function monCenter(y, text, fg, bg) ui.monCenter(y, text, fg, bg) end
local function monBar(x, y, w, r, bc, bgc) ui.monBar(x, y, w, r, bc, bgc) end
local function drawButton(x, y, t, fg, bg, pl, pr) return ui.drawButton(x, y, t, fg, bg, pl, pr) end
-------------------------------------------------
-- Send command to master
@@ -403,7 +293,7 @@ local function drawDashboard()
local w, h = mon.getSize()
pendingZones = {}
draw = window.create(mon, 1, 1, w, h, false)
setDrawTarget(window.create(mon, 1, 1, w, h, false))
draw.setBackgroundColor(colors.black)
draw.clear()
@@ -709,7 +599,7 @@ local function drawSmelterDashboard()
local w, h = smelterMon.getSize()
smelterPendingZones = {}
draw = window.create(smelterMon, 1, 1, w, h, false)
setDrawTarget(window.create(smelterMon, 1, 1, w, h, false))
draw.setBackgroundColor(colors.black)
draw.clear()

View File

@@ -35,6 +35,12 @@ local CRAFT_REPLY_CHANNEL = 4204
local CONFIG_FILE = ".manager_config"
local _loadedConfig = nil -- stored for deferred overrides (compost settings declared later)
-------------------------------------------------
-- Structured logging
-------------------------------------------------
local log = dofile("lib/log.lua")
local function loadConfig()
if not fs.exists(CONFIG_FILE) then return end
local f = fs.open(CONFIG_FILE, "r")
@@ -87,160 +93,16 @@ local SLOT_FUEL = 2
local SLOT_OUTPUT = 3
-------------------------------------------------
-- Smeltable items: input -> output
-- Items in chests matching a key here get auto-smelted.
-- Add/remove entries to control what gets cooked.
-- Load data tables from external files (data/)
-------------------------------------------------
local SMELTABLE = {
-- Ores (furnace + blast furnace only)
["minecraft:raw_iron"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:raw_gold"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:raw_copper"] = { result = "minecraft:copper_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:iron_ore"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:gold_ore"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:copper_ore"] = { result = "minecraft:copper_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:deepslate_iron_ore"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:deepslate_gold_ore"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:deepslate_copper_ore"] = { result = "minecraft:copper_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["minecraft:ancient_debris"] = { result = "minecraft:netherite_scrap",furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-- Sand / stone / clay (regular furnace only — blast furnace rejects these)
["minecraft:sand"] = { result = "minecraft:glass", furnaces = {"minecraft:furnace"} },
["minecraft:red_sand"] = { result = "minecraft:glass", furnaces = {"minecraft:furnace"} },
["minecraft:cobblestone"] = { result = "minecraft:stone", furnaces = {"minecraft:furnace"} },
["minecraft:stone"] = { result = "minecraft:smooth_stone", furnaces = {"minecraft:furnace"} },
["minecraft:clay_ball"] = { result = "minecraft:brick", furnaces = {"minecraft:furnace"} },
["minecraft:netherrack"] = { result = "minecraft:nether_brick", furnaces = {"minecraft:furnace"} },
["minecraft:sandstone"] = { result = "minecraft:smooth_sandstone", furnaces = {"minecraft:furnace"} },
-- Food (furnace + smoker only)
["minecraft:beef"] = { result = "minecraft:cooked_beef", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:porkchop"] = { result = "minecraft:cooked_porkchop", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:chicken"] = { result = "minecraft:cooked_chicken", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:mutton"] = { result = "minecraft:cooked_mutton", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:rabbit"] = { result = "minecraft:cooked_rabbit", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:cod"] = { result = "minecraft:cooked_cod", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:salmon"] = { result = "minecraft:cooked_salmon", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:potato"] = { result = "minecraft:baked_potato", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["minecraft:kelp"] = { result = "minecraft:dried_kelp", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
-- Misc (furnace only)
["minecraft:wet_sponge"] = { result = "minecraft:sponge", furnaces = {"minecraft:furnace"} },
["minecraft:cactus"] = { result = "minecraft:green_dye", furnaces = {"minecraft:furnace"} },
["minecraft:sea_pickle"] = { result = "minecraft:lime_dye", furnaces = {"minecraft:furnace"} },
["minecraft:log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:oak_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:spruce_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:birch_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:jungle_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:acacia_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:dark_oak_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:mangrove_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
["minecraft:cherry_log"] = { result = "minecraft:charcoal", furnaces = {"minecraft:furnace"} },
-------------------------------------------------
-- Mythic Metals — raw ores (furnace + blast furnace)
-------------------------------------------------
["mythicmetals:raw_adamantite"] = { result = "mythicmetals:adamantite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_aquarium"] = { result = "mythicmetals:aquarium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_banglum"] = { result = "mythicmetals:banglum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_carmot"] = { result = "mythicmetals:carmot_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_kyber"] = { result = "mythicmetals:kyber_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_manganese"] = { result = "mythicmetals:manganese_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_midas_gold"] = { result = "mythicmetals:midas_gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_mythril"] = { result = "mythicmetals:mythril_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_orichalcum"] = { result = "mythicmetals:orichalcum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_palladium"] = { result = "mythicmetals:palladium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_prometheum"] = { result = "mythicmetals:prometheum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_quadrillum"] = { result = "mythicmetals:quadrillum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_runite"] = { result = "mythicmetals:runite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_star_platinum"] = { result = "mythicmetals:star_platinum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_stormyx"] = { result = "mythicmetals:stormyx_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_tin"] = { result = "mythicmetals:tin_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:raw_silver"] = { result = "mythicmetals:silver_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- Mythic Metals — ore blocks (furnace + blast furnace)
-------------------------------------------------
["mythicmetals:adamantite_ore"] = { result = "mythicmetals:adamantite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_adamantite_ore"] = { result = "mythicmetals:adamantite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:aquarium_ore"] = { result = "mythicmetals:aquarium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:banglum_ore"] = { result = "mythicmetals:banglum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_banglum_ore"] = { result = "mythicmetals:banglum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:nether_banglum_ore"] = { result = "mythicmetals:banglum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:carmot_ore"] = { result = "mythicmetals:carmot_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_carmot_ore"] = { result = "mythicmetals:carmot_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:kyber_ore"] = { result = "mythicmetals:kyber_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_kyber_ore"] = { result = "mythicmetals:kyber_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:manganese_ore"] = { result = "mythicmetals:manganese_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_manganese_ore"] = { result = "mythicmetals:manganese_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:midas_gold_ore"] = { result = "mythicmetals:midas_gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:mythril_ore"] = { result = "mythicmetals:mythril_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_mythril_ore"] = { result = "mythicmetals:mythril_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:orichalcum_ore"] = { result = "mythicmetals:orichalcum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_orichalcum_ore"] = { result = "mythicmetals:orichalcum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:end_stone_orichalcum_ore"] = { result = "mythicmetals:orichalcum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:palladium_ore"] = { result = "mythicmetals:palladium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:prometheum_ore"] = { result = "mythicmetals:prometheum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_prometheum_ore"] = { result = "mythicmetals:prometheum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:quadrillum_ore"] = { result = "mythicmetals:quadrillum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_quadrillum_ore"] = { result = "mythicmetals:quadrillum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:runite_ore"] = { result = "mythicmetals:runite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_runite_ore"] = { result = "mythicmetals:runite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:star_platinum_ore"] = { result = "mythicmetals:star_platinum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:end_stone_star_platinum_ore"] = { result = "mythicmetals:star_platinum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:stormyx_ore"] = { result = "mythicmetals:stormyx_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:end_stone_stormyx_ore"] = { result = "mythicmetals:stormyx_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:tin_ore"] = { result = "mythicmetals:tin_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_tin_ore"] = { result = "mythicmetals:tin_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:silver_ore"] = { result = "mythicmetals:silver_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["mythicmetals:deepslate_silver_ore"] = { result = "mythicmetals:silver_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- Ad Astra — raw ores + planetary ores (furnace + blast furnace)
-------------------------------------------------
["ad_astra:raw_desh"] = { result = "ad_astra:desh_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:raw_ostrum"] = { result = "ad_astra:ostrum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:raw_calorite"] = { result = "ad_astra:calorite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:moon_desh_ore"] = { result = "ad_astra:desh_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:deepslate_desh_ore"] = { result = "ad_astra:desh_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:mars_ostrum_ore"] = { result = "ad_astra:ostrum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:deepslate_ostrum_ore"] = { result = "ad_astra:ostrum_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:venus_calorite_ore"] = { result = "ad_astra:calorite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:deepslate_calorite_ore"] = { result = "ad_astra:calorite_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:moon_iron_ore"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:mars_iron_ore"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:venus_gold_ore"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:venus_diamond_ore"] = { result = "minecraft:diamond", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:mars_diamond_ore"] = { result = "minecraft:diamond", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["ad_astra:moon_ice_shard_ore"] = { result = "ad_astra:ice_shard", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- Create — zinc + crushed ores (furnace + blast furnace)
-------------------------------------------------
["create:raw_zinc"] = { result = "create:zinc_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:zinc_ore"] = { result = "create:zinc_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:deepslate_zinc_ore"] = { result = "create:zinc_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:crushed_raw_iron"] = { result = "minecraft:iron_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:crushed_raw_gold"] = { result = "minecraft:gold_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:crushed_raw_copper"] = { result = "minecraft:copper_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["create:crushed_raw_zinc"] = { result = "create:zinc_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- BetterEnd — thallasium (furnace + blast furnace)
-------------------------------------------------
["betterend:thallasium_raw"] = { result = "betterend:thallasium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
["betterend:thallasium_ore"] = { result = "betterend:thallasium_ingot", furnaces = {"minecraft:furnace", "minecraft:blast_furnace"} },
-------------------------------------------------
-- Farmer's Delight — food (furnace + smoker)
-------------------------------------------------
["farmersdelight:chicken_cuts"] = { result = "farmersdelight:cooked_chicken_cuts", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:bacon"] = { result = "farmersdelight:cooked_bacon", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:cod_slice"] = { result = "farmersdelight:cooked_cod_slice", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:salmon_slice"] = { result = "farmersdelight:cooked_salmon_slice", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:mutton_chops"] = { result = "farmersdelight:cooked_mutton_chops", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:ham"] = { result = "farmersdelight:smoked_ham", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
["farmersdelight:minced_beef"] = { result = "farmersdelight:beef_patty", furnaces = {"minecraft:furnace", "minecraft:smoker"} },
}
local SMELTABLE = dofile("data/smeltable.lua")
local FUEL_LIST = dofile("data/fuel.lua")
local _compostData = dofile("data/compostable.lua")
local COMPOSTABLE = _compostData.items
local COMPOST_TRASH = _compostData.trash
local CRAFTABLE = dofile("data/craftable.lua")
local LOW_STOCK_ALERTS = dofile("data/alerts.lua")
-- Pre-build furnace compatibility sets for O(1) lookup
for _, recipe in pairs(SMELTABLE) do
@@ -251,7 +113,6 @@ for _, recipe in pairs(SMELTABLE) do
end
-- Pre-built smelt candidate lists per furnace type (sorted: food first, then alpha)
-- Avoids rebuilding & re-sorting in autoSmelt on every cycle.
local smeltCandidatesByType = {}
do
for _, ftype in ipairs(FURNACE_TYPES) do
@@ -271,412 +132,33 @@ do
end
end
-- Fuel items, ordered by preference (best first)
-- burn_time = how many items one fuel smelts
local FUEL_LIST = {
{ name = "minecraft:coal", burn_time = 8 },
{ name = "minecraft:charcoal", burn_time = 8 },
{ name = "minecraft:coal_block", burn_time = 80 },
{ name = "minecraft:blaze_rod", burn_time = 12 },
{ name = "minecraft:dried_kelp_block", burn_time = 20 },
{ name = "minecraft:lava_bucket", burn_time = 100 },
{ name = "minecraft:oak_planks", burn_time = 1.5 },
{ name = "minecraft:spruce_planks",burn_time = 1.5 },
{ name = "minecraft:birch_planks", burn_time = 1.5 },
{ name = "minecraft:jungle_planks",burn_time = 1.5 },
{ name = "minecraft:acacia_planks",burn_time = 1.5 },
{ name = "minecraft:dark_oak_planks",burn_time = 1.5 },
{ name = "minecraft:mangrove_planks",burn_time = 1.5 },
{ name = "minecraft:cherry_planks",burn_time = 1.5 },
{ name = "minecraft:stick", burn_time = 0.5 },
}
-- Build a set for quick lookup
-- Build fuel set for quick lookup
local FUEL_SET = {}
for _, f in ipairs(FUEL_LIST) do FUEL_SET[f.name] = true end
-------------------------------------------------
-- Compostable items (pushed into dropper_10,
-- which distributes to composters via hoppers).
-- Bone meal returns through hopper_0.
-------------------------------------------------
local COMPOSTABLE = {
-- Seeds & crops
"minecraft:wheat_seeds",
"minecraft:beetroot_seeds",
"minecraft:pumpkin_seeds",
"minecraft:melon_seeds",
"minecraft:torchflower_seeds",
"minecraft:pitcher_pod",
"minecraft:wheat",
"minecraft:beetroot",
"minecraft:carrot",
"minecraft:melon_slice",
"minecraft:pumpkin",
"minecraft:carved_pumpkin",
"minecraft:sweet_berries",
"minecraft:glow_berries",
-- Plant blocks
"minecraft:tall_grass",
"minecraft:short_grass",
"minecraft:fern",
"minecraft:large_fern",
"minecraft:dead_bush",
"minecraft:vine",
"minecraft:hanging_roots",
"minecraft:small_dripleaf",
"minecraft:big_dripleaf",
"minecraft:moss_block",
"minecraft:moss_carpet",
"minecraft:azalea",
"minecraft:flowering_azalea",
"minecraft:spore_blossom",
"minecraft:seagrass",
"minecraft:sea_pickle",
"minecraft:lily_pad",
"minecraft:sugar_cane",
"minecraft:kelp",
"minecraft:dried_kelp",
"minecraft:cactus",
"minecraft:nether_wart",
"minecraft:crimson_fungus",
"minecraft:warped_fungus",
"minecraft:crimson_roots",
"minecraft:warped_roots",
"minecraft:shroomlight",
"minecraft:weeping_vines",
"minecraft:twisting_vines",
-- Leaves
"minecraft:oak_leaves",
"minecraft:spruce_leaves",
"minecraft:birch_leaves",
"minecraft:jungle_leaves",
"minecraft:acacia_leaves",
"minecraft:dark_oak_leaves",
"minecraft:mangrove_leaves",
"minecraft:cherry_leaves",
"minecraft:azalea_leaves",
"minecraft:flowering_azalea_leaves",
-- Flowers
"minecraft:dandelion",
"minecraft:poppy",
"minecraft:blue_orchid",
"minecraft:allium",
"minecraft:azure_bluet",
"minecraft:red_tulip",
"minecraft:orange_tulip",
"minecraft:white_tulip",
"minecraft:pink_tulip",
"minecraft:oxeye_daisy",
"minecraft:cornflower",
"minecraft:lily_of_the_valley",
"minecraft:sunflower",
"minecraft:lilac",
"minecraft:rose_bush",
"minecraft:peony",
"minecraft:wither_rose",
"minecraft:torchflower",
"minecraft:pitcher_plant",
-- Saplings
"minecraft:oak_sapling",
"minecraft:spruce_sapling",
"minecraft:birch_sapling",
"minecraft:jungle_sapling",
"minecraft:acacia_sapling",
"minecraft:dark_oak_sapling",
"minecraft:mangrove_propagule",
"minecraft:cherry_sapling",
-- Food waste
"minecraft:rotten_flesh",
"minecraft:spider_eye",
"minecraft:poisonous_potato",
"minecraft:fermented_spider_eye",
"minecraft:apple",
"minecraft:bread",
"minecraft:cookie",
"minecraft:cake",
"minecraft:pumpkin_pie",
-- Farmer's Delight compostables
"farmersdelight:tree_bark",
"farmersdelight:straw",
"farmersdelight:canvas",
"farmersdelight:rice",
"farmersdelight:rice_panicle",
"farmersdelight:onion",
"farmersdelight:tomato",
"farmersdelight:cabbage",
"farmersdelight:cabbage_leaf",
}
-- Build set for quick lookup
-- Build compostable set for quick lookup
local COMPOSTABLE_SET = {}
for _, name in ipairs(COMPOSTABLE) do COMPOSTABLE_SET[name] = true end
-- Reserve: keep at least this many of each compostable before composting the rest
-- Compost settings (overridable via config)
local COMPOST_RESERVE = 128 -- 2 stacks
local COMPOST_DROPPER = "minecraft:dropper_10"
local COMPOST_HOPPER = "minecraft:hopper_0"
-- Apply config overrides for compost settings (loaded earlier)
if _loadedConfig then
if _loadedConfig.compostReserve then COMPOST_RESERVE = _loadedConfig.compostReserve end
if _loadedConfig.compostDropper then COMPOST_DROPPER = _loadedConfig.compostDropper end
if _loadedConfig.compostHopper then COMPOST_HOPPER = _loadedConfig.compostHopper end
end
-- Trash items: compostables with zero reserve (always fully composted)
local COMPOST_TRASH = {
["minecraft:rotten_flesh"] = true,
["minecraft:spider_eye"] = true,
["minecraft:poisonous_potato"] = true,
["minecraft:fermented_spider_eye"] = true,
}
-------------------------------------------------
-- Crafting recipes (for networked crafting turtle)
-- grid: 9 entries mapping to turtle slots 1-3, 5-7, 9-11
-------------------------------------------------
-- Crafting grid-to-slot mapping
local GRID_TO_SLOT = {1, 2, 3, 5, 6, 7, 9, 10, 11}
local CRAFTABLE = {
-- Basic materials
{
output = "minecraft:oak_planks",
count = 4,
grid = {
"minecraft:oak_log", nil, nil,
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:spruce_planks",
count = 4,
grid = {
"minecraft:spruce_log", nil, nil,
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:birch_planks",
count = 4,
grid = {
"minecraft:birch_log", nil, nil,
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:stick",
count = 4,
grid = {
"minecraft:oak_planks", nil, nil,
"minecraft:oak_planks", nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:oak_slab",
count = 6,
grid = {
"minecraft:oak_planks", "minecraft:oak_planks", "minecraft:oak_planks",
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:torch",
count = 4,
grid = {
"minecraft:coal", nil, nil,
"minecraft:stick", nil, nil,
nil, nil, nil,
},
},
-- Crafting & storage
{
output = "minecraft:crafting_table",
count = 1,
grid = {
"minecraft:oak_planks", "minecraft:oak_planks", nil,
"minecraft:oak_planks", "minecraft:oak_planks", nil,
nil, nil, nil,
},
},
{
output = "minecraft:chest",
count = 1,
grid = {
"minecraft:oak_planks", "minecraft:oak_planks", "minecraft:oak_planks",
"minecraft:oak_planks", nil, "minecraft:oak_planks",
"minecraft:oak_planks", "minecraft:oak_planks", "minecraft:oak_planks",
},
},
{
output = "minecraft:barrel",
count = 1,
grid = {
"minecraft:oak_planks", "minecraft:oak_slab", "minecraft:oak_planks",
"minecraft:oak_planks", nil, "minecraft:oak_planks",
"minecraft:oak_planks", "minecraft:oak_slab", "minecraft:oak_planks",
},
},
{
output = "minecraft:hopper",
count = 1,
grid = {
"minecraft:iron_ingot", nil, "minecraft:iron_ingot",
"minecraft:iron_ingot", "minecraft:chest", "minecraft:iron_ingot",
nil, "minecraft:iron_ingot", nil,
},
},
-- Building
{
output = "minecraft:furnace",
count = 1,
grid = {
"minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone",
"minecraft:cobblestone", nil, "minecraft:cobblestone",
"minecraft:cobblestone", "minecraft:cobblestone", "minecraft:cobblestone",
},
},
{
output = "minecraft:ladder",
count = 3,
grid = {
"minecraft:stick", nil, "minecraft:stick",
"minecraft:stick", "minecraft:stick", "minecraft:stick",
"minecraft:stick", nil, "minecraft:stick",
},
},
{
output = "minecraft:glass_pane",
count = 16,
grid = {
"minecraft:glass", "minecraft:glass", "minecraft:glass",
"minecraft:glass", "minecraft:glass", "minecraft:glass",
nil, nil, nil,
},
},
{
output = "minecraft:iron_bars",
count = 16,
grid = {
"minecraft:iron_ingot", "minecraft:iron_ingot", "minecraft:iron_ingot",
"minecraft:iron_ingot", "minecraft:iron_ingot", "minecraft:iron_ingot",
nil, nil, nil,
},
},
-- Tools & combat
{
output = "minecraft:bucket",
count = 1,
grid = {
"minecraft:iron_ingot", nil, "minecraft:iron_ingot",
nil, "minecraft:iron_ingot", nil,
nil, nil, nil,
},
},
{
output = "minecraft:arrow",
count = 4,
grid = {
"minecraft:flint", nil, nil,
"minecraft:stick", nil, nil,
"minecraft:feather", nil, nil,
},
},
-- Redstone
{
output = "minecraft:piston",
count = 1,
grid = {
"minecraft:oak_planks", "minecraft:oak_planks", "minecraft:oak_planks",
"minecraft:cobblestone", "minecraft:iron_ingot", "minecraft:cobblestone",
"minecraft:cobblestone", "minecraft:redstone", "minecraft:cobblestone",
},
},
{
output = "minecraft:rail",
count = 16,
grid = {
"minecraft:iron_ingot", nil, "minecraft:iron_ingot",
"minecraft:iron_ingot", "minecraft:stick", "minecraft:iron_ingot",
"minecraft:iron_ingot", nil, "minecraft:iron_ingot",
},
},
{
output = "minecraft:powered_rail",
count = 6,
grid = {
"minecraft:gold_ingot", nil, "minecraft:gold_ingot",
"minecraft:gold_ingot", "minecraft:stick", "minecraft:gold_ingot",
"minecraft:gold_ingot", "minecraft:redstone", "minecraft:gold_ingot",
},
},
-- Food & misc
{
output = "minecraft:bread",
count = 1,
grid = {
"minecraft:wheat", "minecraft:wheat", "minecraft:wheat",
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:paper",
count = 3,
grid = {
"minecraft:sugar_cane", "minecraft:sugar_cane", "minecraft:sugar_cane",
nil, nil, nil,
nil, nil, nil,
},
},
{
output = "minecraft:compass",
count = 1,
grid = {
nil, "minecraft:iron_ingot", nil,
"minecraft:iron_ingot", "minecraft:redstone", "minecraft:iron_ingot",
nil, "minecraft:iron_ingot", nil,
},
},
{
output = "minecraft:clock",
count = 1,
grid = {
nil, "minecraft:gold_ingot", nil,
"minecraft:gold_ingot", "minecraft:redstone", "minecraft:gold_ingot",
nil, "minecraft:gold_ingot", nil,
},
},
}
-------------------------------------------------
-- Low-stock alerts
-- When a tracked item drops below 'min', an alert
-- is shown on the inventory monitor.
-- Shared UI helpers (drawing, zones, craft math)
-------------------------------------------------
local LOW_STOCK_ALERTS = {
{ name = "minecraft:coal", min = 64, label = "Coal" },
{ name = "minecraft:charcoal", min = 64, label = "Charcoal" },
{ name = "minecraft:torch", min = 64, label = "Torches" },
{ name = "minecraft:arrow", min = 64, label = "Arrows" },
{ name = "minecraft:cooked_beef", min = 32, label = "Steak" },
{ name = "minecraft:cooked_porkchop",min = 32, label = "Porkchops" },
{ name = "minecraft:bread", min = 32, label = "Bread" },
{ name = "minecraft:iron_ingot", min = 64, label = "Iron" },
{ name = "minecraft:gold_ingot", min = 32, label = "Gold" },
{ name = "minecraft:diamond", min = 16, label = "Diamond" },
{ name = "minecraft:bone_meal", min = 32, label = "Bone Meal" },
{ name = "minecraft:oak_planks", min = 64, label = "Planks" },
{ name = "minecraft:cobblestone", min = 128, label = "Cobblestone" },
}
local ui = dofile("lib/ui.lua")
-- Active alerts (populated by checkAlerts)
local activeAlerts = {}
@@ -1110,49 +592,13 @@ local networkModemName = nil
local craftTurtleName = nil
local function setupMonitor()
mon = peripheral.wrap(MONITOR_SIDE)
if mon and mon.setTextScale then
monName = MONITOR_SIDE
else
mon = nil
end
if not mon then
-- Search for a monitor on the network (skip smelter side)
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" and name ~= SMELTER_MONITOR_SIDE then
mon = peripheral.wrap(name)
monName = name
break
end
end
end
if not mon then return false end
mon.setTextScale(0.5)
mon.clear()
return true
mon, monName = ui.setupMonitor(MONITOR_SIDE, SMELTER_MONITOR_SIDE)
return mon ~= nil
end
local function setupSmelterMonitor()
smelterMon = peripheral.wrap(SMELTER_MONITOR_SIDE)
if smelterMon and smelterMon.setTextScale then
smelterMonName = SMELTER_MONITOR_SIDE
else
smelterMon = nil
end
if not smelterMon then
-- Search for a second monitor on the network
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" and name ~= monName then
smelterMon = peripheral.wrap(name)
smelterMonName = name
break
end
end
end
if not smelterMon then return false end
smelterMon.setTextScale(0.5)
smelterMon.clear()
return true
smelterMon, smelterMonName = ui.setupSmelterMonitor(SMELTER_MONITOR_SIDE, monName)
return smelterMon ~= nil
end
-------------------------------------------------
@@ -1219,94 +665,41 @@ end
-- Get items filtered by search query
local function getFilteredItems()
ensureItemList()
local filtered = {}
for _, item in ipairs(cache.itemList) do
if searchQuery == "" then
table.insert(filtered, item)
else
local lower = item.name:lower():gsub("minecraft:", ""):gsub("_", " ")
if lower:find(searchQuery:lower(), 1, true) then
table.insert(filtered, item)
end
end
end
return filtered
return ui.getFilteredItems(cache.itemList, searchQuery)
end
local function addZone(x1, y1, x2, y2, action, data)
table.insert(pendingZones, {
x1 = x1, y1 = y1, x2 = x2, y2 = y2,
action = action, data = data
})
ui.addZone(pendingZones, x1, y1, x2, y2, action, data)
end
local function hitTest(x, y)
for _, zone in ipairs(touchZones) do
if x >= zone.x1 and x <= zone.x2 and y >= zone.y1 and y <= zone.y2 then
return zone.action, zone.data
end
end
return nil, nil
return ui.hitTest(touchZones, x, y)
end
local function addSmelterZone(x1, y1, x2, y2, action, data)
table.insert(smelterPendingZones, {
x1 = x1, y1 = y1, x2 = x2, y2 = y2,
action = action, data = data
})
ui.addZone(smelterPendingZones, x1, y1, x2, y2, action, data)
end
local function smelterHitTest(x, y)
for _, zone in ipairs(smelterTouchZones) do
if x >= zone.x1 and x <= zone.x2 and y >= zone.y1 and y <= zone.y2 then
return zone.action, zone.data
end
end
return nil, nil
return ui.hitTest(smelterTouchZones, x, y)
end
-------------------------------------------------
-- Drawing helpers (write to draw target)
-- Drawing helpers (delegated to shared ui module)
-------------------------------------------------
local draw = nil
local draw = nil -- set to window target before each draw cycle
local function monWrite(x, y, text, fg, bg)
draw.setCursorPos(x, y)
if fg then draw.setTextColor(fg) end
if bg then draw.setBackgroundColor(bg) end
draw.write(text)
local function setDrawTarget(target)
draw = target
ui.draw = target
end
local function monFill(y, color)
local w, _ = draw.getSize()
draw.setCursorPos(1, y)
draw.setBackgroundColor(color)
draw.write(string.rep(" ", w))
end
local function monCenter(y, text, fg, bg)
local w, _ = draw.getSize()
local x = math.floor((w - #text) / 2) + 1
monWrite(x, y, text, fg, bg)
end
local function monBar(x, y, width, ratio, barColor, bgColor)
local filled = math.floor(ratio * width)
draw.setCursorPos(x, y)
draw.setBackgroundColor(barColor)
draw.write(string.rep(" ", filled))
draw.setBackgroundColor(bgColor)
draw.write(string.rep(" ", width - filled))
end
local function drawButton(x, y, text, fg, bg, padLeft, padRight)
padLeft = padLeft or 1
padRight = padRight or 1
local full = string.rep(" ", padLeft) .. text .. string.rep(" ", padRight)
monWrite(x, y, full, fg, bg)
return x, y, x + #full - 1, y
end
local function monWrite(x, y, text, fg, bg) ui.monWrite(x, y, text, fg, bg) end
local function monFill(y, color) ui.monFill(y, color) end
local function monCenter(y, text, fg, bg) ui.monCenter(y, text, fg, bg) end
local function monBar(x, y, w, r, bc, bgc) ui.monBar(x, y, w, r, bc, bgc) end
local function drawButton(x, y, t, fg, bg, pl, pr) return ui.drawButton(x, y, t, fg, bg, pl, pr) end
-------------------------------------------------
-- Dashboard (reads ONLY from cache — no peripheral calls — instant)
@@ -1319,7 +712,7 @@ local function drawDashboard()
pendingZones = {}
-- Offscreen buffer
draw = window.create(mon, 1, 1, w, h, false)
setDrawTarget(window.create(mon, 1, 1, w, h, false))
draw.setBackgroundColor(colors.black)
draw.clear()
@@ -1620,73 +1013,34 @@ local function drawDashboard()
end
-------------------------------------------------
-- Crafting helpers
-- Crafting helpers (delegated to shared ui module)
-------------------------------------------------
--- Get ingredient counts from a recipe's grid
--- Get stock total for an item from catalogue
local function getItemTotal(itemName)
local have = 0
if cache.catalogue[itemName] then
for _, src in ipairs(cache.catalogue[itemName]) do
have = have + src.total
end
end
return have
end
local function getRecipeIngredients(recipe)
local ingredients = {}
for _, item in ipairs(recipe.grid) do
if item then
ingredients[item] = (ingredients[item] or 0) + 1
end
end
return ingredients
return ui.getRecipeIngredients(recipe)
end
--- Check if a recipe can be crafted with current stock
local function canCraftRecipe(recipe)
local ingredients = getRecipeIngredients(recipe)
for itemName, needed in pairs(ingredients) do
local have = 0
if cache.catalogue[itemName] then
for _, src in ipairs(cache.catalogue[itemName]) do
have = have + src.total
end
end
if have < needed then return false end
end
return true
return ui.canCraftRecipe(recipe, getItemTotal)
end
--- How many times a recipe can be crafted
local function maxCraftBatches(recipe)
local ingredients = getRecipeIngredients(recipe)
local minBatches = math.huge
for itemName, needed in pairs(ingredients) do
local have = 0
if cache.catalogue[itemName] then
for _, src in ipairs(cache.catalogue[itemName]) do
have = have + src.total
end
end
local batches = math.floor(have / needed)
if batches < minBatches then minBatches = batches end
end
if minBatches == math.huge then return 0 end
return minBatches
return ui.maxCraftBatches(recipe, getItemTotal)
end
--- Get list of missing ingredients for a recipe
local function getMissingIngredients(recipe)
local ingredients = getRecipeIngredients(recipe)
local missing = {}
for itemName, needed in pairs(ingredients) do
local have = 0
if cache.catalogue[itemName] then
for _, src in ipairs(cache.catalogue[itemName]) do
have = have + src.total
end
end
if have < needed then
table.insert(missing, {
name = itemName,
have = have,
need = needed,
})
end
end
return missing
return ui.getMissingIngredients(recipe, getItemTotal)
end
--- Execute a craft via the networked turtle.
@@ -1886,7 +1240,7 @@ local function drawSmelterDashboard()
smelterPendingZones = {}
-- Offscreen buffer
draw = window.create(smelterMon, 1, 1, w, h, false)
setDrawTarget(window.create(smelterMon, 1, 1, w, h, false))
draw.setBackgroundColor(colors.black)
draw.clear()

45
lib/log.lua Normal file
View File

@@ -0,0 +1,45 @@
-- lib/log.lua — Structured logging for CC:Tweaked programs
-- Usage:
-- local log = dofile("lib/log.lua")
-- log.info("SMELT", "Loaded %d recipes", count)
-- log.warn("NET", "No modem found")
-- log.setLevel("DEBUG") -- show everything
--
-- Levels: DEBUG < INFO < WARN < ERROR
-- Default level: INFO (suppresses DEBUG)
local LEVELS = { DEBUG = 1, INFO = 2, WARN = 3, ERROR = 4 }
local minLevel = LEVELS.INFO
local log = {}
--- Set minimum log level (string: "DEBUG", "INFO", "WARN", "ERROR")
function log.setLevel(level)
minLevel = LEVELS[level] or LEVELS.INFO
end
--- Get the current minimum level name
function log.getLevel()
for name, val in pairs(LEVELS) do
if val == minLevel then return name end
end
return "INFO"
end
local function emit(levelName, tag, msg, ...)
if LEVELS[levelName] < minLevel then return end
local text
if select("#", ...) > 0 then
text = string.format(msg, ...)
else
text = msg
end
print(string.format("[%s][%s] %s", levelName, tag, text))
end
function log.debug(tag, msg, ...) emit("DEBUG", tag, msg, ...) end
function log.info(tag, msg, ...) emit("INFO", tag, msg, ...) end
function log.warn(tag, msg, ...) emit("WARN", tag, msg, ...) end
function log.error(tag, msg, ...) emit("ERROR", tag, msg, ...) end
return log

216
lib/ui.lua Normal file
View File

@@ -0,0 +1,216 @@
-- lib/ui.lua — Shared UI helpers for manager & client
-- Usage: local ui = dofile("lib/ui.lua")
--
-- Set ui.draw to the current render target (window/monitor)
-- before calling any drawing functions.
local ui = {}
-------------------------------------------------
-- Drawing target — set this before drawing
-------------------------------------------------
ui.draw = nil
-------------------------------------------------
-- Drawing primitives
-------------------------------------------------
function ui.monWrite(x, y, text, fg, bg)
ui.draw.setCursorPos(x, y)
if fg then ui.draw.setTextColor(fg) end
if bg then ui.draw.setBackgroundColor(bg) end
ui.draw.write(text)
end
function ui.monFill(y, color)
local w, _ = ui.draw.getSize()
ui.draw.setCursorPos(1, y)
ui.draw.setBackgroundColor(color)
ui.draw.write(string.rep(" ", w))
end
function ui.monCenter(y, text, fg, bg)
local w, _ = ui.draw.getSize()
local x = math.floor((w - #text) / 2) + 1
ui.monWrite(x, y, text, fg, bg)
end
function ui.monBar(x, y, width, ratio, barColor, bgColor)
local filled = math.floor(ratio * width)
ui.draw.setCursorPos(x, y)
ui.draw.setBackgroundColor(barColor)
ui.draw.write(string.rep(" ", filled))
ui.draw.setBackgroundColor(bgColor)
ui.draw.write(string.rep(" ", width - filled))
end
function ui.drawButton(x, y, text, fg, bg, padLeft, padRight)
padLeft = padLeft or 1
padRight = padRight or 1
local full = string.rep(" ", padLeft) .. text .. string.rep(" ", padRight)
ui.monWrite(x, y, full, fg, bg)
return x, y, x + #full - 1, y
end
-------------------------------------------------
-- Touch zone management
-------------------------------------------------
--- Append a clickable zone to a pending-zone list.
-- @param zones table — the pending zone array to append to
function ui.addZone(zones, x1, y1, x2, y2, action, data)
table.insert(zones, {
x1 = x1, y1 = y1, x2 = x2, y2 = y2,
action = action, data = data,
})
end
--- Find which zone was hit.
-- @param zones table — the active zone array to search
function ui.hitTest(zones, x, y)
for _, zone in ipairs(zones) do
if x >= zone.x1 and x <= zone.x2 and y >= zone.y1 and y <= zone.y2 then
return zone.action, zone.data
end
end
return nil, nil
end
-------------------------------------------------
-- Monitor setup
-------------------------------------------------
--- Wrap and configure the main inventory monitor.
-- @param side string — preferred peripheral side/name
-- @param excludeSide string — side to skip (e.g. smelter monitor)
-- @return mon, monName or nil, nil
function ui.setupMonitor(side, excludeSide)
local mon = peripheral.wrap(side)
local monName
if mon and mon.setTextScale then
monName = side
else
mon = nil
end
if not mon then
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" and name ~= excludeSide then
mon = peripheral.wrap(name)
monName = name
break
end
end
end
if not mon then return nil, nil end
mon.setTextScale(0.5)
mon.clear()
return mon, monName
end
--- Wrap and configure the smelter monitor.
-- @param side string — preferred peripheral side/name
-- @param excludeName string — main monitor name to skip
-- @return smelterMon, smelterMonName or nil, nil
function ui.setupSmelterMonitor(side, excludeName)
local smelterMon = peripheral.wrap(side)
local smelterMonName
if smelterMon and smelterMon.setTextScale then
smelterMonName = side
else
smelterMon = nil
end
if not smelterMon then
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "monitor" and name ~= excludeName then
smelterMon = peripheral.wrap(name)
smelterMonName = name
break
end
end
end
if not smelterMon then return nil, nil end
smelterMon.setTextScale(0.5)
smelterMon.clear()
return smelterMon, smelterMonName
end
-------------------------------------------------
-- Item filtering
-------------------------------------------------
--- Filter an item list by search query.
-- @param itemList table — array of { name, total }
-- @param searchQuery string — filter text (case-insensitive, plain match)
-- @return filtered table — matching subset
function ui.getFilteredItems(itemList, searchQuery)
local filtered = {}
for _, item in ipairs(itemList) do
if searchQuery == "" then
table.insert(filtered, item)
else
local lower = item.name:lower():gsub("minecraft:", ""):gsub("_", " ")
if lower:find(searchQuery:lower(), 1, true) then
table.insert(filtered, item)
end
end
end
return filtered
end
-------------------------------------------------
-- Crafting recipe helpers
-------------------------------------------------
--- Count ingredients needed for one craft.
function ui.getRecipeIngredients(recipe)
local ingredients = {}
for _, item in ipairs(recipe.grid) do
if item then
ingredients[item] = (ingredients[item] or 0) + 1
end
end
return ingredients
end
--- Check if a recipe can be crafted with current stock.
-- @param recipe table — recipe with .grid
-- @param getTotal function(itemName) -> number — returns stock count
function ui.canCraftRecipe(recipe, getTotal)
local ingredients = ui.getRecipeIngredients(recipe)
for itemName, needed in pairs(ingredients) do
if (getTotal(itemName) or 0) < needed then return false end
end
return true
end
--- How many batches can be crafted.
-- @param recipe table — recipe with .grid
-- @param getTotal function(itemName) -> number
function ui.maxCraftBatches(recipe, getTotal)
local ingredients = ui.getRecipeIngredients(recipe)
local minBatches = math.huge
for itemName, needed in pairs(ingredients) do
local batches = math.floor((getTotal(itemName) or 0) / needed)
if batches < minBatches then minBatches = batches end
end
if minBatches == math.huge then return 0 end
return minBatches
end
--- Get list of ingredients where stock < needed.
-- @param recipe table — recipe with .grid
-- @param getTotal function(itemName) -> number
function ui.getMissingIngredients(recipe, getTotal)
local ingredients = ui.getRecipeIngredients(recipe)
local missing = {}
for itemName, needed in pairs(ingredients) do
local have = getTotal(itemName) or 0
if have < needed then
table.insert(missing, { name = itemName, have = have, need = needed })
end
end
return missing
end
return ui