Add network broadcasting functionality for client displays and command handling
This commit is contained in:
@@ -15,6 +15,11 @@ local CACHE_FILE = ".inventory_cache" -- persistent cache file
|
|||||||
local SMELTER_MONITOR_SIDE = "top"
|
local SMELTER_MONITOR_SIDE = "top"
|
||||||
local DISABLED_RECIPES_FILE = ".disabled_recipes"
|
local DISABLED_RECIPES_FILE = ".disabled_recipes"
|
||||||
|
|
||||||
|
-- Network sync (for client displays)
|
||||||
|
local BROADCAST_CHANNEL = 4200
|
||||||
|
local ORDER_CHANNEL = 4201
|
||||||
|
local BROADCAST_INTERVAL = 1 -- seconds between state broadcasts
|
||||||
|
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
-- Furnace types to manage
|
-- Furnace types to manage
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
@@ -651,6 +656,8 @@ local mon = nil
|
|||||||
local monName = nil
|
local monName = nil
|
||||||
local smelterMon = nil
|
local smelterMon = nil
|
||||||
local smelterMonName = nil
|
local smelterMonName = nil
|
||||||
|
local networkModem = nil
|
||||||
|
local networkModemName = nil
|
||||||
|
|
||||||
local function setupMonitor()
|
local function setupMonitor()
|
||||||
mon = peripheral.wrap(MONITOR_SIDE)
|
mon = peripheral.wrap(MONITOR_SIDE)
|
||||||
@@ -2133,6 +2140,36 @@ local function handleSmelterTouch(x, y)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
-- Network broadcast (sends state to client displays)
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
local function broadcastState()
|
||||||
|
if not networkModem then return end
|
||||||
|
local state = {
|
||||||
|
type = "state",
|
||||||
|
cache = {
|
||||||
|
itemList = cache.itemList,
|
||||||
|
grandTotal = cache.grandTotal,
|
||||||
|
chestCount = cache.chestCount,
|
||||||
|
totalSlots = cache.totalSlots,
|
||||||
|
usedSlots = cache.usedSlots,
|
||||||
|
freeSlots = cache.freeSlots,
|
||||||
|
usedRatio = cache.usedRatio,
|
||||||
|
dropperOk = cache.dropperOk,
|
||||||
|
barrelOk = cache.barrelOk,
|
||||||
|
furnaceCount = cache.furnaceCount,
|
||||||
|
furnaceStatus = cache.furnaceStatus,
|
||||||
|
},
|
||||||
|
activity = activity,
|
||||||
|
alerts = activeAlerts,
|
||||||
|
smeltingPaused = smeltingPaused,
|
||||||
|
disabledRecipes = disabledRecipes,
|
||||||
|
smeltable = SMELTABLE,
|
||||||
|
}
|
||||||
|
networkModem.transmit(BROADCAST_CHANNEL, ORDER_CHANNEL, state)
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
-- Main
|
-- Main
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
@@ -2167,6 +2204,21 @@ local function main()
|
|||||||
print("[WARN] No smelter monitor on " .. SMELTER_MONITOR_SIDE)
|
print("[WARN] No smelter monitor on " .. SMELTER_MONITOR_SIDE)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Find modem for client communication
|
||||||
|
for _, name in ipairs(peripheral.getNames()) do
|
||||||
|
if peripheral.getType(name) == "modem" then
|
||||||
|
networkModem = peripheral.wrap(name)
|
||||||
|
networkModemName = name
|
||||||
|
networkModem.open(ORDER_CHANNEL)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if networkModem then
|
||||||
|
print("[OK] Network modem: " .. networkModemName)
|
||||||
|
else
|
||||||
|
print("[WARN] No modem found for client sync")
|
||||||
|
end
|
||||||
|
|
||||||
-- Load recipe toggles from disk
|
-- Load recipe toggles from disk
|
||||||
loadDisabledRecipes()
|
loadDisabledRecipes()
|
||||||
if smeltingPaused then
|
if smeltingPaused then
|
||||||
@@ -2404,6 +2456,73 @@ local function main()
|
|||||||
handleTouch(x, y)
|
handleTouch(x, y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Task 10: Network state broadcast
|
||||||
|
function()
|
||||||
|
while true do
|
||||||
|
pcall(broadcastState)
|
||||||
|
sleep(BROADCAST_INTERVAL)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Task 11: Network order/command listener
|
||||||
|
function()
|
||||||
|
if not networkModem then return end
|
||||||
|
while true do
|
||||||
|
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
||||||
|
if channel == ORDER_CHANNEL and type(message) == "table" then
|
||||||
|
if message.type == "order" and message.itemName and message.amount then
|
||||||
|
print(string.format("[NET] Order: %s x%d", message.itemName, message.amount))
|
||||||
|
local success = orderItem(message.itemName, message.amount)
|
||||||
|
networkModem.transmit(replyChannel, ORDER_CHANNEL, {
|
||||||
|
type = "order_result",
|
||||||
|
success = success,
|
||||||
|
message = statusMessage,
|
||||||
|
color = statusColor,
|
||||||
|
})
|
||||||
|
pcall(broadcastState)
|
||||||
|
elseif message.type == "scan" then
|
||||||
|
print("[NET] Scan request from client")
|
||||||
|
pcall(refreshCache)
|
||||||
|
pcall(checkAlerts)
|
||||||
|
needsRedraw = true
|
||||||
|
smelterNeedsRedraw = true
|
||||||
|
pcall(broadcastState)
|
||||||
|
elseif message.type == "toggle_pause" then
|
||||||
|
smeltingPaused = not smeltingPaused
|
||||||
|
print("[NET] Smelting " .. (smeltingPaused and "PAUSED" or "RESUMED"))
|
||||||
|
saveDisabledRecipes()
|
||||||
|
smelterNeedsRedraw = true
|
||||||
|
needsRedraw = true
|
||||||
|
pcall(broadcastState)
|
||||||
|
elseif message.type == "toggle_recipe" and message.recipe then
|
||||||
|
if disabledRecipes[message.recipe] then
|
||||||
|
disabledRecipes[message.recipe] = nil
|
||||||
|
else
|
||||||
|
disabledRecipes[message.recipe] = true
|
||||||
|
end
|
||||||
|
print("[NET] Recipe toggle: " .. message.recipe)
|
||||||
|
saveDisabledRecipes()
|
||||||
|
smelterNeedsRedraw = true
|
||||||
|
pcall(broadcastState)
|
||||||
|
elseif message.type == "enable_all" then
|
||||||
|
disabledRecipes = {}
|
||||||
|
print("[NET] All recipes enabled")
|
||||||
|
saveDisabledRecipes()
|
||||||
|
smelterNeedsRedraw = true
|
||||||
|
pcall(broadcastState)
|
||||||
|
elseif message.type == "disable_all" then
|
||||||
|
for inputName in pairs(SMELTABLE) do
|
||||||
|
disabledRecipes[inputName] = true
|
||||||
|
end
|
||||||
|
print("[NET] All recipes disabled")
|
||||||
|
saveDisabledRecipes()
|
||||||
|
smelterNeedsRedraw = true
|
||||||
|
pcall(broadcastState)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user