1
0
mirror of https://github.com/kepler155c/opus synced 2025-10-24 12:17:40 +00:00

bit of everything

This commit is contained in:
kepler155c@gmail.com
2017-07-23 22:37:07 -04:00
parent 027f386ed1
commit f8bcf90a6b
30 changed files with 866 additions and 502 deletions

View File

@@ -14,7 +14,6 @@ local keys = Util.transpose({
})
function ChestProvider:init(args)
local defaults = {
items = { },
name = 'chest',
@@ -43,12 +42,10 @@ function ChestProvider:getCachedItemDetails(item, k)
if not detail then
return
end
-- NOT SUFFICIENT
if detail.name ~= item.name then
return
end
if detail.maxDamage and detail.maxDamage > 0 and detail.damage > 0 then
detail.displayName = detail.displayName .. ' (damaged)'
end
for _,k in ipairs(Util.keys(detail)) do
if not keys[k] then
@@ -135,8 +132,8 @@ function ChestProvider:provide(item, qty, slot, direction)
end
end
function ChestProvider:extract(slot, qty)
self.pushItems(self.direction, slot, qty)
function ChestProvider:extract(slot, qty, toSlot)
self.pushItems(self.direction, slot, qty, toSlot)
end
function ChestProvider:insert(slot, qty)

View File

@@ -1,25 +1,17 @@
local Util = require('util')
local Process = require('process')
local Event = {
uid = 1, -- unique id for handlers
routines = { },
handlers = { namedTimers = { } },
terminate = false,
}
local eventHandlers = {
namedTimers = {}
}
-- debug purposes
function Event.getHandlers()
return eventHandlers
end
function Event.addHandler(type, f)
local event = eventHandlers[type]
local event = Event.handlers[type]
if not event then
event = {}
event.handlers = {}
eventHandlers[type] = event
event = { handlers = { } }
Event.handlers[type] = event
end
local handler = {
@@ -35,7 +27,7 @@ end
function Event.removeHandler(h)
if h and h.event then
eventHandlers[h.event].handlers[h.uid] = nil
Event.handlers[h.event].handlers[h.uid] = nil
end
end
@@ -49,11 +41,11 @@ end
function Event.addNamedTimer(name, interval, recurring, f)
Event.cancelNamedTimer(name)
eventHandlers.namedTimers[name] = Event.addTimer(interval, recurring, f)
Event.handlers.namedTimers[name] = Event.addTimer(interval, recurring, f)
end
function Event.getNamedTimer(name)
return eventHandlers.namedTimers[name]
return Event.handlers.namedTimers[name]
end
function Event.cancelNamedTimer(name)
@@ -64,11 +56,6 @@ function Event.cancelNamedTimer(name)
end
end
function Event.isTimerActive(timer)
return timer.enabled and
os.clock() < timer.start + timer.interval
end
function Event.addTimer(interval, recurring, f)
local timer = Event.addHandler('timer',
function(t, id)
@@ -81,7 +68,6 @@ function Event.addTimer(interval, recurring, f)
end
if t.recurring then
t.fired = false
t.start = os.clock()
t.timerId = os.startTimer(t.interval)
else
Event.removeHandler(t)
@@ -91,103 +77,121 @@ function Event.addTimer(interval, recurring, f)
timer.cf = f
timer.interval = interval
timer.recurring = recurring
timer.start = os.clock()
timer.enabled = true
timer.timerId = os.startTimer(interval)
return timer
end
function Event.removeTimer(h)
Event.removeHandler(h)
function Event.onInterval(interval, f)
return Event.addTimer(interval, true, f)
end
function Event.blockUntilEvent(event, timeout)
return Event.waitForEvent(event, timeout, os.pullEvent)
function Event.onTimeout(timeout, f)
return Event.addTimer(timeout, false, f)
end
function Event.waitForEvent(event, timeout, pullEvent)
pullEvent = pullEvent or Event.pullEvent
function Event.waitForEvent(event, timeout)
local timerId = os.startTimer(timeout)
repeat
local e, p1, p2, p3, p4 = pullEvent()
local e, p1, p2, p3, p4 = os.pullEvent()
if e == event then
return e, p1, p2, p3, p4
end
until e == 'timer' and p1 == timerId
end
local exitPullEvents = false
local function _pullEvents()
while true do
local e = { os.pullEvent() }
Event.processEvent(e)
function Event.addRoutine(routine)
local r = { co = coroutine.create(routine) }
local s, m = coroutine.resume(r.co)
if not s then
error(m or 'Error processing routine')
end
end
function Event.sleep(t)
local timerId = os.startTimer(t or 0)
repeat
local event, id = Event.pullEvent()
until event == 'timer' and id == timerId
end
function Event.addThread(fn)
return Process:addThread(fn)
Event.routines[r] = true
r.filter = m
return r
end
function Event.pullEvents(...)
local routines = { ... }
if #routines > 0 then
Process:addThread(_pullEvents)
for _, routine in ipairs(routines) do
Process:addThread(routine)
end
while true do
local e = Process:pullEvent()
if exitPullEvents or e == 'terminate' then
break
end
end
else
while true do
local e = { os.pullEventRaw() }
Event.processEvent(e)
if exitPullEvents or e[1] == 'terminate' then
break
end
end
for _, r in ipairs({ ... }) do
Event.addRoutine(r)
end
repeat
local e = Event.pullEvent()
until e[1] == 'terminate'
end
function Event.exitPullEvents()
exitPullEvents = true
Event.terminate = true
os.sleep(0)
end
function Event.pullEvent(eventType)
local e = { os.pullEventRaw(eventType) }
return Event.processEvent(e)
while true do
local e = { os.pullEventRaw() }
local routines = Util.keys(Event.routines)
for _, r in ipairs(routines) do
if not r.filter or r.filter == e[1] then
local s, m = coroutine.resume(r.co, table.unpack(e))
if not s and e[1] ~= 'terminate' then
debug({s, m})
debug(r)
error(m or 'Error processing event')
end
if coroutine.status(r.co) == 'dead' then
r.co = nil
Event.routines[r] = nil
else
r.filter = m
end
end
end
Event.processEvent(e)
if Event.terminate or e[1] == 'terminate' then
Event.terminate = false
return { 'terminate' }
end
if not eventType or e[1] == eventType then
return e
end
end
end
function Event.processEvent(pe)
local e, p1, p2, p3, p4, p5 = unpack(pe)
local event = eventHandlers[e]
local event = Event.handlers[e]
if event then
local keys = Util.keys(event.handlers)
for _,key in pairs(keys) do
local h = event.handlers[key]
if h then
h.f(h, p1, p2, p3, p4, p5)
if h and not h.co then
local co = coroutine.create(function()
h.f(h, p1, p2, p3, p4, p5)
end)
local s, m = coroutine.resume(co)
if not s then
debug({s, m})
debug(h)
error(m or 'Error processing ' .. e)
elseif coroutine.status(co) ~= 'dead' then
h.co = co
h.filter = m
Event.routines[h] = true
end
end
end
end
return e, p1, p2, p3, p4, p5
end
Event.on = Event.addHandler
Event.off = Event.removeHandler
return Event

View File

@@ -12,9 +12,9 @@ local PASTEBIN_URL = 'http://pastebin.com/raw'
local GIT_URL = 'https://raw.githubusercontent.com'
local function standardSearcher(modname, env, shell)
if package.loaded[modname] then
if _G.package.loaded[modname] then
return function()
return package.loaded[modname]
return _G.package.loaded[modname]
end
end
end
@@ -33,7 +33,7 @@ end
local function pathSearcher(modname, env, shell)
local fname = modname:gsub('%.', '/') .. '.lua'
for dir in string.gmatch(package.path, "[^:]+") do
for dir in string.gmatch(_G.package.path, "[^:]+") do
local path = fs.combine(dir, fname)
if fs.exists(path) and not fs.isDir(path) then
return loadfile(path, env)
@@ -109,7 +109,7 @@ local function urlSearcher(modname, env, shell)
local fname = modname:gsub('%.', '/') .. '.lua'
if fname:sub(1, 1) ~= '/' then
for entry in string.gmatch(package.upath, "[^;]+") do
for entry in string.gmatch(_G.package.upath, "[^;]+") do
local url = entry .. '/' .. fname
local c = loadUrl(url)
if c then
@@ -150,7 +150,7 @@ local function requireWrapper(env)
return loaded[modname]
end
for _,searcher in ipairs(package.loaders) do
for _,searcher in ipairs(_G.package.loaders) do
local fn, msg = searcher(modname, env, shell)
if fn then
local module, msg = fn(modname, env)

View File

@@ -1,6 +1,6 @@
local TableDB = require('tableDB')
local itemDB = TableDB({ fileName = 'usr/config/items.db' })
local itemDB = TableDB({ fileName = 'usr/etc/items.db' })
function itemDB:get(key)
@@ -13,6 +13,9 @@ function itemDB:get(key)
if key[2] ~= 0 then
item = TableDB.get(self, { key[1], 0, key[3] })
if item and item.maxDamage > 0 then
item = Util.shallowCopy(item)
item.damage = key[2]
item.displayName = string.format('%s (damage: %d)', item.displayName, item.damage)
return item
end
end

View File

@@ -50,7 +50,12 @@ function Peripheral.addDevice(deviceList, side)
name = uniqueName
end
deviceList[name] = peripheral.wrap(side)
local s, m pcall(function() deviceList[name] = peripheral.wrap(side) end)
if not s and m then
printError('wrap failed')
printError(m)
end
if deviceList[name] then
Util.merge(deviceList[name], {
name = name,

View File

@@ -4,13 +4,19 @@ function Point.copy(pt)
return { x = pt.x, y = pt.y, z = pt.z }
end
function Point.same(pta, ptb)
return pta.x == ptb.x and
pta.y == ptb.y and
pta.z == ptb.z
end
function Point.subtract(a, b)
a.x = a.x - b.x
a.y = a.y - b.y
a.z = a.z - b.z
end
-- real distance
-- Euclidian distance
function Point.pythagoreanDistance(a, b)
return math.sqrt(
math.pow(a.x - b.x, 2) +
@@ -18,7 +24,7 @@ function Point.pythagoreanDistance(a, b)
math.pow(a.z - b.z, 2))
end
-- turtle distance
-- turtle distance (manhattan)
function Point.turtleDistance(a, b)
if a.y and b.y then
return math.abs(a.x - b.x) +
@@ -40,6 +46,35 @@ function Point.calculateTurns(ih, oh)
return 1
end
function Point.calculateHeading(pta, ptb)
local heading
if (pta.heading % 2) == 0 and pta.z ~= ptb.z then
if ptb.z > pta.z then
heading = 1
else
heading = 3
end
elseif (pta.heading % 2) == 1 and pta.x ~= ptb.x then
if ptb.x > pta.x then
heading = 0
else
heading = 2
end
elseif pta.heading == 0 and pta.x > ptb.x then
heading = 2
elseif pta.heading == 2 and pta.x < ptb.x then
heading = 0
elseif pta.heading == 1 and pta.z > ptb.z then
heading = 3
elseif pta.heading == 3 and pta.z < ptb.z then
heading = 1
end
return heading or pta.heading
end
-- Calculate distance to location including turns
-- also returns the resulting heading
function Point.calculateMoves(pta, ptb, distance)
@@ -88,6 +123,32 @@ function Point.closest(reference, pts)
return lpt
end
-- find the closest block
-- * favor same plane
-- * going backwards only if the dest is above or below
function Point.closest2(reference, pts)
local lpt, lm -- lowest
for _,pt in pairs(pts) do
local m = Point.turtleDistance(reference, pt)
local h = Point.calculateHeading(reference, pt)
local t = Point.calculateTurns(reference.heading, h)
if pt.y ~= reference.y then -- try and stay on same plane
m = m + .01
end
if t ~= 2 or pt.y == reference.y then
m = m + t
if t > 0 then
m = m + .01
end
end
if not lm or m < lm then
lpt = pt
lm = m
end
end
return lpt
end
function Point.adjacentPoints(pt)
local pts = { }

View File

@@ -48,9 +48,6 @@ function RefinedProvider:getCachedItemDetails(item)
return
end
Util.merge(detail, meta)
if detail.maxDamage and detail.maxDamage > 0 and detail.damage > 0 then
detail.displayName = detail.displayName .. ' (damaged)'
end
detail.lname = detail.displayName:lower()
local t = { }

View File

@@ -100,15 +100,15 @@ function Schematic:parse(a, h, containsName, spinner)
local i4 = h:readbyte(h)
local i = bit.blshift(i1, 24) + bit.blshift(i2, 16) + bit.blshift(i3, 8) + i4
if not self.length or not self.width then
self:discardBytes(h,i, spinner)
self.twopass = true
elseif name == "Blocks" then
if name == "Blocks" then
for i = 1, i do
local id = h:readbyte(h)
self:assignCoord(i, id)
if id > 0 then
table.insert(self.blocks, {
id = id,
index = i,
})
end
if (i % 1000) == 0 then
spinner:spin()
end
@@ -269,15 +269,36 @@ function Schematic:loadpass(fh, spinner)
break
end
self:parse(a, fh, true, spinner)
if self.twopass and self.width and self.length then
break
end
spinner:spin()
end
fh:close()
print('Assigning coords ')
local index = 1
for _, b in ipairs(self.blocks) do
while index < b.index do
self.x = self.x + 1
if self.x >= self.width then
self.x = 0
self.z = self.z + 1
end
if self.z >= self.length then
self.z = 0
self.y = self.y + 1
end
if self.y >= self.height then
self.height = self.y + 1
end
index = index + 1
end
b.x = self.x
b.y = self.y
b.z = self.z
spinner:spin()
end
self:assignDamages(spinner)
self.damages = nil
@@ -313,22 +334,9 @@ function Schematic:load(filename)
self:checkFileType(f)
print('Initial pass ')
print('Loading blocks ')
self:loadpass(f, spinner)
if self.twopass then
self.twopass = nil
self.blocks = { }
self.damages = { }
self.originalBlocks = { }
self.x, self.y, self.z = 0, 0, 0
self.height = 0
self.index = 1
print('Second pass ')
self:loadpass(f, spinner)
end
self.rowIndex = { }
for k,b in ipairs(self.blocks) do
local ri = self.rowIndex[b.y]
@@ -342,42 +350,12 @@ function Schematic:load(filename)
self.cache = Util.readTable('usr/builder/' .. self.filename .. '.cache') or { }
end
function Schematic:assignCoord(i, id)
if id > 0 then
table.insert(self.blocks, {
id = id,
index = i,
x = self.x,
z = self.z,
y = self.y,
})
end
self.x = self.x + 1
if self.x >= self.width then
self.x = 0
self.z = self.z + 1
end
if self.z >= self.length then
self.z = 0
self.y = self.y + 1
end
if self.y >= self.height then
self.height = self.y + 1
end
end
function Schematic:assignDamages(spinner)
print('Assigning damages')
local i = 0
for _,b in pairs(self.blocks) do
b.dmg = self.damages[b.index] or 0
i = i + 1
if (i % 1000) == 0 then
spinner:spin()
end
spinner:spin()
end
end
@@ -849,6 +827,7 @@ function Schematic:getComputedBlock(i)
-- has this level been computed ?
if not self.rowIndex[b.y].loaded then
-- compute each level up til this one (unless saved in cache)
for y = 0, b.y - 1 do
if not self.cache[y] then
self:determineBlockPlacement(y)
@@ -858,7 +837,6 @@ function Schematic:getComputedBlock(i)
-- get the block now at the computed location
b = self.blocks[i]
end
return b
end

View File

@@ -67,7 +67,7 @@ function Manager:init(args)
local mouseDragged = false
local pages = { }
Event.addHandler('term_resize', function(h, side)
Event.on('term_resize', function(h, side)
if self.currentPage then
-- the parent doesn't have any children set...
-- that's why we have to resize both the parent and the current page
@@ -81,7 +81,7 @@ function Manager:init(args)
end
end)
Event.addHandler('mouse_scroll', function(h, direction, x, y)
Event.on('mouse_scroll', function(h, direction, x, y)
if self.target then
local event = self:pointToChild(self.target, x, y)
local directions = {
@@ -97,7 +97,7 @@ function Manager:init(args)
end)
-- this should be moved to the device !
Event.addHandler('monitor_touch', function(h, side, x, y)
Event.on('monitor_touch', function(h, side, x, y)
if self.currentPage then
if self.currentPage.parent.device.side == side then
self:click(1, x, y)
@@ -105,7 +105,7 @@ function Manager:init(args)
end
end)
Event.addHandler('mouse_click', function(h, button, x, y)
Event.on('mouse_click', function(h, button, x, y)
mouseDragged = false
if button == 1 and shift and control then -- debug hack
@@ -123,7 +123,7 @@ function Manager:init(args)
end
end)
Event.addHandler('mouse_up', function(h, button, x, y)
Event.on('mouse_up', function(h, button, x, y)
if self.currentPage and not mouseDragged then
if not self.currentPage.parent.device.side then
@@ -132,7 +132,7 @@ function Manager:init(args)
end
end)
Event.addHandler('mouse_drag', function(h, button, x, y)
Event.on('mouse_drag', function(h, button, x, y)
mouseDragged = true
if self.target then
@@ -146,7 +146,7 @@ function Manager:init(args)
end
end)
Event.addHandler('paste', function(h, text)
Event.on('paste', function(h, text)
if clipboard.isInternal() then
text = clipboard.getData()
end
@@ -156,7 +156,7 @@ function Manager:init(args)
end
end)
Event.addHandler('char', function(h, ch)
Event.on('char', function(h, ch)
control = false
if self.currentPage then
self:inputEvent(self.currentPage.focused, { type = 'key', key = ch })
@@ -164,7 +164,7 @@ function Manager:init(args)
end
end)
Event.addHandler('key_up', function(h, code)
Event.on('key_up', function(h, code)
if code == keys.leftCtrl or code == keys.rightCtrl then
control = false
elseif code == keys.leftShift or code == keys.rightShift then
@@ -172,7 +172,7 @@ function Manager:init(args)
end
end)
Event.addHandler('key', function(h, code)
Event.on('key', function(h, code)
local ch = keys.getName(code)
if not ch then
return
@@ -1282,6 +1282,8 @@ function UI.Device:runTransitions(transitions, canvas)
if Util.empty(transitions) then
break
end
os.sleep(0)
--[[
local timerId = os.startTimer(0)
while true do
local e = { os.pullEvent() }
@@ -1290,10 +1292,11 @@ function UI.Device:runTransitions(transitions, canvas)
end
table.insert(queue, e)
end
--]]
end
for _, e in ipairs(queue) do
Event.processEvent(e)
end
-- for _, e in ipairs(queue) do
-- Event.processEvent(e)
-- end
end
function UI.Device:sync()