Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
-- RSWarehouse.lua -- Orignal Author: Chuck Burgess -- updated by: Mathew Biltonen -- Updated: 2025-10-17 local logFile = "RSWarehouse.log" local time_between_runs = 30 -- Initialize Monitor -- see: https://www.computercraft.info/wiki/Advanced_Monitor local monitor = peripheral.find("monitor") if not monitor then error("Monitor not found.") end monitor.setTextScale(0.5) monitor.clear() monitor.setCursorPos(1, 1) monitor.setCursorBlink(false) print("Monitor initialized.") -- Initialize RS Bridge -- see: https://advancedperipherals.madefor.cc/peripherals/rs_bridge/ local bridge = peripheral.find("rs_bridge") if not bridge then error("RS Bridge not found.") end print("RS Bridge initialized.") -- Initialize Colony Integrator -- see: https://docs.advanced-peripherals.de/peripherals/colony_integrator/ local colony = peripheral.find("colony_integrator") if not colony then error("Colony Integrator not found.") end if not colony.isInColony then error("Colony Integrator is not in a colony.") end print("Colony Integrator initialized.") -- Establish the direction to transport the items into the Warehouse based on -- where the entnglement block is sitting. Default to empty string. local storage = peripheral.find("entangled:tile") if not storage then error("Warehouse storage not found.") end local direction = "" local names = peripheral.getNames() for _, pos in ipairs(names) do if peripheral.getType(pos) == "entangled:tile" then direction = pos end end print("Warehouse storage initialized.") ---------------------------------------------------------------------------- -- FUNCTIONS ---------------------------------------------------------------------------- --[[ Table.Empty @desc check to see if a table contains any data @return boolean ]] function table.empty (self) for _, _ in pairs(self) do return false end return true end --[[ Write To Log @desc Write the specified `table` to the file surrounded by the `blockTop` and `blockBottom` @return void ]] function writeToLog(data, blockTop, blockBottom) file.write("\n") file.write(blockTop) file.write("\n") file.write(textutils.serialize(data, { allow_repetitions = true })) file.write("\n") file.write(blockBottom) file.write("\n") end --[[ Process Work Request Item @desc Determine if this item can be delivered to the warehouse from the storage @return boolean ]] function processWorkRequestItem(request) if string.find(request.desc, "Tool of class") then return false end if string.find(request.name, "Hoe") then return false end if string.find(request.name, "Shovel") then return false end if string.find(request.name, "Axe") then return false end if string.find(request.name, "Pickaxe") then return false end if string.find(request.name, "Bow") then return false end if string.find(request.name, "Sword") then return false end if string.find(request.name, "Shield") then return false end if string.find(request.name, "Helmet") then return false end if string.find(request.name, "Leather Cap") then return false end if string.find(request.name, "Chestplate") then return false end if string.find(request.name, "Tunic") then return false end if string.find(request.name, "Pants") then return false end if string.find(request.name, "Leggings") then return false end if string.find(request.name, "Boots") then return false end if request.name == "Rallying Banner" then return false end --bugged in alpha versions if request.name == "Crafter" then return false end if request.name == "Compostable" then return false end if request.name == "Fertilizer" then return false end if request.name == "Flowers" then return false end if request.name == "Food" then return false end if request.name == "Fuel" then return false end if request.name == "Smeltable Ore" then return false end if request.name == "Stack List" then return false end -- you can add any new items here if they are found return true end --[[ Monitor Print Row Justified @desc Print a line of data to the in-game monitor @return void ]] function mPrintRowJustified(mon, y, pos, text, textcolor) w, h = mon.getSize() fg = colors.white bg = colors.black if pos == "left" then x = 1 end if pos == "center" then x = math.floor((w - #text) / 2) end if pos == "right" then x = w - #text end mon.setTextColor(textcolor) mon.setCursorPos(x, y) mon.write(text) mon.setTextColor(fg) mon.setBackgroundColor(bg) end --[[ Display Timer @desc Update the time on the monitor @return void ]] function displayTimer(mon, t) now = os.time() cycle = "day" cycle_color = colors.orange if now >= 4 and now < 6 then cycle = "sunrise" cycle_color = colors.yellow elseif now >= 6 and now < 18 then cycle = "day" cycle_color = colors.lightBlue elseif now >= 18 and now < 19.5 then cycle = "sunset" cycle_color = colors.magenta elseif now >= 19.5 or now < 5 then cycle = "night" cycle_color = colors.red end timer_color = colors.green if t < 15 then timer_color = colors.yellow end if t < 5 then timer_color = colors.orange end mPrintRowJustified(mon, 1, "left", string.format("Time: %s [%s] ", textutils.formatTime(now, false), cycle), cycle_color) if cycle ~= "night" then mPrintRowJustified(mon, 1, "right", string.format(" Remaining: %ss", t), timer_color) else mPrintRowJustified(mon, 1, "right", " Remaining: PAUSED", colors.red) end end --[[ Create Colonist Data @desc Build a table of Colonist making the request @return table ]] function createColonistData(colonist) title_words = {} words_in_name = 0 colonist_job = "" word_count = 1 for word in colonist:gmatch("%S+") do table.insert(title_words, word) words_in_name = words_in_name + 1 end if words_in_name >= 3 then colonist_name = title_words[words_in_name-2] .. " " .. title_words[words_in_name] else colonist_name = colonist end repeat if colonist_job ~= "" then colonist_job = colonist_job .. " " end colonist_job = colonist_job .. title_words[word_count] word_count = word_count + 1 until word_count > words_in_name - 3 return { fullName = colonist, titleWords = title_words, job = colonist_job, name = colonist_name, wordsInName = words_in_name } end --[[ Get Work Request List (from colony) @desc Build a table of the work request data from the colony @return table ]] function getWorkRequestList(colony) requestList = {} workRequests = colony.getRequests() file = fs.open(logFile, "w") for w in pairs(workRequests) do writeToLog(workRequests[w], "--- Request start ---", "--- Request end ---"); name = workRequests[w].name -- the name of the count/item being requested colonist = createColonistData(workRequests[w].target) desc = workRequests[w].desc -- the request description item = {} -- create the filter item for the transfer request through the bridge if workRequests[w].items and workRequests[w].items[1] then if not workRequests[w].items[1].nbt or table.empty(workRequests[w].items[1].nbt) then item = { name = workRequests[w].items[1].name, count = workRequests[w].count, displayName = workRequests[w].items[1].displayName} else item = { name = workRequests[w].items[1].name, count = workRequests[w].count, displayName = workRequests[w].items[1].displayName, nbt = workRequests[w].items[1].nbt} end end -- how many items are needed to fulfill this request? needed = workRequests[w].count local newRecord = {} newRecord.name = name newRecord.desc = desc newRecord.needed = needed newRecord.item = item newRecord.colonist = colonist table.insert(requestList, newRecord) writeToLog(newRecord, "--- Record start ---", "--- Record end ---"); end file.close() return requestList end --[[ Display List @desc Update the monitor with the work request items currently in the system @return void ]] function displayList(mon, listName, itemList) -- show the list header first mPrintRowJustified(mon, row, "center", listName, colors.white) row = row + 1 for e in pairs(itemList) do record = itemList[e] text = string.format("%d %s", record.provided , record.name) mPrintRowJustified(mon, row, "left", text, record.color) mPrintRowJustified(mon, row, "right", " " .. record.colonist, record.color) row = row + 1 end -- add a space at the end of the list row = row + 1 end -- Color References: -- RED: work order can't be satisfied by Refined Storage (lack of pattern or lack of -- required crafting ingredients). -- YELLOW: order partially filled and a crafting job was scheduled for the rest. -- GREEN: order fully filled. -- BLUE: the Player needs to manually fill the work order. This includes some equipment as well as generic requests ike Compostables, Fuel, Food, Flowers, etc. --[[ Scan Work Requests @desc Manages all of the open work requests in the system and attempts to fulfill them from the inventory @desc Not called at night (as determined by the server) since requests cannot be fulfilled anyway @return void ]] function scanWorkRequests(mon, bridge, direction) print("\nScan starting at", textutils.formatTime(os.time(), false) .. " (" .. os.time() ..").") builder_list = {} nonbuilder_list = {} equipment_list = {} requestList = getWorkRequestList(colony) for j, data in ipairs(requestList) do color = colors.blue provided = 0 if processWorkRequestItem(data) then provided = bridge.exportItem(data.item, direction) color = colors.lightGray if provided >= data.needed then color = colors.green end -- only handle the Non-NBT data items or empty nbt table item records if provided < data.needed then if bridge.isCrafting(data.item) then color = colors.yellow print("[Crafting]", data.name) else if bridge.craftItem(data.item) then color = colors.yellow print("[Scheduled]", data.item.count, "x", data.name) else color = colors.red print("[Failed]", data.name) end end end else nameString = data.name .. " [" .. data.colonist.fullName .. "]" print("[Skipped]", nameString) end -- --------------------------------------------------------------------- -- Build the newList data -- --------------------------------------------------------------------- -- create the target text expectedList = "Builder" colonist = data.colonist.name if not string.find(data.colonist.fullName, "Builder") then expectedList = "" colonist = data.colonist.job .. " " .. data.colonist.name if data.colonist.wordsInName < 3 then colonist = data.colonist.name end end -- create the name listName = data.name if string.find(data.desc, "level") then expectedList = "Equipment" level = "Any Level" if string.find(data.desc, "with maximal level: Leather") then level = "Leather" end if string.find(data.desc, "with maximal level: Gold") then level = "Gold" end if string.find(data.desc, "with maximal level: Chain") then level = "Chain" end if string.find(data.desc, "with maximal level: Wood or Gold") then level = "Wood or Gold" end if string.find(data.desc, "with maximal level: Stone") then level = "Stone" end if string.find(data.desc, "with maximal level: Iron") then level = "Iron" end if string.find(data.desc, "with maximal level: Diamond") then level = "Diamond" end listName = level .. " " .. data.name if level == "Any Level" then listName = data.name .. " of any level" end end -- create the new list table defining what is inserted into a specific list newList = { name=listName, colonist=colonist, needed=data.needed, provided=provided, color=color} if expectedList == "Equipment" then table.insert(equipment_list, newList) elseif expectedList == "Builder" then table.insert(builder_list, newList) else table.insert(nonbuilder_list, newList) end -- --------------------------------------------------------------------- end -- Show the various lists on the attached monitor. mon.clear() row = 3 if not table.empty(builder_list) then displayList(mon, "Builder Requests", builder_list) end if not table.empty(nonbuilder_list) then displayList(mon, "Nonbuilder Requests", nonbuilder_list) end if not table.empty(equipment_list) then displayList(mon, "Equipment", equipment_list) end -- no requests if row == 3 then mPrintRowJustified(mon, row, "center", "No Open Requests", colors.white) end print("Scan completed at", textutils.formatTime(os.time(), false) .. " (" .. os.time() ..").") end --[[ MAIN @desc establish the run times and execute the work request management @return void ]] local current_run = time_between_runs scanWorkRequests(monitor, bridge, direction) displayTimer(monitor, current_run) local TIMER = os.startTimer(1) while true do local e = {os.pullEvent()} if e[1] == "timer" and e[2] == TIMER then now = os.time() if now >= 5 and now < 19.5 then current_run = current_run - 1 if current_run <= 0 then scanWorkRequests(monitor, bridge, direction) current_run = time_between_runs end end displayTimer(monitor, current_run) TIMER = os.startTimer(1) elseif e[1] == "monitor_touch" then os.cancelTimer(TIMER) scanWorkRequests(monitor, bridge, direction) current_run = time_between_runs displayTimer(monitor, current_run) TIMER = os.startTimer(1) end end
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)