opus/apps/pickup.lua

344 lines
7.5 KiB
Lua

require = requireInjector(getfenv(1))
local GPS = require('gps')
local Socket = require('socket')
local MEProvider = require('meProvider')
local Logger = require('logger')
local Point = require('point')
local process = require('process')
if not device.wireless_modem then
error('Modem is required')
end
Logger.setWirelessLogging()
if not turtle then
error('Can only be run on a turtle')
end
turtle.clearMoveCallback()
local gps = GPS.getPointAndHeading()
if not gps then
error('could not get gps location')
end
turtle.setPoint(gps)
local blocks = { }
local meProvider = MEProvider()
local items = { }
local pickups = Util.readTable('pickup.tbl') or { }
local cells = Util.readTable('cells.tbl') or { }
local refills = Util.readTable('refills.tbl') or { }
local fluids = Util.readTable('fluids.tbl') or { }
local chestPt = turtle.loadLocation('chest')
local chargePt = turtle.loadLocation('charge')
local fuel = {
item = {
id = 'minecraft:coal',
dmg = 0,
},
qty = 64
}
local slots
turtle.setMoveCallback(function(action, pt)
if slots then
for _,slot in pairs(slots) do
if turtle.getItemCount(slot.index) ~= slot.qty then
printError('Slots changed')
process:terminate()
end
end
end
end)
function refuel()
if turtle.getFuelLevel() < 5000 then
print('refueling')
turtle.status = 'refueling'
gotoPoint(chestPt, true)
dropOff(chestPt)
while turtle.getFuelLevel() < 5000 do
turtle.select(1)
meProvider:provide(fuel.item, fuel.qty, 1)
turtle.refuel(64)
print(turtle.getFuelLevel())
os.sleep(1)
end
end
end
function pickUp(pt)
turtle.status = 'picking up'
gotoPoint(pt, true)
while true do
if not turtle.selectOpenSlot() then
dropOff(chestPt)
gotoPoint(pt, true)
end
turtle.select(1)
if not turtle.suckDown(64) then
return
end
end
end
function dropOff(pt)
if turtle.selectSlotWithItems() then
gotoPoint(pt, true)
turtle.emptyInventory(turtle.dropDown)
if pt == chestPt then
print('refreshing items')
items = meProvider:refresh()
end
end
end
function gotoPoint(pt, doDetect)
slots = turtle.getInventory()
while not turtle.pathfind(pt, blocks) do
if turtle.abort then
error('aborted')
end
turtle.status = 'blocked'
os.sleep(5)
end
if doDetect and not turtle.detectDown() then
error('Missing target')
end
end
function checkCell(pt)
if not turtle.selectOpenSlot() then
dropOff(chestPt)
end
print('checking cell')
turtle.status = 'recharging'
gotoPoint(pt, true)
local c = peripheral.wrap('bottom')
local energy = c.getMaxEnergyStored() -
c.getEnergyStored()
if energy > 20000 then
print('charging cell')
turtle.selectOpenSlot()
turtle.digDown()
gotoPoint(chargePt, true)
turtle.dropDown()
os.sleep(energy / 20000)
turtle.suckDown()
print('replacing cell')
gotoPoint(pt)
if not turtle.placeDown() then
error('could not place down cell')
end
end
end
function fluid(points)
print('checking fluid')
turtle.status = 'fluiding'
gotoPoint(points.source, true)
turtle.select(1)
turtle.digDown()
gotoPoint(points.target)
if not turtle.placeDown() then
error('could not place fluid container')
end
os.sleep(5)
turtle.digDown()
gotoPoint(points.source)
turtle.placeDown()
end
function refill(entry)
dropOff(chestPt)
turtle.status = 'refilling'
gotoPoint(chestPt)
for _,item in pairs(entry.items) do
meProvider:provide(item, tonumber(item.qty), turtle.selectOpenSlot())
end
if turtle.selectSlotWithItems() then
if entry.point then
dropOff(entry.point)
end
end
end
function oldRefill(points)
gotoPoint(points.source)
repeat until not turtle.suckDown(64)
if points.target then
dropOff(points.target)
end
if points.targets then
for k,target in pairs(points.targets) do
dropOff(target)
end
end
dropOff(points.source)
dropOff(chestPt)
end
local function makeKey(pt)
return string.format('%d:%d:%d', pt.x, pt.y, pt.z)
end
local function pickupHost(socket)
while true do
local data = socket:read()
if not data then
print('pickup: closing connection to ' .. socket.dhost)
return
end
print('command: ' .. data.type)
if data.type == 'pickup' then
local key = makeKey(data.point)
pickups[key] = data.point
Util.writeTable('pickup.tbl', pickups)
socket:write( { type = "response", response = 'added' })
elseif data.type == 'items' then
socket:write( { type = "response", response = items })
elseif data.type == 'refill' then
local key = makeKey(data.entry.point)
refills[key] = data.entry
Util.writeTable('refills.tbl', refills)
socket:write( { type = "response", response = 'added' })
elseif data.type == 'setPickup' then
chestPt = data.point
turtle.storeLocation('chest', chestPt)
socket:write( { type = "response", response = 'Location set' })
elseif data.type == 'setRecharge' then
chargePt = data.point
turtle.storeLocation('charge', chargePt)
socket:write( { type = "response", response = 'Location set' })
elseif data.type == 'charge' then
local key = makeKey(data.point)
cells[key] = data.point
Util.writeTable('cells.tbl', cells)
socket:write( { type = "response", response = 'added' })
elseif data.type == 'fluid' then
elseif data.type == 'clear' then
local key = makeKey(data.point)
refills[key] = nil
cells[key] = nil
fluids[key] = nil
pickups[key] = nil
Util.writeTable('refills.tbl', refills)
Util.writeTable('cells.tbl', cells)
Util.writeTable('fluids.tbl', fluids)
Util.writeTable('pickup.tbl', pickups)
socket:write( { type = "response", response = 'cleared' })
else
print('unknown command')
end
end
end
process:newThread('pickup', function()
while true do
print('waiting for connection on port 5222')
local socket = Socket.server(5222)
print('pickup: connection from ' .. socket.dhost)
process:newThread('pickup_connection', function() pickupHost(socket) end)
end
end)
local function eachEntry(t, fn)
local keys = Util.keys(t)
for _,key in pairs(keys) do
if t[key] then
if turtle.abort then
return
end
fn(t[key])
end
end
end
local function eachClosestEntry(t, fn)
local points = { }
for k,v in pairs(t) do
v = Util.shallowCopy(v)
v.key = k
table.insert(points, v)
end
while not Util.empty(points) do
local closest = Point.closest(turtle.point, points)
if turtle.abort then
return
end
if t[closest.key] then
fn(closest)
end
for k,v in pairs(points) do
if v.key == closest.key then
table.remove(points, k)
break
end
end
end
end
refuel()
turtle.abort = false
local deliveryThread = process:newThread('deliveries', function()
while true do
if chestPt then
eachClosestEntry(pickups, pickUp)
eachEntry(refills, refill)
refuel()
end
eachEntry(fluids, fluid)
if chargePt then
eachEntry(cells, checkCell)
end
print('sleeping')
turtle.status = 'sleeping'
if turtle.abort then
printError('aborted')
break
end
os.sleep(60)
end
end)
turtle.run(function()
while true do
local e = process:pullEvent()
if e == 'terminate' or deliveryThread:isDead() then
break
end
end
end)
process:threadEvent('terminate')