Updates to bring all maps and their viewers up to date with latest changes
This commit is contained in:
185
maps/remoteMap
Normal file
185
maps/remoteMap
Normal file
@@ -0,0 +1,185 @@
|
||||
local REDNET_TIMEOUT = 1
|
||||
|
||||
local MESSAGE_TYPE = {
|
||||
GET = 0,
|
||||
SET = 1,
|
||||
}
|
||||
|
||||
local function newMessage(messageType, grid, data)
|
||||
return {
|
||||
type = messageType,
|
||||
ID = math.random(0, 2^30),
|
||||
grid = grid,
|
||||
data = data,
|
||||
}
|
||||
end
|
||||
|
||||
local function sendAndWaitForResponse(recipientID, message, protocol)
|
||||
rednet.send(recipientID, message, protocol)
|
||||
local attemptNumber = 1
|
||||
while true do
|
||||
local senderID, reply = rednet.receive(protocol, REDNET_TIMEOUT)
|
||||
if senderID == recipientID and type(reply) == "table" and reply.type == message.type and reply.ID == message.ID then
|
||||
return reply.data
|
||||
elseif not senderID then
|
||||
if attemptNumber < 3 then
|
||||
rednet.send(recipientID, message, protocol)
|
||||
attemptNumber = attemptNumber + 1
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function isValidValue(value)
|
||||
return value == nil or value == -1 or value == 1
|
||||
end
|
||||
|
||||
local function toGridCode(tVector)
|
||||
return math.floor(tVector.x/16), math.floor(tVector.y/16), math.floor(tVector.z/16), tVector.x % 16, tVector.y % 16, tVector.z % 16
|
||||
end
|
||||
|
||||
local function getRemoteGrid(tMap, x, y, z)
|
||||
if not tMap.remoteGrids[x] or not tMap.remoteGrids[x][y] or not tMap.remoteGrids[x][y][z] then
|
||||
local message = newMessage(MESSAGE_TYPE.GET, {x, y, z}, nil)
|
||||
local remoteGrid = sendAndWaitForResponse(tMap.serverID, message, tMap.protocol) or {}
|
||||
tMap.remoteGridsAge[x..","..y..","..z] = os.clock()
|
||||
if not tMap.remoteGrids[x] then
|
||||
tMap.remoteGrids[x] = {}
|
||||
end
|
||||
if not tMap.remoteGrids[x][y] then
|
||||
tMap.remoteGrids[x][y] = {}
|
||||
end
|
||||
tMap.remoteGrids[x][y][z] = remoteGrid
|
||||
return remoteGrid
|
||||
else
|
||||
return tMap.remoteGrids[x][y][z]
|
||||
end
|
||||
end
|
||||
|
||||
local function getUpdateGrid(tMap, x, y, z)
|
||||
if not tMap.updateGrids[x] or not tMap.updateGrids[x][y] or not tMap.updateGrids[x][y][z] then
|
||||
local updateGrid = {}
|
||||
if not tMap.updateGrids[x] then
|
||||
tMap.updateGrids[x] = {}
|
||||
end
|
||||
if not tMap.updateGrids[x][y] then
|
||||
tMap.updateGrids[x][y] = {}
|
||||
end
|
||||
tMap.updateGrids[x][y][z] = updateGrid
|
||||
return updateGrid
|
||||
else
|
||||
return tMap.updateGrids[x][y][z]
|
||||
end
|
||||
end
|
||||
|
||||
local remoteMapMethods = {
|
||||
get = function(self, coord)
|
||||
local gX, gY, gZ, pX, pY, pZ = toGridCode(coord)
|
||||
local grid = getRemoteGrid(self, gX, gY, gZ)
|
||||
if grid[pX] and grid[pX][pY] then
|
||||
return grid[pX][pY][pZ]
|
||||
end
|
||||
end,
|
||||
|
||||
set = function(self, coord, value)
|
||||
if not isValidValue(value) then
|
||||
--should we throw an error or use a default value?
|
||||
error("remoteMap set: value is not valid", 2)
|
||||
end
|
||||
local gX, gY, gZ, pX, pY, pZ = toGridCode(coord)
|
||||
local grid = getUpdateGrid(self, gX, gY, gZ)
|
||||
if not grid[pX] then
|
||||
grid[pX] = {}
|
||||
end
|
||||
if not grid[pX][pY] then
|
||||
grid[pX][pY] = {}
|
||||
end
|
||||
grid[pX][pY][pZ] = value
|
||||
end,
|
||||
|
||||
check = function(self)
|
||||
local time = os.clock()
|
||||
local newRemoteGridsAge = {}
|
||||
for gridCode, gridAge in pairs(self.remoteGridsAge) do
|
||||
if time - gridAge >= self.timeout then
|
||||
local x, y, z = string.match(gridCode, "([-]?%d+),([-]?%d+),([-]?%d+)")
|
||||
x, y, z = tonumber(x), tonumber(y), tonumber(z)
|
||||
if x and y and z then
|
||||
if self.remoteGrids[x] and self.remoteGrids[x][y] then
|
||||
self.remoteGrids[x][y][z] = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
newRemoteGridsAge[gridCode] = gridAge
|
||||
end
|
||||
end
|
||||
local newUpdateGridsAge = {}
|
||||
for gridCode, gridAge in pairs(self.updateGridsAge) do
|
||||
if time - gridAge >= self.timeout then
|
||||
-- remove grid from updateGrids ???
|
||||
else
|
||||
newUpdateGridsAge[gridCode] = gridAge
|
||||
end
|
||||
end
|
||||
self.remoteGridsAge = newRemoteGridsAge
|
||||
self.updateGridsAge = newUpdateGridsAge
|
||||
end,
|
||||
|
||||
pushUpdates = function(self, ignoreTimeout)
|
||||
local newUpdateGrids = {}
|
||||
for gX, YZmap in pairs(self.updateGrids) do
|
||||
newUpdateGrids[gX] = {}
|
||||
for gY, Zmap in pairs(YZmap) do
|
||||
newUpdateGrids[gX][gY] = {}
|
||||
for gZ, grid in pairs(Zmap) do
|
||||
local gridCode = gX..","..gY..","..gZ
|
||||
if next(grid) then
|
||||
if ignoreTimeout == true or (not self.updateGridsAge[gridCode]) or os.clock() - self.updateGridsAge[gridCode] >= self.timeout then
|
||||
local message = newMessage(MESSAGE_TYPE.SET, {gX, gY, gZ}, grid)
|
||||
local response = sendAndWaitForResponse(self.serverID, message, self.protocol)
|
||||
if response == true then
|
||||
self.updateGridsAge[gridCode] = os.clock()
|
||||
else
|
||||
newUpdateGrids[gX][gY][gZ] = grid
|
||||
end
|
||||
else
|
||||
newUpdateGrids[gX][gY][gZ] = grid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self.updateGrids = newUpdateGrids
|
||||
end,
|
||||
}
|
||||
local remoteMapMetatable = {__index = remoteMapMethods}
|
||||
|
||||
function new(mapName, timeout)
|
||||
if type(mapName) ~= "string" then
|
||||
error("mapName must be string")
|
||||
end
|
||||
if type(timeout) ~= "number" or timeout < 0 then
|
||||
error("timeout must be positive number")
|
||||
end
|
||||
|
||||
local protocol = "map_share:"..mapName
|
||||
|
||||
local serverID = rednet.lookup(protocol, "SERVER")
|
||||
if not serverID then
|
||||
error("could not find map share server")
|
||||
end
|
||||
|
||||
local remoteMap = {
|
||||
mapName = mapName,
|
||||
protocol = protocol,
|
||||
serverID = serverID,
|
||||
timeout = timeout,
|
||||
remoteGrids = {},
|
||||
remoteGridsAge = {},
|
||||
updateGrids = {},
|
||||
updateGridsAge = {},
|
||||
}
|
||||
return setmetatable(remoteMap, remoteMapMetatable)
|
||||
end
|
||||
Reference in New Issue
Block a user