Try to update Milo for 1.19

Removes Milo trying to access damage on items (`nil` because of The
Flattening). We might also need to reimplement showing durability in the
item's display name - I got a little too carried away with removing
mentions of "damage". Also renames nbtHash to nbt to be consistent with
new CC:T naming. I tried not to touch anything related to MiloRemote for
now, and there are probably still many bugs remaining that need to be
ironed out. Most of the basic functionality works now, though.
This commit is contained in:
Kan18
2022-12-24 15:33:01 +04:00
parent 2461d060e0
commit 2f67fb2ef8
16 changed files with 101 additions and 100 deletions

View File

@@ -2,6 +2,7 @@ local Event = require('opus.event')
local Milo = require('milo')
local Sound = require('opus.sound')
local Storage = require('milo.storage')
local TurtleInv = require('milo.turtleInv')
local UI = require('opus.ui')
local Util = require('opus.util')
@@ -18,7 +19,6 @@ multishell.setTitle(multishell.getCurrent(), 'Milo')
local function Syntax(msg)
print([[
Turtle must be provided with:
* Introspection module (never bound)
* Workbench
Turtle must be connected to:
@@ -46,10 +46,6 @@ if not modem.getNameLocal() then
Syntax('Wired modem is not active')
end
local introspection = device['plethora:introspection'] or
turtle.equip('left', 'plethora:module:0') and device['plethora:introspection'] or
Syntax('Introspection module missing')
if not device.workbench then
turtle.equip('right', 'minecraft:crafting_table:0')
if not device.workbench then
@@ -58,6 +54,7 @@ if not device.workbench then
end
local localName = modem.getNameLocal()
TurtleInv.setLocalName(localName)
local context = {
resources = Util.readTable(Milo.RESOURCE_FILE) or { },
@@ -76,7 +73,7 @@ local context = {
turtleInventory = {
name = localName,
mtype = 'hidden',
adapter = introspection.getInventory(),
adapter = TurtleInv,
}
}

View File

@@ -283,7 +283,7 @@ local function splitKey(key)
local t = Util.split(key, '(.-):')
local item = { }
if #t[#t] > 8 then
item.nbtHash = table.remove(t)
item.nbt = table.remove(t)
end
item.damage = tonumber(table.remove(t))
item.name = table.concat(t, ':')

View File

@@ -20,10 +20,11 @@ local Craft = {
local function splitKey(key)
local t = Util.split(key, '(.-):')
local item = { }
if #t[#t] > 8 then
item.nbtHash = table.remove(t)
if t[3] then
item.nbt = t[3]
end
item.damage = tonumber(table.remove(t))
item.name = table.concat(t, ':')
return item
end
@@ -32,7 +33,7 @@ local function makeRecipeKey(item)
if type(item) == 'string' then
item = splitKey(item)
end
return table.concat({ item.name, item.damage or 0, item.nbtHash }, ':')
return table.concat({ item.name, item.nbt }, ':')
end
local function convert(ingredient)
@@ -47,8 +48,7 @@ local function getCraftingTool(storage, item)
for _,v in pairs(items) do
if item.name == v.name and
(not item.damage or item.damage == v.damage) and
(not item.nbtHash or item.nbtHash == v.nbtHash) then
(not item.nbt or item.nbt == v.nbt) then
return v
end
end
@@ -93,11 +93,7 @@ function Craft.getItemCount(items, item)
local count = 0
for _,v in pairs(items) do
if v.name == item.name and
(not item.damage or v.damage == item.damage) and
v.nbtHash == item.nbtHash then
if item.damage then
return v.count
end
v.nbt == item.nbt then
count = count + v.count
end
end
@@ -387,18 +383,7 @@ function Craft.findRecipe(key)
end
local item = itemDB:splitKey(key)
if item.damage then
return Craft.recipes[makeRecipeKey(item)]
end
-- handle cases where the request is like : IC2:reactorVent:*
for rkey,recipe in pairs(Craft.recipes) do
local r = itemDB:splitKey(rkey)
if item.name == r.name and
(not item.nbtHash or r.nbtHash == item.nbtHash) then
return recipe
end
end
return Craft.recipes[makeRecipeKey(item)]
end
-- determine the full list of ingredients needed to craft

View File

@@ -93,7 +93,7 @@ function Milo:getMatches(item, flags)
local count = 0
local items = self:listItems()
if not flags.ignoreDamage and not flags.ignoreNbtHash then
if not flags.ignoreNbt then
local key = item.key or itemDB:makeKey(item)
local v = items[key]
if v then
@@ -104,8 +104,7 @@ function Milo:getMatches(item, flags)
else
for key,v in pairs(items) do
if item.name == v.name and
(flags.ignoreDamage or item.damage == v.damage) and
(flags.ignoreNbtHash or item.nbtHash == v.nbtHash) then
(flags.ignoreNbt or item.nbt == v.nbt) then
t[key] = Util.shallowCopy(v)
count = count + v.count
@@ -125,7 +124,7 @@ function Milo:getTurtleInventory()
for i, v in pairs(self.context.turtleInventory.adapter.list()) do
list[i] = itemDB:get(v, function()
return self.context.turtleInventory.adapter.getItemMeta(i)
return self.context.turtleInventory.adapter.getItemDetail(i)
end)
end
@@ -277,22 +276,15 @@ function Milo:learnRecipe()
for _,v1 in pairs(results) do
for _,v2 in pairs(ingredients) do
if v1.name == v2.name and
v1.nbtHash == v2.nbtHash and
(v1.damage == v2.damage or
(v1.maxDamage > 0 and v2.maxDamage > 0 and
v1.damage ~= v2.damage)) then
v1.nbt == v2.nbt then
if not newRecipe.crafingTools then
newRecipe.craftingTools = { }
end
local tool = Util.shallowCopy(v2)
if tool.maxDamage > 0 then
tool.damage = '*'
v2.damage = '*'
end
--[[
Turtles can only craft one item at a time using a tool :(
]]--
]] -- Todo: check if this still applies
maxCount = 1
newRecipe.craftingTools[itemDB:makeKey(tool)] = true

View File

@@ -21,13 +21,13 @@ function Adapter:listItems(throttle)
for k,v in pairs(self.list()) do
if v.count > 0 then
local key = table.concat({ v.name, v.damage, v.nbtHash }, ':')
local key = table.concat({ v.name, v.nbt }, ':')
local entry = cache[key]
if entry then
entry.count = entry.count + v.count
else
cache[key] = itemDB:get(v, function() return self.getItemMeta(k) end)
cache[key] = itemDB:get(v, function() return self.getItemDetail(k) end)
end
throttle()
end

View File

@@ -321,7 +321,7 @@ function Storage:listItemsRaw(throttle)
local items = chest.list()
for slot, item in pairs(items) do
items[slot] = itemDB:get(item, function() return chest.getItemMeta(slot) end)
items[slot] = itemDB:get(item, function() return chest.getItemDetail(slot) end)
end
res[v.name] = items
@@ -340,7 +340,7 @@ function Storage:listProviders(throttle)
for chest, items in pairs(rawItems) do
for slot, item in pairs(items) do
local key = table.concat({item.name, item.damage, item.nbtHash}, ":")
local key = table.concat({item.name, item.nbt}, ":")
if not res[key] then
res[key] = {}
end
@@ -443,7 +443,7 @@ function Storage:updateCache(adapter, item, count)
return
end
local key = item.key or table.concat({ item.name, item.damage, item.nbtHash }, ':')
local key = item.key or table.concat({ item.name, item.nbt }, ':')
local entry = adapter.cache[key]
if not entry then
@@ -490,14 +490,14 @@ end
local function isValidTransfer(adapter, target)
-- lazily cache transfer locations
if not adapter.transferLocations then
--[[if not adapter.transferLocations then
adapter.transferLocations = adapter.getTransferLocations()
end
for _,v in pairs(adapter.transferLocations) do
if v == target then
for _,v in pairs(adapter.transferLocations) do]]
-- if v == target then
return true
end
end
-- end
--end
end
local function rawExport(source, target, item, qty, slot)
@@ -529,8 +529,7 @@ local function rawExport(source, target, item, qty, slot)
local stacks = source.list()
for key,stack in Util.rpairs(stacks) do
if stack.name == item.name and
stack.damage == item.damage and
stack.nbtHash == item.nbtHash then
stack.nbt == item.nbt then
local amount = math.min(qty, stack.count)
if amount > 0 then
amount = transfer(key, amount, slot)
@@ -560,7 +559,7 @@ end
function Storage:export(target, slot, count, item)
local timer = Util.timer()
local total = 0
local key = item.key or table.concat({ item.name, item.damage, item.nbtHash }, ':')
local key = item.key or table.concat({ item.name, item.nbt }, ':')
local function provide(adapter, pcount)
-- update cache before export to allow for simultaneous calls
@@ -651,7 +650,7 @@ function Storage:import(source, slot, count, item)
local timer = Util.timer()
local total = 0
local key = item.key or table.concat({ item.name, item.damage, item.nbtHash }, ':')
local key = item.key or table.concat({ item.name, item.nbt }, ':')
if not self.cache then
self:listItems()
@@ -664,7 +663,7 @@ function Storage:import(source, slot, count, item)
entry = itemDB:add(item)
else
-- get the metadata from the device and add to db
entry = itemDB:add(source.adapter.getItemMeta(slot))
entry = itemDB:add(source.adapter.getItemDetail(slot))
end
itemDB:flush()
end

41
milo/apis/turtleInv.lua Normal file
View File

@@ -0,0 +1,41 @@
--[[ Emulate a CC:T inventory on the turtle
]]
local TurtleInv = {}
local turtle = _G.turtle
local inventorySize = 16
local localName = "milo_local_name_unset"
function TurtleInv.setLocalName(name)
localName = name
end
function TurtleInv.size()
return inventorySize
end
function TurtleInv.list()
local list = {}
for slot = 1, inventorySize do
list[slot] = turtle.getItemDetail(slot)
end
return list
end
function TurtleInv.getItemDetail(slot)
return turtle.getItemDetail(slot, true)
end
function TurtleInv.pullItems(fromName, fromSlot, limit, toSlot)
return peripheral.call(fromName, "pushItems", localName, fromSlot, limit, toSlot)
end
function TurtleInv.pushItems(toName, fromSlot, limit, toSlot)
return peripheral.call(toName, "pullItems", localName, fromSlot, limit, toSlot)
end
return TurtleInv

View File

@@ -312,14 +312,10 @@ The settings will take effect immediately!]],
margin = 1,
manualControls = true,
[1] = UI.Checkbox {
formLabel = 'Ignore Dmg', formKey = 'ignoreDamage',
help = 'Ignore damage of item',
},
[2] = UI.Checkbox {
formLabel = 'Ignore NBT', formKey = 'ignoreNbtHash',
formLabel = 'Ignore NBT', formKey = 'ignoreNbt',
help = 'Ignore NBT of item',
},
[3] = UI.Chooser {
[2] = UI.Chooser {
width = 13,
formLabel = 'Mode', formKey = 'blacklist',
nochoice = 'whitelist',
@@ -327,7 +323,7 @@ The settings will take effect immediately!]],
{ name = 'whitelist', value = false },
{ name = 'blacklist', value = true },
},
help = 'Ignore damage of item'
help = 'Accept item by default or deny by default'
},
scan = UI.Button {
x = -11, y = 1,
@@ -349,7 +345,7 @@ The settings will take effect immediately!]],
self.form:setValues(entry)
self:resetGrid()
self.form[3].inactive = whitelistOnly
self.form[2].inactive = whitelistOnly
UI.SlideOut.show(self)
self:setFocus(self.form.scan)

