Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- RSWarehouse.lua
- -- Author: Chuck Burgess
- -- Updated: 2024-01-15
- 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("rsBridge")
- 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("colonyIntegrator")
- 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.exportItemToPeripheral(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.isItemCrafting(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
Add Comment
Please, Sign In to add comment