Compare commits
15 Commits
d80b0b155e
...
71db1d9973
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71db1d9973 | ||
|
|
0e4d184059 | ||
|
|
11c38dbabb | ||
|
|
39b95b3663 | ||
|
|
8cdb2d3b98 | ||
|
|
338af14b6b | ||
|
|
50fa771ca4 | ||
|
|
4dc06184de | ||
|
|
1dca61eece | ||
|
|
c78e25deb2 | ||
|
|
688db466ac | ||
|
|
293dc7925b | ||
|
|
9da5db084e | ||
|
|
4b38a793c6 | ||
|
|
7404e73fd3 |
20
data/alerts.lua
Normal file
20
data/alerts.lua
Normal 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
121
data/compostable.lua
Normal 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
219
data/craftable.lua
Normal 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
21
data/fuel.lua
Normal 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
156
data/smeltable.lua
Normal 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"} },
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
45
lib/log.lua
Normal 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
216
lib/ui.lua
Normal 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
|
||||
Reference in New Issue
Block a user