View File

@@ -30,7 +30,7 @@ function ExportTask:cycle(context)
end
local function exportSingleSlot()
local slot = node.adapter.getItemMeta(entry.slot)
local slot = node.adapter.getItemDetail(entry.slot)
if slot and slot.count == slot.maxCount then
return
@@ -41,8 +41,7 @@ function ExportTask:cycle(context)
for key in pairs(entry.filter) do
local filterItem = itemDB:splitKey(key)
if (slot.name == filterItem.name and
(entry.ignoreDamage or slot.damage == filterItem.damage) and
(entry.ignoreNbtHash or slot.nbtHash == filterItem.nbtHash)) then
(entry.ignoreNbt or slot.nbt == filterItem.nbt)) then
local items = Milo:getMatches(filterItem, entry)
local _, item = next(items)
@@ -81,8 +80,7 @@ function ExportTask:cycle(context)
for i = 1, node.adapter.__size do
local slot = slots[i]
if (not slot or slot.name == item.name and
(entry.ignoreDamage or slot.damage == item.damage) and
(entry.ignoreNbtHash or slot.nbtHash == item.nbtHash) and
(entry.ignoreNbt or slot.nbt == item.nbt) and
slot.count < item.maxCount) then
return true

View File

@@ -21,7 +21,7 @@ function ImportTask:cycle(context)
for _, entry in pairs(node.imports) do
local function itemMatchesFilter(item)
if not entry.ignoreDamage and not entry.ignoreNbtHash then
if not entry.ignoreNbt then
local key = itemDB:makeKey(item)
return entry.filter[key]
end
@@ -29,8 +29,7 @@ function ImportTask:cycle(context)
for key in pairs(entry.filter) do
local v = itemDB:splitKey(key)
if item.name == v.name and
(entry.ignoreDamage or item.damage == v.damage) and
(entry.ignoreNbtHash or item.nbtHash == v.nbtHash) then
(entry.ignoreNbt or item.nbt == v.nbt) then
return true
end
end
@@ -52,7 +51,7 @@ function ImportTask:cycle(context)
local function importSlot(slotNo)
local item = itemDB:get(list[slotNo], function()
return node.adapter.getItemMeta(slotNo)
return node.adapter.getItemDetail(slotNo)
end)
if item and matchesFilter(item) then
if context.storage:import(node, slotNo, item.count, item) ~= item.count then

