mineserver.lua
263 lines · 7.2 KB
PHONE SERVER--
Copy & run
wget https://perlytiara.github.io/turtles.tips/raw/programs/perlytiara/Maengorn/mineserver.lua
| 1 | --PHONE SERVER-- |
| 2 | |
| 3 | local SERVER_PORT = 420 |
| 4 | local CLIENT_PORT = 0 |
| 5 | local SLOT_COUNT = 16 |
| 6 | |
| 7 | |
| 8 | local segmentation = 5 |
| 9 | if (#arg == 1) then |
| 10 | segmentation = tonumber(arg[1]) |
| 11 | elseif (#arg == 0) then |
| 12 | print(string.format("No segmentation size selected, defaulting to %d", segmentation)) |
| 13 | else |
| 14 | print('Too many args given...') |
| 15 | exit(1) |
| 16 | end |
| 17 | |
| 18 | function findWirelessModem() |
| 19 | for _, side in ipairs(peripheral.getNames()) do |
| 20 | if peripheral.getType(side) == "modem" and peripheral.call(side, "isWireless") then |
| 21 | return side |
| 22 | end |
| 23 | end |
| 24 | return nil |
| 25 | end |
| 26 | |
| 27 | local modemSide = findWirelessModem() |
| 28 | if not modemSide then |
| 29 | error("No wireless modem found!") |
| 30 | end |
| 31 | local modem = peripheral.wrap(modemSide) |
| 32 | modem.open(SERVER_PORT) |
| 33 | |
| 34 | local target = vector.new() |
| 35 | local size = vector.new() |
| 36 | local finish = vector.new() |
| 37 | |
| 38 | -- I STOLE -- |
| 39 | function split (inputstr, sep) |
| 40 | if sep == nil then |
| 41 | sep = "%s" |
| 42 | end |
| 43 | local t={} |
| 44 | for str in string.gmatch(inputstr, "([^"..sep.."]+)") do |
| 45 | table.insert(t, str) |
| 46 | end |
| 47 | return t |
| 48 | end |
| 49 | |
| 50 | function parseParams(data) |
| 51 | coords = {} |
| 52 | params = split(data, " ") |
| 53 | |
| 54 | coords[1] = vector.new(params[1], params[2], params[3]) |
| 55 | coords[2] = vector.new(params[4], params[5], params[6]) |
| 56 | |
| 57 | return (coords) |
| 58 | end |
| 59 | |
| 60 | function getItemIndex(itemName) |
| 61 | while true do |
| 62 | for slot = 1, SLOT_COUNT, 1 do |
| 63 | local item = turtle.getItemDetail(slot) |
| 64 | if(item ~= nil) then |
| 65 | if(item["name"] == itemName) then |
| 66 | return slot |
| 67 | end |
| 68 | end |
| 69 | end |
| 70 | |
| 71 | -- Item not found, wait for user to add it |
| 72 | print(string.format("Waiting for: %s", itemName)) |
| 73 | print("Please add to inventory...") |
| 74 | os.sleep(2) |
| 75 | end |
| 76 | end |
| 77 | |
| 78 | function checkFuel() |
| 79 | turtle.select(1) |
| 80 | |
| 81 | if(turtle.getFuelLevel() < 50) then |
| 82 | print("Attempting Refuel...") |
| 83 | for slot = 1, SLOT_COUNT, 1 do |
| 84 | turtle.select(slot) |
| 85 | if(turtle.refuel(1)) then |
| 86 | return true |
| 87 | end |
| 88 | end |
| 89 | return false |
| 90 | else |
| 91 | return true |
| 92 | end |
| 93 | end |
| 94 | |
| 95 | function deployFuelChest() |
| 96 | if (not checkFuel()) then |
| 97 | print("SERVER NEEDS FUEL...") |
| 98 | exit(1) |
| 99 | end |
| 100 | end |
| 101 | |
| 102 | |
| 103 | function deploy(startCoords, quarySize, endCoords, options) |
| 104 | --Place turtle from inventory |
| 105 | -- First try wireless turtle, then fall back to regular advanced turtle |
| 106 | local turtleSlot = getItemIndex("computercraft:turtle_advanced") |
| 107 | |
| 108 | turtle.select(turtleSlot) |
| 109 | while(turtle.detect()) do |
| 110 | os.sleep(0.3) |
| 111 | end |
| 112 | |
| 113 | --Place and turn on turtle |
| 114 | print("Placing turtle...") |
| 115 | turtle.place() |
| 116 | |
| 117 | -- Check if we need to add a wireless modem to the turtle |
| 118 | -- Try to place a modem on the turtle if it doesn't have one |
| 119 | local modemSlot = nil |
| 120 | for slot = 1, SLOT_COUNT do |
| 121 | local item = turtle.getItemDetail(slot) |
| 122 | if item and item.name == "computercraft:wireless_modem_advanced" then |
| 123 | modemSlot = slot |
| 124 | break |
| 125 | elseif item and item.name == "computercraft:wireless_modem_normal" then |
| 126 | modemSlot = slot |
| 127 | break |
| 128 | end |
| 129 | end |
| 130 | |
| 131 | if modemSlot then |
| 132 | print("Equipping modem to turtle...") |
| 133 | turtle.select(modemSlot) |
| 134 | turtle.drop(1) -- Drop modem in front so turtle can pick it up |
| 135 | os.sleep(0.5) |
| 136 | else |
| 137 | print("WARNING: No wireless modem in inventory!") |
| 138 | print("Turtle may not have GPS access!") |
| 139 | end |
| 140 | |
| 141 | -- Turn on the turtle (it should boot from disk/startup automatically) |
| 142 | print("Booting turtle...") |
| 143 | peripheral.call("front", "turnOn") |
| 144 | |
| 145 | |
| 146 | --Wait for client to send ping |
| 147 | event, side, senderChannel, replyChannel, msg, distance = os.pullEvent("modem_message") |
| 148 | if(msg ~= "CLIENT_DEPLOYED") then |
| 149 | print("No client deploy message, exitting...") |
| 150 | os.exit() |
| 151 | end |
| 152 | |
| 153 | |
| 154 | if(options["withStorage"]) then |
| 155 | --Set up ender chest |
| 156 | if (not checkFuel()) then |
| 157 | print("SERVER NEEDS FUEL...") |
| 158 | exit(1) |
| 159 | end |
| 160 | end |
| 161 | |
| 162 | deployFuelChest() |
| 163 | local storageBit = options["withStorage"] and 1 or 0 |
| 164 | |
| 165 | -- Client is deployed |
| 166 | modem.transmit(CLIENT_PORT, |
| 167 | SERVER_PORT, |
| 168 | string.format("%d %d %d %d %d %d %d %d %d %d", |
| 169 | startCoords.x, startCoords.y, startCoords.z, |
| 170 | quarySize.x, quarySize.y, quarySize.z, |
| 171 | endCoords.x, endCoords.y, endCoords.z, |
| 172 | storageBit |
| 173 | )) |
| 174 | end |
| 175 | |
| 176 | |
| 177 | |
| 178 | -- Return array of arbitrary size for each bot placement |
| 179 | function getPositioningTable(x, z, segmaentationSize) |
| 180 | local xRemainder = x % segmaentationSize |
| 181 | local zRemainder = z % segmaentationSize |
| 182 | |
| 183 | local xMain = x - xRemainder |
| 184 | local zMain = z - zRemainder |
| 185 | |
| 186 | xRemainder = (xRemainder == 0 and segmaentationSize or xRemainder) |
| 187 | zRemainder = (zRemainder == 0 and segmaentationSize or zRemainder) |
| 188 | |
| 189 | local positions = {} |
| 190 | |
| 191 | for zi = 0, z - 1 , segmaentationSize do |
| 192 | for xi = 0, x - 1, segmaentationSize do |
| 193 | |
| 194 | local dims = {xi, zi, segmaentationSize, segmaentationSize} |
| 195 | if(xi >= x - segmaentationSize and xi <= x - 1 ) then |
| 196 | dims = {xi, zi, xRemainder, segmaentationSize} |
| 197 | end |
| 198 | |
| 199 | if(zi >= z - segmaentationSize and zi <= z - 1 ) then |
| 200 | dims = {xi, zi, segmaentationSize, zRemainder} |
| 201 | end |
| 202 | |
| 203 | table.insert(positions, dims) |
| 204 | end |
| 205 | end |
| 206 | |
| 207 | return table.pack(positions, xRemainder, zRemainder) |
| 208 | end |
| 209 | |
| 210 | while (true) do |
| 211 | -- Wait for phone |
| 212 | print("Waiting for target signal...") |
| 213 | event, side, senderChannel, replyChannel, msg, distance = os.pullEvent("modem_message") |
| 214 | |
| 215 | -- Parse out coordinates and options |
| 216 | local args = split(msg, " ") |
| 217 | local withStorage = args[#args] |
| 218 | withStorage = withStorage == "1" and true or false |
| 219 | data = parseParams(msg) |
| 220 | options = {} |
| 221 | options["withStorage"] = True |
| 222 | |
| 223 | target = data[1] |
| 224 | size = data[2] |
| 225 | |
| 226 | finish = vector.new(gps.locate()) |
| 227 | finish.y = finish.y + 1 |
| 228 | print(string.format( "RECEIVED QUARY REQUEST AT: %d %d %d", target.x, target.y, target.z)) |
| 229 | |
| 230 | tab, xDf, zDf = table.unpack(getPositioningTable(size.x, size.z, segmentation)) |
| 231 | |
| 232 | print(string.format("Deploying %d bots...", #tab)) |
| 233 | for i = 1, #tab, 1 do |
| 234 | xOffset, zOffset, width, height = table.unpack(tab[i]) |
| 235 | local offsetTarget = vector.new(target.x + xOffset, target.y, target.z + zOffset) |
| 236 | local sclaedSize = vector.new(width, size.y, height) |
| 237 | |
| 238 | deploy(offsetTarget, sclaedSize, finish, options) |
| 239 | os.sleep(1) |
| 240 | print(string.format( "Deploying to; %d %d %d %d %d", target.x + xOffset, target.y, target.z + zOffset, sclaedSize.x, sclaedSize.z)) |
| 241 | end |
| 242 | |
| 243 | -- All bots deployed, wait for last bot finished signal |
| 244 | event, side, senderChannel, replyChannel, msg, distance = os.pullEvent("modem_message") |
| 245 | turtle.digUp() |
| 246 | turtle.turnRight() |
| 247 | turtle.forward(1) |
| 248 | turtle.turnLeft() |
| 249 | turtle.select(getItemIndex("enderstorage:ender_storage")) |
| 250 | endercount = (turtle.getItemCount() - 2) |
| 251 | if (endercount ~= 0) then |
| 252 | print(string.format("Depositing %d Ender Chests.", endercount)) |
| 253 | turtle.drop(endercount) |
| 254 | end |
| 255 | |
| 256 | turtle.turnLeft() |
| 257 | turtle.forward(1) |
| 258 | turtle.turnRight() |
| 259 | |
| 260 | |
| 261 | end |
| 262 | |
| 263 |