mirror of
https://github.com/kepler155c/opus
synced 2024-11-05 08:26:16 +00:00
344 lines
7.5 KiB
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')
|