View File

@@ -20,16 +20,18 @@ function infoTab:draw()
Ansi.orange, item.displayName, Ansi.reset,
item.name)
if item.nbtHash then
value = value .. item.nbtHash .. '\n'
if item.nbt then
value = value .. item.nbt .. '\n'
end
value = value .. string.format('\n%sCount:%s %s',
Ansi.yellow, Ansi.reset, item.count)
value = value .. string.format('\n%sDamage:%s %s',
Ansi.yellow, Ansi.reset, item.damage)
if item.durability then
value = value .. string.format('\n%Durability:%s %s',
Ansi.yellow, Ansi.reset, item.durability)
end
if item.maxDamage and item.maxDamage > 0 then
value = value .. string.format(' (max: %s)', item.maxDamage)
end

View File

@@ -29,11 +29,7 @@ local manageTab = UI.Tab {
transform = 'number',
},
[4] = UI.Checkbox {
formLabel = 'Ignore Dmg', formKey = 'ignoreDamage',
help = 'Ignore damage of item',
},
[5] = UI.Checkbox {
formLabel = 'Ignore NBT', formKey = 'ignoreNbtHash',
formLabel = 'Ignore NBT', formKey = 'ignoreNbt',
help = 'Ignore NBT of item',
},
},
@@ -44,8 +40,6 @@ function manageTab:setItem(item)
self.res = Util.shallowCopy(context.resources[item.key] or { })
self.res.displayName = self.item.displayName
self.form:setValues(self.res)
-- TODO: ignore damage should not be active if there is not a maxDamage value
end
function manageTab:eventHandler(event)
@@ -76,8 +70,7 @@ function manageTab:eventHandler(event)
local newKey = {
name = self.item.name,
damage = self.res.ignoreDamage and 0 or self.item.damage,
nbtHash = not self.res.ignoreNbtHash and self.item.nbtHash or nil,
nbt = not self.res.ignoreNbt and self.item.nbt or nil,
}
context.resources[self.item.key] = nil

View File

@@ -42,7 +42,7 @@ function recipeTab:setItem(item)
})
end
local key = itemDB:splitKey(self.recipe.result)
self.ignoreResultNBT.inactive = not key.nbtHash
self.ignoreResultNBT.inactive = not key.nbt
end
self.grid:setValues(t)
end
@@ -53,7 +53,7 @@ function recipeTab:eventHandler(event)
Milo:updateRecipe(self.recipe.result)
local item = itemDB:splitKey(self.recipe.result)
item.nbtHash = nil
item.nbt = nil
self.recipe.result = itemDB:makeKey(item)
-- add updated entry
@@ -64,13 +64,13 @@ function recipeTab:eventHandler(event)
elseif event.type == 'grid_focus_row' then
local key = itemDB:splitKey(event.selected.key)
self.ignoreNBT.inactive = not key.nbtHash
self.ignoreNBT.inactive = not key.nbt
self.ignoreNBT:draw()
elseif event.type == 'ignore_nbt' then
local selected = self.grid:getSelected()
local item = itemDB:splitKey(selected.key)
item.nbtHash = nil
item.nbt = nil
selected.key = itemDB:makeKey(item)
self.grid:draw()

View File

@@ -94,7 +94,7 @@ local function client(socket)
local function deposit()
local node = makeNode(data.source or 'inventory')
if node then
local slot = node.adapter.getItemMeta(data.slot)
local slot = node.adapter.getItemDetail(data.slot)
if slot then
if context.storage:import(node, data.slot, slot.count, slot) > 0 then
local item = Milo:getItem(slot)

View File

@@ -15,14 +15,13 @@ function ReplenishTask:cycle(context)
local _, count = Milo:getMatches(item, res)
if count < res.low then
local nbtHash
if not res.ignoreNbtHash then
nbtHash = item.nbtHash
local nbt
if not res.ignoreNbt then
nbt = item.nbt
end
Milo:requestCrafting({
name = item.name,
damage = res.ignoreDamage and 0 or item.damage,
nbtHash = nbtHash,
nbt = nbt,
requested = res.low - count,
count = count,
replenish = true,

View File

@@ -12,7 +12,7 @@ local jua = require("swshop.jua")
local await = jua.await
local device = _G.device
local json = _G.json
local json = { encode=textutils.serializeJSON, decode = textutils.unserialiseJSON }
local rs = _G.rs
local textutils = _G.textutils