255 lines
5.4 KiB
Lua
255 lines
5.4 KiB
Lua
local class = require('class')
|
|
local itemDB = require('itemDB')
|
|
local Peripheral = require('peripheral')
|
|
local Util = require('util')
|
|
|
|
local os = _G.os
|
|
|
|
local convertNames = {
|
|
name = 'id',
|
|
damage = 'dmg',
|
|
maxCount = 'max_size',
|
|
count = 'qty',
|
|
displayName = 'display_name',
|
|
maxDamage = 'max_dmg',
|
|
nbtHash = 'nbt_hash',
|
|
}
|
|
|
|
-- Strip off color prefix
|
|
local function safeString(text)
|
|
|
|
local val = text:byte(1)
|
|
|
|
if val < 32 or val > 128 then
|
|
|
|
local newText = {}
|
|
for i = 4, #text do
|
|
val = text:byte(i)
|
|
newText[i - 3] = (val > 31 and val < 127) and val or 63
|
|
end
|
|
return string.char(unpack(newText))
|
|
end
|
|
|
|
return text
|
|
end
|
|
|
|
local function convertItem(item)
|
|
for k,v in pairs(convertNames) do
|
|
item[k] = item[v]
|
|
item[v] = nil
|
|
end
|
|
item.displayName = safeString(item.displayName)
|
|
end
|
|
|
|
local MEAdapter = class()
|
|
|
|
function MEAdapter:init(args)
|
|
local defaults = {
|
|
items = { },
|
|
name = 'ME',
|
|
jobList = { },
|
|
}
|
|
Util.merge(self, defaults)
|
|
Util.merge(self, args)
|
|
|
|
local chest
|
|
|
|
if not self.side then
|
|
chest = Peripheral.getByMethod('getAvailableItems')
|
|
else
|
|
chest = Peripheral.getBySide(self.side)
|
|
if chest and not chest.getAvailableItems then
|
|
chest = nil
|
|
end
|
|
end
|
|
|
|
if chest then
|
|
Util.merge(self, chest)
|
|
end
|
|
end
|
|
|
|
function MEAdapter:isValid()
|
|
return self.getAvailableItems and self.getAvailableItems()
|
|
end
|
|
|
|
function MEAdapter:refresh()
|
|
self.items = nil
|
|
local hasItems, failed
|
|
|
|
local s, m = pcall(function()
|
|
self.items = self.getAvailableItems('all')
|
|
for _,v in pairs(self.items) do
|
|
Util.merge(v, v.item)
|
|
convertItem(v)
|
|
|
|
-- if power has been interrupted, the list will still be returned
|
|
-- but all items will have a 0 quantity
|
|
-- ensure that the list is valid
|
|
if not hasItems then
|
|
hasItems = v.count > 0
|
|
end
|
|
|
|
if not v.fingerprint then
|
|
failed = true
|
|
break
|
|
end
|
|
|
|
if not itemDB:get(v) then
|
|
itemDB:add(v, v)
|
|
end
|
|
end
|
|
end)
|
|
itemDB:flush()
|
|
|
|
if not s and m then
|
|
_debug(m)
|
|
end
|
|
|
|
if s and not failed and hasItems and self.items and not Util.empty(self.items) then
|
|
return self.items
|
|
end
|
|
self.items = nil
|
|
end
|
|
|
|
function MEAdapter:listItems()
|
|
self:refresh()
|
|
return self.items
|
|
end
|
|
|
|
function MEAdapter:getItemInfo(item)
|
|
for _,i in pairs(self.items) do
|
|
if item.name == i.name and
|
|
item.damage == i.damage and
|
|
item.nbtHash == i.nbtHash then
|
|
return i
|
|
end
|
|
end
|
|
end
|
|
|
|
function MEAdapter:isCPUAvailable()
|
|
local cpus = self.getCraftingCPUs() or { }
|
|
local available = false
|
|
|
|
for cpu,v in pairs(cpus) do
|
|
if not v.busy then
|
|
available = true
|
|
elseif not self.jobList[cpu] then -- something else is crafting something (don't know what)
|
|
return false -- return false since we are in an unknown state
|
|
end
|
|
end
|
|
return available
|
|
end
|
|
|
|
function MEAdapter:craft(item, count)
|
|
if not self:isCPUAvailable() then
|
|
return false
|
|
end
|
|
|
|
self:refresh()
|
|
|
|
item = self:getItemInfo(item)
|
|
if item and item.is_craftable then
|
|
|
|
local cpus = self.getCraftingCPUs() or { }
|
|
for cpu,v in pairs(cpus) do
|
|
if not v.busy then
|
|
self.requestCrafting({
|
|
id = item.name,
|
|
dmg = item.damage,
|
|
nbt_hash = item.nbtHash,
|
|
},
|
|
count or 1,
|
|
v.name -- CPUs must be named ! use anvil
|
|
)
|
|
|
|
os.sleep(0) -- needed ?
|
|
cpus = self.getCraftingCPUs() or { }
|
|
|
|
if cpus[cpu].busy then
|
|
self.jobList[cpu] = {
|
|
name = item.name,
|
|
damage = item.damage,
|
|
nbtHash = item.nbtHash,
|
|
count = count,
|
|
}
|
|
return true
|
|
end
|
|
break -- only need to try the first available cpu
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
end
|
|
|
|
function MEAdapter:getJobList()
|
|
local cpus = self.getCraftingCPUs() or { }
|
|
for cpu,v in pairs(cpus) do
|
|
if not v.busy then
|
|
self.jobList[cpu] = nil
|
|
end
|
|
end
|
|
|
|
return self.jobList
|
|
end
|
|
|
|
function MEAdapter:isCrafting(item)
|
|
for _,v in pairs(self:getJobList()) do
|
|
if v.name == item.name and
|
|
v.damage == item.damage and
|
|
v.nbtHash == item.nbtHash then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function MEAdapter:craftItems(items)
|
|
local cpus = self.getCraftingCPUs() or { }
|
|
local count = 0
|
|
|
|
for _,cpu in pairs(cpus) do
|
|
if cpu.busy then
|
|
return
|
|
end
|
|
end
|
|
|
|
for _,item in pairs(items) do
|
|
if count >= #cpus then
|
|
break
|
|
end
|
|
if not self:isCrafting(item) then
|
|
if self:craft(item, item.count) then
|
|
count = count + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function MEAdapter:provide(item, qty, slot, direction)
|
|
return pcall(function()
|
|
for _,stack in pairs(self.getAvailableItems('all')) do
|
|
if stack.item.id == item.name and
|
|
(not item.damage or stack.item.dmg == item.damage) and
|
|
(not item.nbtHash or stack.item.nbt_hash == item.nbtHash) then
|
|
local amount = math.min(qty, stack.item.qty)
|
|
if amount > 0 then
|
|
self.exportItem(stack.item, direction or self.direction, amount, slot)
|
|
end
|
|
qty = qty - amount
|
|
if qty <= 0 then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
function MEAdapter:insert(slot, qty, toSlot)
|
|
local s, m = pcall(self.pullItem, self.direction, slot, qty, toSlot)
|
|
if not s and m then
|
|
os.sleep(1)
|
|
pcall(self.pullItem, self.direction, slot, qty, toSlot)
|
|
end
|
|
end
|
|
|
|
return MEAdapter
|