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("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 = "Right"
- if not storage then error("Warehouse storage not found.") end
- local direction = "back"
- 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
- 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
Advertisement
Comments
-
- Thanks. This current version works great.
- Only suggestion is to add this before the Bow search string (line 79):
- if string.find(request.name, "Bowl") then return true end
- This is because Bow is in Bowl and marks it as skip. By doing the check for Bowl first allows it to get auto crafted.
Add Comment
Please, Sign In to add comment