refactor builder
This commit is contained in:
126
apis/builder/builder.lua
Normal file
126
apis/builder/builder.lua
Normal file
@@ -0,0 +1,126 @@
|
||||
local Blocks = require('blocks')
|
||||
local Message = require('message')
|
||||
local Util = require('util')
|
||||
|
||||
local device = _G.device
|
||||
local fs = _G.fs
|
||||
local turtle = _G.turtle
|
||||
|
||||
local Builder = {
|
||||
isCommandComputer = not turtle,
|
||||
slots = { },
|
||||
loc = { },
|
||||
index = 1,
|
||||
mode = 'build',
|
||||
fuelItem = { id = 'minecraft:coal', dmg = 0 },
|
||||
resourceSlots = 14,
|
||||
facing = 'south',
|
||||
wrenchSucks = false,
|
||||
stairBug = false,
|
||||
}
|
||||
|
||||
local BUILDER_DIR = 'usr/builder'
|
||||
|
||||
local blockInfo = Blocks()
|
||||
|
||||
function Builder:getBlockCounts()
|
||||
local blocks = { }
|
||||
|
||||
-- add a couple essential items to the supply list to allow replacements
|
||||
if not self.isCommandComputer then
|
||||
local wrench = self.subDB:getSubstitutedItem('SubstituteAWrench', 0)
|
||||
wrench.qty = 0
|
||||
wrench.need = 1
|
||||
blocks[wrench.id .. ':' .. wrench.dmg] = wrench
|
||||
|
||||
local fuel = self.subDB:getSubstitutedItem(Builder.fuelItem.id, Builder.fuelItem.dmg)
|
||||
fuel.qty = 0
|
||||
fuel.need = 1
|
||||
blocks[fuel.id .. ':' .. fuel.dmg] = fuel
|
||||
|
||||
blocks['minecraft:piston:0'] = {
|
||||
id = 'minecraft:piston',
|
||||
dmg = 0,
|
||||
qty = 0,
|
||||
need = 1,
|
||||
}
|
||||
end
|
||||
|
||||
for k = self.index, #self.schematic.blocks do
|
||||
local b = self.schematic.blocks[k]
|
||||
local key = tostring(b.id) .. ':' .. b.dmg
|
||||
local block = blocks[key]
|
||||
if not block then
|
||||
block = Util.shallowCopy(b)
|
||||
block.qty = 0
|
||||
block.need = 0
|
||||
blocks[key] = block
|
||||
end
|
||||
block.need = block.need + 1
|
||||
end
|
||||
|
||||
return blocks
|
||||
end
|
||||
|
||||
function Builder:substituteBlocks(throttle)
|
||||
for _,b in pairs(self.schematic.blocks) do
|
||||
|
||||
-- replace schematic block type with substitution
|
||||
local pb = blockInfo:getPlaceableBlock(b.id, b.dmg)
|
||||
|
||||
Util.merge(b, pb)
|
||||
|
||||
b.odmg = pb.odmg or pb.dmg
|
||||
|
||||
local sub = self.subDB:get({ b.id, b.dmg })
|
||||
if sub then
|
||||
b.id, b.dmg = self.subDB:extract(sub)
|
||||
end
|
||||
throttle()
|
||||
end
|
||||
end
|
||||
|
||||
function Builder:reloadSchematic(throttle)
|
||||
self.schematic:reload(throttle)
|
||||
self:substituteBlocks(throttle)
|
||||
end
|
||||
|
||||
function Builder:log(...)
|
||||
Util.print(...)
|
||||
end
|
||||
|
||||
function Builder:dumpInventory()
|
||||
end
|
||||
|
||||
function Builder:logBlock(index, b)
|
||||
local bdir = b.direction or ''
|
||||
local logText = string.format('%d %s:%d (x:%d,z:%d:y:%d) %s',
|
||||
index, b.id, b.dmg, b.x, b.z, b.y, bdir)
|
||||
self:log(logText)
|
||||
-- self:log(b.index) -- unique identifier of block
|
||||
|
||||
if device.wireless_modem then
|
||||
Message.broadcast('builder', { x = b.x, y = b.y, z = b.z, heading = b.heading })
|
||||
end
|
||||
end
|
||||
|
||||
function Builder:saveProgress(index)
|
||||
Util.writeTable(
|
||||
fs.combine(BUILDER_DIR, self.schematic.filename .. '.progress'),
|
||||
{ index = index, facing = Builder.facing, loc = Builder.loc }
|
||||
)
|
||||
end
|
||||
|
||||
function Builder:loadProgress(filename)
|
||||
local progress = Util.readTable(fs.combine(BUILDER_DIR, filename))
|
||||
if progress then
|
||||
Builder.index = progress.index
|
||||
if Builder.index > #self.schematic.blocks then
|
||||
Builder.index = 1
|
||||
end
|
||||
Builder.facing = progress.facing or 'south'
|
||||
Builder.loc = progress.loc or { }
|
||||
end
|
||||
end
|
||||
|
||||
return Builder
|
||||
81
apis/builder/commands.lua
Normal file
81
apis/builder/commands.lua
Normal file
@@ -0,0 +1,81 @@
|
||||
local Builder = require('builder.builder')
|
||||
local Event = require('event')
|
||||
local Util = require('util')
|
||||
|
||||
local commands = _G.commands
|
||||
local fs = _G.fs
|
||||
local os = _G.os
|
||||
local read = _G.read
|
||||
|
||||
function Builder:begin()
|
||||
local direction = 1
|
||||
local last = #self.schematic.blocks
|
||||
local throttle = Util.throttle()
|
||||
|
||||
if self.mode == 'destroy' then
|
||||
direction = -1
|
||||
last = 1
|
||||
end
|
||||
|
||||
for i = self.index, last, direction do
|
||||
self.index = i
|
||||
|
||||
local b = self.schematic:getComputedBlock(i)
|
||||
|
||||
if b.id ~= 'minecraft:air' then
|
||||
|
||||
self:logBlock(self.index, b)
|
||||
|
||||
local id = b.id
|
||||
if self.mode == 'destroy' then
|
||||
id = 'minecraft:air'
|
||||
end
|
||||
|
||||
local function placeBlock(bid, dmg, x, y, z)
|
||||
local cx, _, cz = commands.getBlockPosition()
|
||||
|
||||
local command = table.concat({
|
||||
"setblock",
|
||||
cx + x + 1,
|
||||
"~" .. y,
|
||||
cz + z + 1,
|
||||
bid,
|
||||
dmg,
|
||||
}, ' ')
|
||||
|
||||
commands.execAsync(command)
|
||||
|
||||
local result = { os.pullEvent("task_complete") }
|
||||
if not result[4] then
|
||||
Util.print(result[5])
|
||||
if self.mode ~= 'destroy' then
|
||||
read()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
placeBlock(id, b.odmg, b.x, b.y, b.z)
|
||||
|
||||
if b.twoHigh then
|
||||
local _, topBlock = self.schematic:findIndexAt(b.x, b.z, b.y + 1, true)
|
||||
if topBlock then
|
||||
placeBlock(id, topBlock.odmg, b.x, b.y + 1, b.z)
|
||||
end
|
||||
end
|
||||
|
||||
if self.mode == 'destroy' then
|
||||
self:saveProgress(math.max(self.index, 1))
|
||||
else
|
||||
self:saveProgress(self.index + 1)
|
||||
end
|
||||
else
|
||||
throttle() -- sleep in case there are a large # of skipped blocks
|
||||
end
|
||||
end
|
||||
|
||||
fs.delete(self.schematic.filename .. '.progress')
|
||||
print('Finished')
|
||||
Event.exitPullEvents()
|
||||
end
|
||||
|
||||
return Builder
|
||||
1253
apis/builder/turtle.lua
Normal file
1253
apis/builder/turtle.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,31 @@ local Point = require('point')
|
||||
local bit = _G.bit
|
||||
local fs = _G.fs
|
||||
local term = _G.term
|
||||
local turtle = _G.turtle
|
||||
|
||||
local headings = {
|
||||
[ 0 ] = { xd = 1, zd = 0, yd = 0, heading = 0, direction = 'east' },
|
||||
[ 1 ] = { xd = 0, zd = 1, yd = 0, heading = 1, direction = 'south' },
|
||||
[ 2 ] = { xd = -1, zd = 0, yd = 0, heading = 2, direction = 'west' },
|
||||
[ 3 ] = { xd = 0, zd = -1, yd = 0, heading = 3, direction = 'north' },
|
||||
[ 4 ] = { xd = 0, zd = 0, yd = 1, heading = 4, direction = 'up' },
|
||||
[ 5 ] = { xd = 0, zd = 0, yd = -1, heading = 5, direction = 'down' }
|
||||
}
|
||||
|
||||
local namedHeadings = {
|
||||
east = headings[0],
|
||||
south = headings[1],
|
||||
west = headings[2],
|
||||
north = headings[3],
|
||||
up = headings[4],
|
||||
down = headings[5]
|
||||
}
|
||||
|
||||
local function getHeadingInfo(heading)
|
||||
if heading and type(heading) == 'string' then
|
||||
return namedHeadings[heading]
|
||||
end
|
||||
return headings[heading]
|
||||
end
|
||||
|
||||
--[[
|
||||
Loading and manipulating a schematic
|
||||
@@ -431,7 +455,7 @@ function Schematic:findIndexAt(x, z, y, allBlocks)
|
||||
end
|
||||
|
||||
function Schematic:findBlockAtSide(b, side)
|
||||
local hi = turtle.getHeadingInfo(side)
|
||||
local hi = getHeadingInfo(side)
|
||||
local index = self:findIndexAt(b.x + hi.xd, b.z + hi.zd, b.y + hi.yd)
|
||||
if index then
|
||||
return self.blocks[index] -- could be better
|
||||
@@ -465,10 +489,10 @@ function Schematic:bestSide(b, chains, ...)
|
||||
local blocks = { }
|
||||
|
||||
for k,d in pairs(directions) do
|
||||
local hi = turtle.getHeadingInfo(d)
|
||||
local hi = getHeadingInfo(d)
|
||||
local sb = self:findIndexAt(b.x - hi.xd, b.z - hi.zd, b.y)
|
||||
if not sb then
|
||||
b.heading = turtle.getHeadingInfo(d).heading
|
||||
b.heading = getHeadingInfo(d).heading
|
||||
b.direction = d .. '-block'
|
||||
return
|
||||
end
|
||||
@@ -525,7 +549,7 @@ function Schematic:bestFlipSide(b, chains)
|
||||
}
|
||||
|
||||
local d = directions[b.direction]
|
||||
local hi = turtle.getHeadingInfo(d)
|
||||
local hi = getHeadingInfo(d)
|
||||
local _, fb = self:findIndexAt(b.x + hi.xd, b.z + hi.zd, b.y)
|
||||
|
||||
if fb then
|
||||
@@ -541,7 +565,7 @@ function Schematic:bestFlipSide(b, chains)
|
||||
{ x = b.x - hi.xd, z = b.z - hi.zd, y = b.y }, -- room for the turtle
|
||||
{ x = b.x + hi.xd, z = b.z + hi.zd, y = b.y }, -- block we are placing against
|
||||
})
|
||||
b.direction = turtle.getHeadingInfo((hi.heading + 2) % 4).direction .. '-block'
|
||||
b.direction = getHeadingInfo((hi.heading + 2) % 4).direction .. '-block'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -581,7 +605,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
|
||||
table.insert(pc, { x = b.x, z = b.z, y = b.y })
|
||||
|
||||
b.direction = side1 .. '-block'
|
||||
b.heading = turtle.getHeadingInfo(side1).heading
|
||||
b.heading = getHeadingInfo(side1).heading
|
||||
|
||||
if b == lb then
|
||||
break
|
||||
@@ -599,7 +623,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
|
||||
local ub = self:findBlockAtSide(fb, 'down')
|
||||
if not ub then
|
||||
fb.direction = side1 .. '-block'
|
||||
fb.heading = turtle.getHeadingInfo(side1).heading
|
||||
fb.heading = getHeadingInfo(side1).heading
|
||||
else
|
||||
fb.direction = od
|
||||
end
|
||||
@@ -613,7 +637,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
|
||||
local ub = self:findBlockAtSide(lb, 'down')
|
||||
if not ub then
|
||||
lb.direction = side1 .. '-block'
|
||||
lb.heading = turtle.getHeadingInfo(side1).heading
|
||||
lb.heading = getHeadingInfo(side1).heading
|
||||
else
|
||||
fb.direction = od
|
||||
end
|
||||
@@ -758,12 +782,12 @@ function Schematic:determineBlockPlacement(y)
|
||||
spinner:spin(#dirtyBlocks + #dirtyBlocks2 .. ' blocks remaining ')
|
||||
|
||||
if directions[d] then
|
||||
b.heading = turtle.getHeadingInfo(directions[d]).heading
|
||||
b.heading = getHeadingInfo(directions[d]).heading
|
||||
end
|
||||
|
||||
if doorDirections[d] then
|
||||
|
||||
local hi = turtle.getHeadingInfo(doorDirections[d])
|
||||
local hi = getHeadingInfo(doorDirections[d])
|
||||
b.heading = hi.heading
|
||||
|
||||
self:addPlacementChain(chains, {
|
||||
@@ -775,9 +799,9 @@ function Schematic:determineBlockPlacement(y)
|
||||
if stairDownDirections[d] then
|
||||
if not self:findIndexAt(b.x, b.z, b.y-1) then
|
||||
b.direction = stairDownDirections[b.direction]
|
||||
b.heading = turtle.getHeadingInfo(b.direction).heading
|
||||
b.heading = getHeadingInfo(b.direction).heading
|
||||
else
|
||||
b.heading = turtle.getHeadingInfo(stairDownDirections[b.direction]).heading
|
||||
b.heading = getHeadingInfo(stairDownDirections[b.direction]).heading
|
||||
end
|
||||
end
|
||||
|
||||
@@ -816,7 +840,7 @@ function Schematic:determineBlockPlacement(y)
|
||||
if self:findIndexAt(b.x, b.z, b.y-1) then
|
||||
-- there's a block below
|
||||
b.direction = sd[1]
|
||||
b.heading = turtle.getHeadingInfo(b.direction).heading
|
||||
b.heading = getHeadingInfo(b.direction).heading
|
||||
else
|
||||
local _,pb = self:findIndexAt(b.x + sd[3], b.z + sd[4], b.y)
|
||||
if pb and pb.direction ~= sd[5] then
|
||||
@@ -824,7 +848,7 @@ function Schematic:determineBlockPlacement(y)
|
||||
d = sd[2] -- fall through to the blockDirections code below
|
||||
b.direction = sd[2]
|
||||
else
|
||||
b.heading = (turtle.getHeadingInfo(sd[1]).heading + 2) % 4
|
||||
b.heading = (getHeadingInfo(sd[1]).heading + 2) % 4
|
||||
end
|
||||
end
|
||||
elseif flipDirections[d] then
|
||||
@@ -833,7 +857,7 @@ function Schematic:determineBlockPlacement(y)
|
||||
|
||||
if blockDirections[d] then
|
||||
-- placing a block from the side
|
||||
local hi = turtle.getHeadingInfo(blockDirections[d])
|
||||
local hi = getHeadingInfo(blockDirections[d])
|
||||
b.heading = hi.heading
|
||||
self:addPlacementChain(chains, {
|
||||
{ x = b.x + hi.xd, z = b.z + hi.zd, y = b.y }, -- block we are placing against
|
||||
|
||||
1418
apps/builder.lua
1418
apps/builder.lua
File diff suppressed because it is too large
Load Diff
53
apps/hijack.lua
Normal file
53
apps/hijack.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
_G.requireInjector()
|
||||
|
||||
local Socket = require('socket')
|
||||
|
||||
if not ... then
|
||||
local turtle = _G.turtle
|
||||
|
||||
while true do
|
||||
print('hijack: waiting for connections')
|
||||
local socket = Socket.server(188)
|
||||
|
||||
print('hijack: connection from ' .. socket.dhost)
|
||||
|
||||
local methods = { }
|
||||
for k,v in pairs(turtle) do
|
||||
if type(v) == 'function' then
|
||||
table.insert(methods, k)
|
||||
end
|
||||
end
|
||||
socket:write(methods)
|
||||
|
||||
while true do
|
||||
local data = socket:read()
|
||||
if not data then
|
||||
break
|
||||
end
|
||||
socket:write({ turtle[data.fn](unpack(data.args)) })
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
local remoteId = ({ ... })[1]
|
||||
local socket, msg = Socket.connect(remoteId, 188)
|
||||
|
||||
if not socket then
|
||||
error(msg)
|
||||
end
|
||||
|
||||
local methods = socket:read()
|
||||
|
||||
local turtle = { }
|
||||
for _,method in pairs(methods) do
|
||||
turtle[method] = function(...)
|
||||
socket:write({ fn = method, args = { ... } })
|
||||
local resp = socket:read()
|
||||
return table.unpack(resp)
|
||||
end
|
||||
end
|
||||
|
||||
_G.turtle = turtle
|
||||
os.pullEventRaw('terminate')
|
||||
socket:close()
|
||||
end
|
||||
Reference in New Issue
Block a user