225 lines
5.3 KiB
Lua
225 lines
5.3 KiB
Lua
local Event = require('event')
|
|
local Milo = require('milo')
|
|
local Sound = require('sound')
|
|
local Storage = require('milo.storage')
|
|
local UI = require('ui')
|
|
local Util = require('util')
|
|
|
|
local colors = _G.colors
|
|
local device = _G.device
|
|
local fs = _G.fs
|
|
local multishell = _ENV.multishell
|
|
local os = _G.os
|
|
local shell = _ENV.shell
|
|
local turtle = _G.turtle
|
|
|
|
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:
|
|
* Wired modem (activated)
|
|
]])
|
|
|
|
error(msg)
|
|
end
|
|
|
|
local modem
|
|
for _,v in pairs(device) do
|
|
if v.type == 'wired_modem' then
|
|
if modem then
|
|
Syntax('Only 1 wired modem can be connected')
|
|
end
|
|
modem = v
|
|
end
|
|
end
|
|
|
|
if not modem or not modem.getNameLocal then
|
|
Syntax('Wired modem missing')
|
|
end
|
|
|
|
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
|
|
Syntax('Workbench missing')
|
|
end
|
|
end
|
|
|
|
local localName = modem.getNameLocal()
|
|
|
|
local context = {
|
|
resources = Util.readTable(Milo.RESOURCE_FILE) or { },
|
|
|
|
state = { },
|
|
craftingQueue = { },
|
|
tasks = { },
|
|
queue = { },
|
|
plugins = { },
|
|
loggers = { },
|
|
|
|
taskTimer = 0,
|
|
taskCounter = 0,
|
|
|
|
storage = Storage(),
|
|
turtleInventory = {
|
|
name = localName,
|
|
mtype = 'hidden',
|
|
adapter = introspection.getInventory(),
|
|
}
|
|
}
|
|
|
|
context.storage.nodes[localName] = context.turtleInventory
|
|
context.storage.nodes[localName].adapter.name = localName
|
|
|
|
Milo:init(context)
|
|
context.storage:initStorage()
|
|
context.storage.turtleInventory = context.turtleInventory
|
|
|
|
local function loadPlugin(file)
|
|
local s, plugin = Util.run(_ENV, file, context)
|
|
if not s and plugin then
|
|
_G.printError('Error loading: ' .. file)
|
|
error(plugin or 'Unknown error')
|
|
end
|
|
|
|
if plugin and type(plugin) == 'table' then
|
|
Milo:registerPlugin(plugin)
|
|
end
|
|
end
|
|
|
|
local function loadDirectory(dir)
|
|
for _, file in pairs(fs.list(dir)) do
|
|
if not fs.isDir(fs.combine(dir, file)) then
|
|
loadPlugin(fs.combine(dir, file))
|
|
end
|
|
end
|
|
end
|
|
|
|
local programDir = fs.getDir(shell.getRunningProgram())
|
|
loadDirectory(fs.combine(programDir, 'core'))
|
|
loadDirectory(fs.combine(programDir, 'plugins'))
|
|
loadDirectory(fs.combine(programDir, 'plugins/item'))
|
|
|
|
for k in pairs(Milo:getState('plugins') or { }) do
|
|
loadPlugin(k)
|
|
end
|
|
|
|
table.sort(context.tasks, function(a, b)
|
|
return a.priority < b.priority
|
|
end)
|
|
|
|
_G._debug('Tasks\n-----')
|
|
for _, task in ipairs(context.tasks) do
|
|
task.execTime = 0
|
|
_G._debug('%d: %s', task.priority, task.name)
|
|
end
|
|
|
|
Milo:clearGrid()
|
|
|
|
UI:setPage(UI:getPage('listing'))
|
|
Sound.play('ui.toast.challenge_complete')
|
|
|
|
Event.on({ 'milo_cycle', 'milo_queue' }, function(e)
|
|
if context.storage:isOnline() then
|
|
if #context.queue > 0 then
|
|
local queue = context.queue
|
|
context.queue = { }
|
|
for _, entry in pairs(queue) do
|
|
local s, m = pcall(entry.callback, entry.request)
|
|
if not s and m then
|
|
_G._debug('callback crashed')
|
|
_G._debug(m)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if e == 'milo_cycle' and not Milo:isCraftingPaused() then
|
|
local taskTimer = Util.timer()
|
|
Milo:resetCraftingStatus()
|
|
|
|
for _, task in ipairs(context.tasks) do
|
|
local timer = Util.timer()
|
|
local s, m = pcall(function() task:cycle(context) end)
|
|
if not s and m then
|
|
_G._debug(task.name .. ' crashed')
|
|
_G._debug(m)
|
|
end
|
|
task.execTime = task.execTime + timer()
|
|
end
|
|
context.taskTimer = context.taskTimer + taskTimer()
|
|
context.taskCounter = context.taskCounter + 1
|
|
|
|
end
|
|
|
|
if context.storage:isOnline() and #context.queue > 0 then
|
|
os.queueEvent('milo_cycle')
|
|
end
|
|
end)
|
|
|
|
Event.on('turtle_inventory', function()
|
|
Milo:queueRequest({ }, function()
|
|
if not Milo:isCraftingPaused() then
|
|
Milo:clearGrid()
|
|
end
|
|
end)
|
|
end)
|
|
|
|
local cycleHandle
|
|
cycleHandle = Event.onInterval(5, function()
|
|
Event.trigger('milo_cycle')
|
|
if context.taskCounter > 0 then
|
|
--local average = context.taskTimer / context.taskCounter
|
|
--_debug('Interval: ' .. math.max(5, 2 + average * 3))
|
|
--cycleHandle.updateInterval(math.max(5, 2 + average * 3))
|
|
end
|
|
end)
|
|
|
|
Event.on({ 'storage_offline', 'storage_online' }, function()
|
|
if context.storage:isOnline() then
|
|
Milo:resumeCrafting({ key = 'storageOnline' })
|
|
else
|
|
Milo:pauseCrafting({ key = 'storageOnline', msg = 'Storage offline' })
|
|
end
|
|
end)
|
|
|
|
Event.on('terminate', function()
|
|
for _, node in pairs(context.storage.nodes) do
|
|
if node.category == 'display' and node.adapter and node.adapter.clear then
|
|
node.adapter.setBackgroundColor(colors.black)
|
|
node.adapter.clear()
|
|
end
|
|
end
|
|
end)
|
|
|
|
os.queueEvent(
|
|
context.storage:isOnline() and 'storage_online' or 'storage_offline',
|
|
context.storage:isOnline())
|
|
|
|
local oldDebug = _G._debug
|
|
_G._debug = function(...)
|
|
for _,v in pairs(context.loggers) do
|
|
v(...)
|
|
end
|
|
oldDebug(...)
|
|
end
|
|
|
|
local s, m = pcall(function()
|
|
UI:pullEvents()
|
|
end)
|
|
|
|
_G._debug = oldDebug
|
|
if not s then error(m) end
|