Guest User

Untitled

a guest
Jun 25th, 2025
267
1
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.70 KB | None | 1 0
  1. -- RSWarehouse.lua
  2. -- Author: Chuck Burgess
  3. -- Updated: 2024-01-15
  4.  
  5. local logFile = "RSWarehouse.log"
  6. local time_between_runs = 30
  7.  
  8. -- Initialize Monitor
  9. -- see: https://www.computercraft.info/wiki/Advanced_Monitor
  10. local monitor = peripheral.find("monitor")
  11. if not monitor then error("Monitor not found.") end
  12. monitor.setTextScale(0.5)
  13. monitor.clear()
  14. monitor.setCursorPos(1, 1)
  15. monitor.setCursorBlink(false)
  16. print("Monitor initialized.")
  17.  
  18. -- Initialize RS Bridge
  19. -- see: https://advancedperipherals.madefor.cc/peripherals/rs_bridge/
  20. local bridge = peripheral.find("rs_bridge")
  21. if not bridge then error("RS Bridge not found.") end
  22. print("RS Bridge initialized.")
  23.  
  24. -- Initialize Colony Integrator
  25. -- see: https://docs.advanced-peripherals.de/peripherals/colony_integrator/
  26. local colony = peripheral.find("colony_integrator")
  27. if not colony then error("Colony Integrator not found.") end
  28. if not colony.isInColony then error("Colony Integrator is not in a colony.") end
  29. print("Colony Integrator initialized.")
  30.  
  31. -- Establish the direction to transport the items into the Warehouse based on
  32. -- where the entnglement block is sitting. Default to empty string.
  33. local storage = "Right"
  34. if not storage then error("Warehouse storage not found.") end
  35. local direction = "back"
  36. print("Warehouse storage initialized.")
  37.  
  38. ----------------------------------------------------------------------------
  39. -- FUNCTIONS
  40. ----------------------------------------------------------------------------
  41. --[[
  42. Table.Empty
  43. @desc check to see if a table contains any data
  44. @return boolean
  45. ]]
  46. function table.empty (self)
  47. for _, _ in pairs(self) do
  48. return false
  49. end
  50. return true
  51. end
  52.  
  53. --[[
  54. Write To Log
  55. @desc Write the specified `table` to the file surrounded by the `blockTop` and `blockBottom`
  56. @return void
  57. ]]
  58. function writeToLog(data, blockTop, blockBottom)
  59. file.write("\n")
  60. file.write(blockTop)
  61. file.write("\n")
  62. file.write(textutils.serialize(data, { allow_repetitions = true }))
  63. file.write("\n")
  64. file.write(blockBottom)
  65. file.write("\n")
  66. end
  67.  
  68. --[[
  69. Process Work Request Item
  70. @desc Determine if this item can be delivered to the warehouse from the storage
  71. @return boolean
  72. ]]
  73. function processWorkRequestItem(request)
  74. if string.find(request.desc, "Tool of class") then return false end
  75. if string.find(request.name, "Hoe") then return false end
  76. if string.find(request.name, "Shovel") then return false end
  77. if string.find(request.name, "Axe") then return false end
  78. if string.find(request.name, "Pickaxe") then return false end
  79. if string.find(request.name, "Bow") then return false end
  80. if string.find(request.name, "Sword") then return false end
  81. if string.find(request.name, "Shield") then return false end
  82. if string.find(request.name, "Helmet") then return false end
  83. if string.find(request.name, "Leather Cap") then return false end
  84. if string.find(request.name, "Chestplate") then return false end
  85. if string.find(request.name, "Tunic") then return false end
  86. if string.find(request.name, "Pants") then return false end
  87. if string.find(request.name, "Leggings") then return false end
  88. if string.find(request.name, "Boots") then return false end
  89. if request.name == "Rallying Banner" then return false end --bugged in alpha versions
  90. if request.name == "Crafter" then return false end
  91. if request.name == "Compostable" then return false end
  92. if request.name == "Fertilizer" then return false end
  93. if request.name == "Flowers" then return false end
  94. if request.name == "Food" then return false end
  95. if request.name == "Fuel" then return false end
  96. if request.name == "Smeltable Ore" then return false end
  97. if request.name == "Stack List" then return false end
  98. -- you can add any new items here if they are found
  99. return true
  100. end
  101.  
  102. --[[
  103. Monitor Print Row Justified
  104. @desc Print a line of data to the in-game monitor
  105. @return void
  106. ]]
  107. function mPrintRowJustified(mon, y, pos, text, textcolor)
  108. w, h = mon.getSize()
  109. fg = colors.white
  110. bg = colors.black
  111.  
  112. if pos == "left" then x = 1 end
  113. if pos == "center" then x = math.floor((w - #text) / 2) end
  114. if pos == "right" then x = w - #text end
  115.  
  116. mon.setTextColor(textcolor)
  117. mon.setCursorPos(x, y)
  118. mon.write(text)
  119. mon.setTextColor(fg)
  120. mon.setBackgroundColor(bg)
  121. end
  122.  
  123. --[[
  124. Display Timer
  125. @desc Update the time on the monitor
  126. @return void
  127. ]]
  128. function displayTimer(mon, t)
  129. now = os.time()
  130. cycle = "day"
  131. cycle_color = colors.orange
  132. if now >= 4 and now < 6 then
  133. cycle = "sunrise"
  134. cycle_color = colors.yellow
  135. elseif now >= 6 and now < 18 then
  136. cycle = "day"
  137. cycle_color = colors.lightBlue
  138. elseif now >= 18 and now < 19.5 then
  139. cycle = "sunset"
  140. cycle_color = colors.magenta
  141. elseif now >= 19.5 or now < 5 then
  142. cycle = "night"
  143. cycle_color = colors.red
  144. end
  145.  
  146. timer_color = colors.green
  147. if t < 15 then timer_color = colors.yellow end
  148. if t < 5 then timer_color = colors.orange end
  149.  
  150. mPrintRowJustified(mon, 1, "left", string.format("Time: %s [%s] ", textutils.formatTime(now, false), cycle), cycle_color)
  151. if cycle ~= "night" then
  152. mPrintRowJustified(mon, 1, "right", string.format(" Remaining: %ss", t), timer_color)
  153. else
  154. mPrintRowJustified(mon, 1, "right", " Remaining: PAUSED", colors.red)
  155. end
  156. end
  157.  
  158. --[[
  159. Create Colonist Data
  160. @desc Build a table of Colonist making the request
  161. @return table
  162. ]]
  163. function createColonistData(colonist)
  164. title_words = {}
  165. words_in_name = 0
  166. colonist_job = ""
  167. word_count = 1
  168.  
  169. for word in colonist:gmatch("%S+") do
  170. table.insert(title_words, word)
  171. words_in_name = words_in_name + 1
  172. end
  173.  
  174. if words_in_name >= 3 then colonist_name = title_words[words_in_name-2] .. " " .. title_words[words_in_name]
  175. else colonist_name = colonist end
  176.  
  177. repeat
  178. if colonist_job ~= "" then colonist_job = colonist_job .. " " end
  179. colonist_job = colonist_job .. title_words[word_count]
  180. word_count = word_count + 1
  181. until word_count > words_in_name - 3
  182.  
  183. return { fullName = colonist, titleWords = title_words, job = colonist_job, name = colonist_name, wordsInName = words_in_name }
  184. end
  185.  
  186. --[[
  187. Get Work Request List (from colony)
  188. @desc Build a table of the work request data from the colony
  189. @return table
  190. ]]
  191. function getWorkRequestList(colony)
  192. requestList = {}
  193. workRequests = colony.getRequests()
  194. file = fs.open(logFile, "w")
  195.  
  196. for w in pairs(workRequests) do
  197. writeToLog(workRequests[w], "--- Request start ---", "--- Request end ---");
  198. name = workRequests[w].name -- the name of the count/item being requested
  199. colonist = createColonistData(workRequests[w].target)
  200. desc = workRequests[w].desc -- the request description
  201. item = {}
  202. -- create the filter item for the transfer request through the bridge
  203. if workRequests[w].items and workRequests[w].items[1] then
  204. if not workRequests[w].items[1].nbt or table.empty(workRequests[w].items[1].nbt) then
  205. item = { name = workRequests[w].items[1].name, count = workRequests[w].count, displayName = workRequests[w].items[1].displayName}
  206. else
  207. item = { name = workRequests[w].items[1].name, count = workRequests[w].count, displayName = workRequests[w].items[1].displayName, nbt = workRequests[w].items[1].nbt}
  208. end
  209. end
  210. -- how many items are needed to fulfill this request?
  211. needed = workRequests[w].count
  212.  
  213. local newRecord = {}
  214. newRecord.name = name
  215. newRecord.desc = desc
  216. newRecord.needed = needed
  217. newRecord.item = item
  218. newRecord.colonist = colonist
  219. table.insert(requestList, newRecord)
  220. writeToLog(newRecord, "--- Record start ---", "--- Record end ---");
  221. end
  222. file.close()
  223. return requestList
  224. end
  225.  
  226. --[[
  227. Display List
  228. @desc Update the monitor with the work request items currently in the system
  229. @return void
  230. ]]
  231. function displayList(mon, listName, itemList)
  232. -- show the list header first
  233. mPrintRowJustified(mon, row, "center", listName, colors.white)
  234. row = row + 1
  235. for e in pairs(itemList) do
  236. record = itemList[e]
  237. text = string.format("%d %s", record.provided , record.name)
  238. mPrintRowJustified(mon, row, "left", text, record.color)
  239. mPrintRowJustified(mon, row, "right", " " .. record.colonist, record.color)
  240. row = row + 1
  241. end
  242. -- add a space at the end of the list
  243. row = row + 1
  244. end
  245.  
  246. -- Color References:
  247. -- RED: work order can't be satisfied by Refined Storage (lack of pattern or lack of
  248. -- required crafting ingredients).
  249. -- YELLOW: order partially filled and a crafting job was scheduled for the rest.
  250. -- GREEN: order fully filled.
  251. -- 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.
  252. --[[
  253. Scan Work Requests
  254. @desc Manages all of the open work requests in the system and attempts to fulfill them from the inventory
  255. @desc Not called at night (as determined by the server) since requests cannot be fulfilled anyway
  256. @return void
  257. ]]
  258. function scanWorkRequests(mon, bridge, direction)
  259.  
  260. print("\nScan starting at", textutils.formatTime(os.time(), false) .. " (" .. os.time() ..").")
  261. builder_list = {}
  262. nonbuilder_list = {}
  263. equipment_list = {}
  264. requestList = getWorkRequestList(colony)
  265.  
  266. for j, data in ipairs(requestList) do
  267. color = colors.blue
  268. provided = 0
  269.  
  270. if processWorkRequestItem(data) then
  271. provided = bridge.exportItem(data.item, direction)
  272. color = colors.lightGray
  273. if provided >= data.needed then
  274. color = colors.green
  275. end
  276.  
  277. else
  278. nameString = data.name .. " [" .. data.colonist.fullName .. "]"
  279. print("[Skipped]", nameString)
  280. end
  281. -- ---------------------------------------------------------------------
  282. -- Build the newList data
  283. -- ---------------------------------------------------------------------
  284. -- create the target text
  285. expectedList = "Builder"
  286. colonist = data.colonist.name
  287. if not string.find(data.colonist.fullName, "Builder") then
  288. expectedList = ""
  289. colonist = data.colonist.job .. " " .. data.colonist.name
  290. if data.colonist.wordsInName < 3 then
  291. colonist = data.colonist.name
  292. end
  293. end
  294.  
  295. -- create the name
  296. listName = data.name
  297. if string.find(data.desc, "level") then
  298. expectedList = "Equipment"
  299. level = "Any Level"
  300. if string.find(data.desc, "with maximal level: Leather") then level = "Leather" end
  301. if string.find(data.desc, "with maximal level: Gold") then level = "Gold" end
  302. if string.find(data.desc, "with maximal level: Chain") then level = "Chain" end
  303. if string.find(data.desc, "with maximal level: Wood or Gold") then level = "Wood or Gold" end
  304. if string.find(data.desc, "with maximal level: Stone") then level = "Stone" end
  305. if string.find(data.desc, "with maximal level: Iron") then level = "Iron" end
  306. if string.find(data.desc, "with maximal level: Diamond") then level = "Diamond" end
  307. listName = level .. " " .. data.name
  308. if level == "Any Level" then listName = data.name .. " of any level" end
  309. end
  310.  
  311. -- create the new list table defining what is inserted into a specific list
  312. newList = { name=listName, colonist=colonist, needed=data.needed, provided=provided, color=color}
  313.  
  314. if expectedList == "Equipment" then
  315. table.insert(equipment_list, newList)
  316. elseif expectedList == "Builder" then
  317. table.insert(builder_list, newList)
  318. else
  319. table.insert(nonbuilder_list, newList)
  320. end
  321. -- ---------------------------------------------------------------------
  322. end
  323.  
  324. -- Show the various lists on the attached monitor.
  325. mon.clear()
  326. row = 3
  327. if not table.empty(builder_list) then displayList(mon, "Builder Requests", builder_list) end
  328. if not table.empty(nonbuilder_list) then displayList(mon, "Nonbuilder Requests", nonbuilder_list) end
  329. if not table.empty(equipment_list) then displayList(mon, "Equipment", equipment_list) end
  330.  
  331. -- no requests
  332. if row == 3 then
  333. mPrintRowJustified(mon, row, "center", "No Open Requests", colors.white)
  334. end
  335. print("Scan completed at", textutils.formatTime(os.time(), false) .. " (" .. os.time() ..").")
  336. end
  337.  
  338.  
  339. --[[
  340. MAIN
  341. @desc establish the run times and execute the work request management
  342. @return void
  343. ]]
  344. local current_run = time_between_runs
  345. scanWorkRequests(monitor, bridge, direction)
  346. displayTimer(monitor, current_run)
  347. local TIMER = os.startTimer(1)
  348.  
  349. while true do
  350. local e = {os.pullEvent()}
  351. if e[1] == "timer" and e[2] == TIMER then
  352. now = os.time()
  353. if now >= 5 and now < 19.5 then
  354. current_run = current_run - 1
  355. if current_run <= 0 then
  356. scanWorkRequests(monitor, bridge, direction)
  357. current_run = time_between_runs
  358. end
  359. end
  360. displayTimer(monitor, current_run)
  361. TIMER = os.startTimer(1)
  362. elseif e[1] == "monitor_touch" then
  363. os.cancelTimer(TIMER)
  364. scanWorkRequests(monitor, bridge, direction)
  365. current_run = time_between_runs
  366. displayTimer(monitor, current_run)
  367. TIMER = os.startTimer(1)
  368. end
  369. end
Advertisement
Comments
  • mirvine
    43 days
    # text 0.29 KB | 0 0
    1. Thanks. This current version works great.
    2.  
    3. Only suggestion is to add this before the Bow search string (line 79):
    4.  
    5. if string.find(request.name, "Bowl") then return true end
    6.  
    7. 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