Playing around controlling multiple turtles. I thought this turned out pretty good.
Basically, I'm running all the turtles as if they were local to the pocket computer. This approach greatly simplifies multi-turtle programs. Note that the turtle functions I use are somewhat high-level (I just need to tell the turtle at what coordinates to place each block). I also notify each turtle when a block is placed so the path finding algorithm is more efficient.
I've added this support to the develop branch only as I'm still improving the code.
Spoiler
_G.requireInjector()
local Event = require('event')
local GPS = require('gps')
local Point = require('point')
local Socket = require('socket')
local Util = require('util')
local os = _G.os
local template = { }
template[1] = {
{ 3,3,3,3,3 },
{ 1,4,4,4,1 },
{ 1,4,0,4,1 },
{ 1,4,0,4,1 },
{ 1,1,1,1,1 },
}
template[2] = {
{ 3,4,4,4,3 },
{ 4,0,0,0,4 },
{ 4,0,0,0,4 },
{ 4,0,0,0,4 },
{ 1,1,1,1,1 },
}
template[3] = {
{ 3,4,4,4,3 },
{ 4,0,0,0,4 },
{ 5,0,0,0,5 },
{ 4,0,0,0,4 },
{ 1,1,1,1,1 },
}
template[4] = template[2]
template[5] = {
{ 3,3,3,3,3 },
{ 1,4,4,4,1 },
{ 1,4,4,4,1 },
{ 1,4,4,4,1 },
{ 1,1,1,1,1 },
}
local blocks = {
[ 1 ] = { 'minecraft:cobblestone' },
[ 2 ] = { 'minecraft:oak_stairs', 3 },
[ 3 ] = { 'minecraft:log', 5 },
[ 4 ] = { 'minecraft:planks' },
[ 5 ] = { 'minecraft:glass_pane' },
}
local spt = GPS.getPoint() or { x = 0, y = 0, z = 0, heading = 0 }
local house = { }
-- construct a simple schematic from the template
for x,plane in pairs(template) do
for ry,row in pairs(plane) do
local y = #plane - ry + 1
for z, b in pairs(row) do
if b ~= 0 then
table.insert(house, {
x = x + spt.x,
y = y + spt.y - 1,
z = z + spt.z,
name = blocks[b][1],
direction = blocks[b][2], -- forward, down, up
facing = blocks[b][3],
})
end
end
end
end
-- define a box the turtles should not path find out of
local height, width, length = #template[1], #template[1][1], #template
local box = {
x = spt.x - 1,
y = spt.y,
z = spt.z - 1,
ex = spt.x + length + 1,
ey = spt.y + height + 1,
ez = spt.z + width + 1,
}
local function hijackTurtle(remoteId)
local socket, msg = Socket.connect(remoteId, 188)
if not socket then
error(msg)
end
socket:write('turtle')
local methods = socket:read()
local hijack = { }
for _,method in pairs(methods) do
hijack[method] = function(...)
socket:write({ fn = method, args = { ... } })
local resp = socket:read()
if not resp then
error('timed out')
end
return table.unpack(resp)
end
end
return hijack
end
-- try a couple times in case a turtle is in the way
local function place(turtle, pt)
for _ = 1, 3 do
if pt.direction then
if turtle.placeXXXAt(pt, pt.direction, pt.name) then
return true
end
else
if turtle.placeAt(pt, pt.name) then
return true
end
end
os.sleep(.5)
end
end
local args = { ... }
local turtleCount = #args
local turtles = { }
for _, id in pairs(args) do -- secondary channel
table.insert(turtles, hijackTurtle(tonumber(id)))
end
for _, id in pairs(args) do
Event.addRoutine(function()
--os.sleep(1)
local turtle = hijackTurtle(tonumber(id))
os.sleep(1)
turtle.reset()
turtle.enableGPS()
local lastPoint = turtle.getPoint()
turtle.setPersistent(true)
local boxed
while true do
local pt = Point.closest(turtle.getPoint(), house)
if not pt then
break
end
Util.removeByValue(house, pt)
if place(turtle, pt) then
for _, t in pairs(turtles) do
t.addWorldBlock(pt) -- notify all turtles about this block
end
elseif turtleCount > 1 then
--table.insert(house, pt)
end
if not boxed then
turtle.setPathingBox(box)
boxed = true
end
end
turtle.setPathingBox()
turtle.setPersistent(false)
turtle.pathfind(lastPoint)
if turtleCount == 1 then
Event.exitPullEvents()
end
turtleCount = turtleCount - 1
end)
end
print('pulling')
Event.pullEvents()