Files
opus-apps/core/apis/meAdapter.lua

255 lines
5.0 KiB
Lua

local class = require('class')
local itemDB = require('core.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
_G._syslog(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