163 lines
3.8 KiB
Lua
163 lines
3.8 KiB
Lua
local args = {...}
|
|
|
|
--===== OPEN REDNET =====--
|
|
for _, side in ipairs(redstone.getSides()) do
|
|
if peripheral.getType(side) == "modem" then
|
|
rednet.open(side)
|
|
end
|
|
end
|
|
|
|
if not rednet.isOpen() then
|
|
printError("could not open rednet")
|
|
return
|
|
end
|
|
|
|
--===== LOAD MAP =====--
|
|
if not compactMap then
|
|
if not os.loadAPI("compactMap") then
|
|
error("could not load API: compactMap")
|
|
end
|
|
end
|
|
local map = compactMap.new(args[1])
|
|
|
|
--===== SET REDNET PROTOCOL =====--
|
|
local MAP_SHARE_PROTOCOL
|
|
if args[2] and type(args[2]) == "string" then
|
|
MAP_SHARE_PROTOCOL = "map_share:"..args[2]
|
|
else
|
|
MAP_SHARE_PROTOCOL = "map_share:"..fs.getName(args[1])
|
|
end
|
|
|
|
--===== HOST AS SERVER =====--
|
|
do
|
|
local host = rednet.lookup(MAP_SHARE_PROTOCOL, "SERVER")
|
|
if host and host ~= os.computerID() then
|
|
printError("server already running for this map share")
|
|
return
|
|
end
|
|
end
|
|
rednet.host(MAP_SHARE_PROTOCOL, "SERVER")
|
|
|
|
--===== UTILS =====--
|
|
local MESSAGE_TYPE = {
|
|
GET = 0,
|
|
SET = 1,
|
|
}
|
|
local receivedMessages = {}
|
|
local receivedMessageTimeouts = {}
|
|
|
|
local function isValidCoord(coord)
|
|
return type(coord) == "number" and coord % 1 == 0 and coord >= 0 and coord <= 15
|
|
end
|
|
|
|
local function updateCoord(x, y, z, value)
|
|
local coord = vector.new(x, y, z)
|
|
local currValue = map:get(coord)
|
|
if value == 1 then
|
|
if currValue then
|
|
map:set(coord, math.min(7, currValue + 1))
|
|
else
|
|
map:set(coord, 0)
|
|
end
|
|
elseif value == -1 then
|
|
if currValue then
|
|
if currValue == 0 then
|
|
map:set(coord, nil)
|
|
else
|
|
map:set(coord, currValue - 1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function updateMap(newData, gX, gY, gZ)
|
|
if type(newData) == "table" then
|
|
local currX, currY
|
|
for x, gridYZ in pairs(newData) do
|
|
if isValidCoord(x) and type(gridYZ) == "table" then
|
|
currX = gX*16 + x
|
|
for y, gridZ in pairs(gridYZ) do
|
|
if isValidCoord(y) and type(gridZ) == "table" then
|
|
currY = gY*16 + y
|
|
for z, value in pairs(gridZ) do
|
|
if isValidCoord(z) then
|
|
updateCoord(currX, currY, gZ*16 + z, value)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
map:save(gX, gY, gZ)
|
|
end
|
|
end
|
|
|
|
local function checkGridCoordFormat(gridCoord)
|
|
if type(gridCoord) == "table" and #gridCoord == 3 then
|
|
for i = 1, 3 do
|
|
local coord = gridCoord[i]
|
|
if type(coord) ~= "number" or coord % 1 ~= 0 then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function newMessage(messageType, messageID, grid, data)
|
|
return {
|
|
type = messageType,
|
|
ID = messageID,
|
|
grid = grid,
|
|
data = data,
|
|
}
|
|
end
|
|
|
|
--===== REPEATED MESSAGE HANDLING =====--
|
|
local function clearOldMessages()
|
|
while true do
|
|
local event, timer = os.pullEvent("timer")
|
|
local messageID = receivedMessageTimeouts[timer]
|
|
if messageID then
|
|
receivedMessageTimeouts[timer] = nil
|
|
receivedMessages[messageID] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
--===== MAIN =====--
|
|
local function main()
|
|
while true do
|
|
local senderID, message = rednet.receive(MAP_SHARE_PROTOCOL)
|
|
if type(message) == "table" and checkGridCoordFormat(message.grid) then
|
|
if message.type == MESSAGE_TYPE.GET then
|
|
local gridData = map:getGrid(unpack(message.grid))
|
|
local replyMessage = newMessage(MESSAGE_TYPE.GET, message.ID, message.grid, gridData)
|
|
rednet.send(senderID, replyMessage, MAP_SHARE_PROTOCOL)
|
|
elseif message.type == MESSAGE_TYPE.SET then
|
|
if not receivedMessages[message.ID] then
|
|
updateMap(message.data, unpack(message.grid))
|
|
receivedMessages[message.ID] = true
|
|
receivedMessageTimeouts[os.startTimer(15)] = message.ID
|
|
end
|
|
local replyMessage = newMessage(MESSAGE_TYPE.SET, message.ID, message.grid, true)
|
|
rednet.send(senderID, replyMessage, MAP_SHARE_PROTOCOL)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--===== USER INTERFACE =====--
|
|
local function control()
|
|
while true do
|
|
local event, key = os.pullEvent("key")
|
|
if key == keys.backspace then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
parallel.waitForAny(main, clearOldMessages, control)
|
|
|
|
rednet.unhost(MAP_SHARE_PROTOCOL) |