Skip to content

Instantly share code, notes, and snippets.

@sk89q
Created March 5, 2013 05:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sk89q/5088260 to your computer and use it in GitHub Desktop.
Save sk89q/5088260 to your computer and use it in GitHub Desktop.
Request system we used that let you put what you wanted in a book, and then it would supply your ender pouch with the items
--[[
Remote Request
by sk89q
]]--
function periph(side)
while true do
local p = peripheral.wrap(side)
if p then return p end
os.sleep(1)
end
end
function wrap(str, limit)
local here = 1
return str:gsub("(%s+)()(%S+)()",
function(sp, st, word, fi)
if fi - here > limit then
here = st
return "\n" .. word
end
end)
end
function prototype(parent, t)
if not t then
t = parent
parent = nil
end -- when there is no inheritance
local t = t or {}
local mt = { __index = t }
setmetatable(t, {
__call = function(_, ...)
local obj = setmetatable({}, mt)
if obj.__construct then obj:__construct(unpack(arg)) end
return obj
end,
__index = parent
})
return t
end
function trim(s)
return s:match("^%s*(.*)"):match("(.-)%s*$")
end
local Transport = prototype({
__construct = function(self, ...)
self.paths = arg
end,
transferTo = function(self, id, amount)
for i = 1, #self.paths do
local sorter = path[1]
local from = path[2]
local to = path[3]
sorter.extract(from, id, to, amount)
end
end,
transferFrom = function(self, id, amount)
for i = #self.paths, 1, -1 do
local sorter = path[1]
local to = path[2] -- reversed
local from = path[3]
sorter.extract(from, id, to, amount)
end
end,
listFrom = function(self)
local path = self.paths[1]
return path[1].list(path[2])
end,
listTo = function(self)
local path = self.paths[#self.paths]
return path[1].list(path[3])
end
})
local Printer = prototype({
__construct = function(self, printer)
self.printer = printer
end,
print = function(self, title, text)
self.printer.newPage()
self.printer.setPageTitle(title)
local w, h = self.printer.getPageSize()
local lineNo = 1
for token in string.gmatch(text, "[^\n]+") do
for line in string.gmatch(wrap(token, w), "[^\n]+") do
-- may need new page!
if lineNo > h then
lineNo = 1
if not self.printer.endPage() then
return false
end
self.printer.newPage()
self.printer.setPageTitle(title)
w, h = self.printer.getPageSize()
end
self.printer.setCursorPos(1, lineNo)
self.printer.write(line)
lineNo = lineNo + 1
end
end
return self.printer.endPage()
end
})
local Requester = prototype({
cobbleISorterId = 538962333,
triggerAmount = 1,
__construct = function(self, sorter, side, sharedSide)
self.sorter = sorter
self.side = side
self.sharedSide = sharedSide
end,
isTriggered = function(self)
local items = self.sorter.list(self.side)
if items == nil then return end -- inventory missing
for id, amount in pairs(items) do
if id == self.cobbleISorterId and amount == self.triggerAmount then
return true
end
end
return false
end,
pull = function(self, id, amount)
self.sorter.extract(self.side, self.cobbleISorterId, self.sharedSide, self.triggerAmount)
self.sorter.extract(self.side, id, self.sharedSide, amount)
-- return what the trigger item is
return unpack({self.cobbleISorterId, self.triggerAmount})
end,
distribute = function(self, left, silent)
local items = self.sorter.list(self.sharedSide)
if items == nil then return end -- inventory missing
for id, amount in pairs(items) do
if left <= 0 then
print("Ran out of items!", id)
return 0
end
local n = math.min(left, amount)
left = left - n -- remove from # of items we still need
if not silent then
print("Moving ", n, "x (isorter)", id)
end
self.sorter.extract(self.sharedSide, id, self.side, n)
end
return left -- how many we were unable to send?
end
})
local Match = prototype({
__construct = function(self, uid, name, amount, confidence)
self.uid = uid
self.name = name
self.amount = amount
self.confidence = confidence
end
})
local Request = prototype({
__construct = function(self, name, amount)
self.name = name
self.amount = amount
self.match = nil
end,
getConfidence = function(self, name)
local test = self.name:lower()
local name = name:lower()
if string.sub(name, 1, string.len(test)) == test then
return 1/math.abs(#test - #name)
else
return 0
end
end,
setMatch = function(self, match)
if self.match == nil or match.confidence > self.match.confidence then
self.match = match
end
end
})
local RequestManager = prototype({
bookISorterId = 551348637, -- isorter ID, UPDATE LATER
bookId = 386, -- book and quill ID
__construct = function(self, queryPipe, requestPipe, sorter, storeSide, processSide)
self.queryPipe = queryPipe
self.requestPipe = requestPipe
self.sorter = sorter
self.storeSide = storeSide
self.processSide = processSide
end,
execute = function(self, requester)
-- pull the book and destroy the trigger
local id, amount = requester:pull(self.bookISorterId, 1)
self.sorter.extract(self.storeSide, id, self.processSide, amount)
local requested = self:read()
-- move the book back
requester:distribute(1, true)
if #requested > 0 then -- only if some were parsed correctly!
local left = self:request(requested)
if left > 0 then
local limit = 30
for i = 1, limit do -- keep trying to send until we give up or finish
os.sleep(1) -- just wait a bit
left = requester:distribute(left)
if left == 0 then break end -- finish successfully
limit = 30
print("Still ", left, " item(s) left!")
end
print("Finished request with ", left, " item(s) left")
else
print("No items successfully requested")
end
end
end,
read = function(self)
local requested = {} -- returned
-- ask the request pipe for items
self.queryPipe.getAvailableItems()
-- look for the book
local event, items = os.pullEvent("available_items_return")
for _, item in ipairs(items) do
local uid = item[1]
local amount = item[2]
local id = self.queryPipe.getItemID(uid)
-- book and quill
if id == self.bookId then
local nbt = self.queryPipe.getNBTTagCompound(uid)
local pages = nbt.value.pages.value
local text = ""
for _, v in ipairs(pages) do
text = text .. v.value .. "\n"
end
for k, v in string.gmatch(text, "([0-9]+) +([^0-9]+)") do
table.insert(requested, Request(trim(v), tonumber(k)))
end
end
end
return requested
end,
request = function(self, requested)
local expected = 0 -- keep track of the number of items that we want
self.requestPipe.getAvailableItems()
local event, items = os.pullEvent("available_items_return")
for _, item in ipairs(items) do
local uid = item[1]
local amount = item[2]
local name = self.requestPipe.getItemName(uid)
if name ~= "" then -- empty names are bad!
for k, request in ipairs(requested) do
-- does it match?
local confidence = request:getConfidence(name)
if confidence > 0 then
local n = math.min(amount, request.amount)
request:setMatch(Match(uid, name, n, confidence))
end
end
end
end
-- loop over and request
for k, request in ipairs(requested) do
local match = request.match
if match then
print("Requesting ", match.amount, "x ", match.name)
expected = expected + match.amount
self.requestPipe.makeRequest(match.uid, match.amount) -- request!
else
print("Couldn't find ", request.amount, "x ", request.name)
end
end
return expected
end
})
--------------
local down = 0
local up = 1
local north = 2
local south = 3
local west = 4
local east = 5
local sorter1 = periph("left:yellow")
local sorter2 = periph("right:yellow")
local queryPipe = periph("back")
local requestPipe = periph("top")
local printerBlock = periph("right:blue")
--[[
local printer = Printer(printerBlock)
printer.print("TEST", "testing")
local transport = Transport(
{sorter2, south, north}, {sorter2, south, north})
skcraft.dump(transport:listTo())
]]--
local requesters = {
Requester(sorter1, west, south),
Requester(sorter1, north, south),
Requester(sorter1, east, south),
Requester(sorter1, up, south),
Requester(sorter2, west, north),
Requester(sorter2, south, north),
Requester(sorter2, east, north),
Requester(sorter2, up, north),
}
local reqMan = RequestManager(queryPipe, requestPipe, sorter2, north, up)
print("Remote Request activated")
while true do
for _, requester in ipairs(requesters) do
if requester:isTriggered() then
reqMan:execute(requester)
end
end
os.sleep(1)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment