milo wip
This commit is contained in:
@@ -1,20 +1,33 @@
|
||||
|
||||
local mon = device.monitor_1
|
||||
mon.clear()
|
||||
mon.setTextScale(.5)
|
||||
_G.requireInjector(_ENV)
|
||||
|
||||
local Util = require('util')
|
||||
|
||||
local device = _G.device
|
||||
local os = _G.os
|
||||
local term = _G.term
|
||||
|
||||
local args = { ... }
|
||||
local mon = device[args[1] or 'monitor'] or error('Syntax: debug <monitor>')
|
||||
|
||||
mon.clear()
|
||||
mon.setTextScale(.5)
|
||||
mon.setCursorPos(1, 1)
|
||||
|
||||
local oldDebug = _G.debug
|
||||
|
||||
_G.debug = function(...)
|
||||
local oldTerm = term.redirect(mon)
|
||||
Util.print(...)
|
||||
term.redirect(oldTerm)
|
||||
local oldTerm = term.redirect(mon)
|
||||
Util.print(...)
|
||||
term.redirect(oldTerm)
|
||||
end
|
||||
|
||||
pcall(read)
|
||||
|
||||
repeat
|
||||
local e, side = os.pullEventRaw('monitor_touch')
|
||||
if e == 'monitor_touch' and side == mon.side then
|
||||
mon.clear()
|
||||
mon.setTextScale(.5)
|
||||
mon.setCursorPos(1, 1)
|
||||
end
|
||||
until e == 'terminate'
|
||||
|
||||
_G.debug = oldDebug
|
||||
|
||||
@@ -61,7 +61,7 @@ replenish
|
||||
autocraft
|
||||
]]
|
||||
|
||||
_G.requireInjector()
|
||||
_G.requireInjector(_ENV)
|
||||
|
||||
local Config = require('config')
|
||||
local Event = require('event')
|
||||
@@ -108,17 +108,39 @@ local context = {
|
||||
userRecipes = Util.readTable(Milo.RECIPES_FILE) or { },
|
||||
learnTypes = { },
|
||||
machineTypes = { },
|
||||
localName = modem.getNameLocal(),
|
||||
}
|
||||
|
||||
local function initStorage()
|
||||
local function initStorage(detachedDevice)
|
||||
debug('Initializing storage')
|
||||
local storage = { }
|
||||
local storageOffline
|
||||
|
||||
-- check to see if any of the storage chests are disconnected
|
||||
for k,v in pairs(config.remoteDefaults) do
|
||||
if v.mtype == 'storage' and device[v.name] then
|
||||
storage[k] = v
|
||||
if v.mtype == 'storage' then
|
||||
if not device[v.name] or v.name == detachedDevice then
|
||||
storageOffline = true
|
||||
else
|
||||
storage[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
debug(storage)
|
||||
|
||||
if storageOffline then
|
||||
Milo:pauseCrafting()
|
||||
debug('Crafting paused')
|
||||
Milo:showError('A storage chest has gone offline, ctrl-l to continue')
|
||||
|
||||
-- todo: just can't resume crafting - need to use offline flag instead
|
||||
-- in the case where crafting was paused already when storage went offline
|
||||
-- ie. in crafting process
|
||||
elseif Milo:isCraftingPaused() then
|
||||
debug('resuming')
|
||||
Milo:resumeCrafting()
|
||||
end
|
||||
|
||||
context.inventoryAdapter = InventoryAdapter.wrap({ remoteDefaults = storage })
|
||||
|
||||
if not context.inventoryAdapter then
|
||||
@@ -138,12 +160,7 @@ Event.on({ 'device_detach' }, function(_, dev)
|
||||
debug('detach: ' .. dev)
|
||||
if config.remoteDefaults[dev] and
|
||||
config.remoteDefaults[dev].mtype == 'storage' then
|
||||
|
||||
Milo:pauseCrafting()
|
||||
debug('Crafting paused')
|
||||
Milo:showError('Check log')
|
||||
|
||||
initStorage()
|
||||
initStorage(dev)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
193
milo/MiloRemote.lua
Normal file
193
milo/MiloRemote.lua
Normal file
@@ -0,0 +1,193 @@
|
||||
_G.requireInjector(_ENV)
|
||||
|
||||
local Socket = require('socket')
|
||||
local UI = require('ui')
|
||||
local Util = require('util')
|
||||
|
||||
local colors = _G.colors
|
||||
|
||||
local socket, msg = Socket.connect(1, 4242)
|
||||
if not socket then
|
||||
error(msg)
|
||||
end
|
||||
|
||||
local page = UI.Page {
|
||||
menuBar = UI.MenuBar {
|
||||
buttons = {
|
||||
{ text = 'Craft', event = 'craft' },
|
||||
{ text = 'Refresh', event = 'refresh', x = -9 },
|
||||
},
|
||||
},
|
||||
grid = UI.Grid {
|
||||
y = 2, ey = -2,
|
||||
columns = {
|
||||
{ heading = ' Qty', key = 'count' , width = 4, justify = 'right' },
|
||||
{ heading = 'Name', key = 'displayName' },
|
||||
},
|
||||
sortColumn = 'displayName',
|
||||
},
|
||||
statusBar = UI.StatusBar {
|
||||
filter = UI.TextEntry {
|
||||
x = 1, ex = -4,
|
||||
limit = 50,
|
||||
shadowText = 'filter',
|
||||
shadowTextColor = colors.gray,
|
||||
backgroundColor = colors.cyan,
|
||||
backgroundFocusColor = colors.cyan,
|
||||
accelerators = {
|
||||
[ 'enter' ] = 'craft',
|
||||
},
|
||||
},
|
||||
display = UI.Button {
|
||||
x = -3,
|
||||
event = 'toggle_display',
|
||||
value = 0,
|
||||
text = 'A',
|
||||
},
|
||||
},
|
||||
notification = UI.Notification(),
|
||||
accelerators = {
|
||||
r = 'refresh',
|
||||
q = 'quit',
|
||||
[ 'control-e' ] = 'eject',
|
||||
[ 'control-r' ] = 'refresh',
|
||||
[ 'control-s' ] = 'eject_stack',
|
||||
[ 'control-1' ] = 'eject_1',
|
||||
[ 'control-2' ] = 'eject_1',
|
||||
[ 'control-3' ] = 'eject_1',
|
||||
[ 'control-4' ] = 'eject_1',
|
||||
[ 'control-5' ] = 'eject_1',
|
||||
[ 'control-6' ] = 'eject_1',
|
||||
[ 'control-7' ] = 'eject_1',
|
||||
[ 'control-8' ] = 'eject_1',
|
||||
[ 'control-9' ] = 'eject_1',
|
||||
[ 'control-0' ] = 'eject_1',
|
||||
[ 'control-m' ] = 'machines',
|
||||
[ 'control-l' ] = 'resume',
|
||||
},
|
||||
displayMode = 0,
|
||||
}
|
||||
|
||||
local function filterItems(t, filter, displayMode)
|
||||
if filter or displayMode > 0 then
|
||||
local r = { }
|
||||
if filter then
|
||||
filter = filter:lower()
|
||||
end
|
||||
for _,v in pairs(t) do
|
||||
if not filter or string.find(v.lname, filter, 1, true) then
|
||||
if not displayMode or
|
||||
displayMode == 0 or
|
||||
displayMode == 1 and v.count > 0 or
|
||||
displayMode == 2 and v.has_recipe then
|
||||
table.insert(r, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function page.statusBar:draw()
|
||||
return UI.Window.draw(self)
|
||||
end
|
||||
|
||||
function page.grid:getRowTextColor(row, selected)
|
||||
if row.is_craftable then
|
||||
return colors.yellow
|
||||
end
|
||||
if row.has_recipe then
|
||||
return colors.cyan
|
||||
end
|
||||
return UI.Grid:getRowTextColor(row, selected)
|
||||
end
|
||||
|
||||
function page.grid:getDisplayValues(row)
|
||||
row = Util.shallowCopy(row)
|
||||
row.count = row.count > 0 and Util.toBytes(row.count) or ''
|
||||
if row.low then
|
||||
row.low = Util.toBytes(row.low)
|
||||
end
|
||||
if row.limit then
|
||||
row.limit = Util.toBytes(row.limit)
|
||||
end
|
||||
return row
|
||||
end
|
||||
|
||||
function page:eventHandler(event)
|
||||
if event.type == 'quit' then
|
||||
UI:exitPullEvents()
|
||||
|
||||
elseif event.type == 'eject' then
|
||||
local item = self.grid:getSelected()
|
||||
if item then
|
||||
socket:write({ request = 'transfer', item = item, count = 1 })
|
||||
end
|
||||
|
||||
elseif event.type == 'eject_stack' then
|
||||
local item = self.grid:getSelected()
|
||||
if item then
|
||||
socket:write({ request = 'transfer', item = item, count = 64 })
|
||||
end
|
||||
|
||||
elseif event.type == 'refresh' then
|
||||
self:refresh()
|
||||
self.grid:draw()
|
||||
self.statusBar.filter:focus()
|
||||
|
||||
elseif event.type == 'toggle_display' then
|
||||
local values = {
|
||||
[0] = 'A',
|
||||
[1] = 'I',
|
||||
[2] = 'C',
|
||||
}
|
||||
|
||||
event.button.value = (event.button.value + 1) % 3
|
||||
self.displayMode = event.button.value
|
||||
event.button.text = values[event.button.value]
|
||||
event.button:draw()
|
||||
self:applyFilter()
|
||||
self.grid:draw()
|
||||
|
||||
elseif event.type == 'text_change' then
|
||||
self.filter = event.text
|
||||
if #self.filter == 0 then
|
||||
self.filter = nil
|
||||
end
|
||||
self:applyFilter()
|
||||
self.grid:draw()
|
||||
self.statusBar.filter:focus()
|
||||
|
||||
else
|
||||
UI.Page.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function page:enable()
|
||||
self:refresh()
|
||||
self:setFocus(self.statusBar.filter)
|
||||
UI.Page.enable(self)
|
||||
end
|
||||
|
||||
function page:refresh()
|
||||
socket:write({ request = 'list' })
|
||||
self.items = socket:read()
|
||||
|
||||
if not self.items then
|
||||
UI:exitPullEvents()
|
||||
else
|
||||
self:applyFilter()
|
||||
end
|
||||
end
|
||||
|
||||
function page:applyFilter()
|
||||
local t = filterItems(self.items, self.filter, self.displayMode)
|
||||
self.grid:setValues(t)
|
||||
end
|
||||
|
||||
UI:setPage(page)
|
||||
UI:pullEvents()
|
||||
|
||||
socket:close()
|
||||
@@ -4,7 +4,6 @@ local itemDB = require('itemDB')
|
||||
local Util = require('util')
|
||||
|
||||
local os = _G.os
|
||||
local term = _G.term
|
||||
local turtle = _G.turtle
|
||||
|
||||
local Milo = {
|
||||
@@ -81,12 +80,7 @@ function Milo:registerTask(task)
|
||||
end
|
||||
|
||||
function Milo:showError(msg)
|
||||
--term.clear()
|
||||
self.context.jobList:showError(msg)
|
||||
--print(msg)
|
||||
--print('rebooting in 5 secs')
|
||||
--os.sleep(5)
|
||||
--os.reboot()
|
||||
end
|
||||
|
||||
function Milo:getItem(items, inItem, ignoreDamage, ignoreNbtHash)
|
||||
|
||||
@@ -118,9 +118,11 @@ function NetworkedAdapter:provide(item, qty, slot, direction)
|
||||
local total = 0
|
||||
|
||||
for _, remote in ipairs(self.remotes) do
|
||||
debug('%s -> slot %d: %d %s', remote.side, slot or -1, qty, item.name)
|
||||
local amount = remote:provide(item, qty, slot, direction)
|
||||
if amount > 0 then
|
||||
debug('%s(%d): %s -> %s%s',
|
||||
item.name, amount, remote.side, direction or self.localName,
|
||||
slot and string.format('[%d]', slot) or '')
|
||||
self.dirty = true
|
||||
remote.dirty = true
|
||||
local entry = self.activity[key] or 0
|
||||
@@ -170,7 +172,9 @@ function NetworkedAdapter:insert(slot, qty, toSlot, item, source)
|
||||
local function insert(remote)
|
||||
local amount = remote:insert(slot, qty, toSlot, source or self.direction)
|
||||
if amount > 0 then
|
||||
debug('%s(%d) -> %s: %d', source or self.localName, slot, remote.side, amount)
|
||||
debug('%s(%d): %s[%d] -> %s',
|
||||
item.name, amount,
|
||||
source or self.localName, slot, remote.side)
|
||||
self.dirty = true
|
||||
remote.dirty = true
|
||||
local entry = self.activity[key] or 0
|
||||
|
||||
@@ -230,7 +230,17 @@ function machineWizard:eventHandler(event)
|
||||
v:save(self.machine)
|
||||
end
|
||||
end
|
||||
context.config.remoteDefaults[self.machine.name] = self.machine
|
||||
context.config.remoteDefaults[self.machine.name] =
|
||||
Util.prune(self.machine, function(v)
|
||||
if type(v) == 'boolean' then
|
||||
return v
|
||||
elseif type(v) == 'string' then
|
||||
return #v > 0
|
||||
elseif type(v) == 'table' then
|
||||
return not Util.empty(v)
|
||||
end
|
||||
return true
|
||||
end)
|
||||
Config.update('milo', context.config)
|
||||
|
||||
UI:setPreviousPage()
|
||||
|
||||
@@ -25,7 +25,7 @@ function ExportTask:cycle(context)
|
||||
item = Milo:getItemWithQty(item)
|
||||
if item and count > 0 then
|
||||
context.inventoryAdapter:provide(
|
||||
itemDB:splitKey(entry.name),
|
||||
item,
|
||||
math.min(count, item.count),
|
||||
entry.slot,
|
||||
target)
|
||||
|
||||
@@ -92,9 +92,9 @@ function itemSlideout.grid:enable()
|
||||
UI.Grid.enable(self)
|
||||
end
|
||||
|
||||
function itemSlideout:show(machine, entry)
|
||||
self.machine = machine
|
||||
function itemSlideout:show(machine, entry, callback)
|
||||
self.entry = entry
|
||||
self.callback = callback
|
||||
|
||||
self.form.choices = { }
|
||||
local m = device[machine.name]
|
||||
@@ -131,8 +131,9 @@ function itemSlideout:eventHandler(event)
|
||||
else
|
||||
self.form:save()
|
||||
self.form.values.name = itemDB:makeKey(selected)
|
||||
table.insert(self.machine.exports, self.form.values)
|
||||
self:hide()
|
||||
debug('calling cllbck')
|
||||
self.callback()
|
||||
end
|
||||
|
||||
elseif event.type == 'cancel' then
|
||||
@@ -194,10 +195,18 @@ end
|
||||
|
||||
function exportView:eventHandler(event)
|
||||
if event.type == 'grid_select' then
|
||||
itemSlideout:show(self.machine, self.grid:getSelected())
|
||||
itemSlideout:show(self.machine, self.grid:getSelected(), function()
|
||||
self.grid:update()
|
||||
self.grid:draw()
|
||||
end)
|
||||
|
||||
elseif event.type == 'add_export' then
|
||||
itemSlideout:show(self.machine, { })
|
||||
local export = { }
|
||||
itemSlideout:show(self.machine, export, function()
|
||||
table.insert(self.machine.exports, export)
|
||||
self.grid:update()
|
||||
self.grid:draw()
|
||||
end)
|
||||
|
||||
elseif event.type == 'remove_export' then
|
||||
local row = self.grid:getSelected()
|
||||
|
||||
@@ -32,10 +32,12 @@ function jobList:showError(msg)
|
||||
end
|
||||
|
||||
function jobList:updateList(craftList)
|
||||
self.grid:setValues(craftList)
|
||||
self.grid:update()
|
||||
self:draw()
|
||||
self:sync()
|
||||
if not Milo:isCraftingPaused() then
|
||||
self.grid:setValues(craftList)
|
||||
self.grid:update()
|
||||
self:draw()
|
||||
self:sync()
|
||||
end
|
||||
end
|
||||
|
||||
function jobList.grid:getRowTextColor(row, selected)
|
||||
|
||||
@@ -78,6 +78,7 @@ local listingPage = UI.Page {
|
||||
notification = UI.Notification(),
|
||||
accelerators = {
|
||||
r = 'refresh',
|
||||
[ 'control-r' ] = 'refresh',
|
||||
q = 'quit',
|
||||
[ 'control-e' ] = 'eject',
|
||||
[ 'control-s' ] = 'eject_stack',
|
||||
|
||||
52
milo/plugins/remote.lua
Normal file
52
milo/plugins/remote.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
local Event = require('event')
|
||||
local Milo = require('milo')
|
||||
local Socket = require('socket')
|
||||
|
||||
local device = _G.device
|
||||
local manipulator = device.manipulator_1
|
||||
local turtle = _G.turtle
|
||||
|
||||
local context = Milo:getContext()
|
||||
|
||||
local function client(socket)
|
||||
repeat
|
||||
local data = socket:read()
|
||||
if not data then
|
||||
break
|
||||
end
|
||||
if data.request == 'list' then
|
||||
local items = Milo:listItems()
|
||||
Milo:mergeResources(items)
|
||||
socket:write(items)
|
||||
|
||||
elseif data.request == 'transfer' then
|
||||
context.inventoryAdapter:provide(
|
||||
data.item,
|
||||
data.count,
|
||||
nil,
|
||||
context.localName)
|
||||
|
||||
turtle.eachFilledSlot(function(slot)
|
||||
manipulator.getInventory().pullItems(
|
||||
context.localName,
|
||||
slot.index,
|
||||
slot.count)
|
||||
end)
|
||||
end
|
||||
until not socket.connected
|
||||
end
|
||||
|
||||
if device.wireless_modem then
|
||||
Event.addRoutine(function()
|
||||
debug('Milo: listening on port 4242')
|
||||
while true do
|
||||
local socket = Socket.server(4242)
|
||||
|
||||
debug('connection from ' .. socket.dhost)
|
||||
|
||||
Event.addRoutine(function()
|
||||
client(socket)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
Reference in New Issue
Block a user