Skip to content

Instantly share code, notes, and snippets.

@Zbizu
Created July 28, 2021 22:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Zbizu/85778dcb815532cd1a95abcb78d7fbd4 to your computer and use it in GitHub Desktop.
Save Zbizu/85778dcb815532cd1a95abcb78d7fbd4 to your computer and use it in GitHub Desktop.
non-blocking iteration over large areas
-- async iterate area
-- for when you want to execute a script on a large area, but dont want lags on your server
local defaultChunkSize = 16
local defaultDelay = 200
Area = setmetatable ({ },
{
__call = function (area, ...)
return area.new (...)
end
}
)
Area.__index = Area
Area.__call = function (self)
return Area.new (self)
end
function Area.new(fromPos, toPos, chunkSize, delay)
local self = setmetatable ({ }, Area)
self.fromPos = fromPos
self.toPos = toPos
self:adjustPos()
self.chunkSize = tonumber(chunkSize) or defaultChunkSize
self.delay = tonumber(delay) or defaultDelay
return self
end
function Area:adjustPos()
if self.toPos.x < self.fromPos.x then
local tmp = self.toPos.x
self.toPos.x = self.fromPos.x
self.fromPos.x = tmp
end
if self.toPos.y < self.fromPos.y then
local tmp = self.toPos.y
self.toPos.y = self.fromPos.y
self.fromPos.y = tmp
end
if self.toPos.z < self.fromPos.z then
local tmp = self.toPos.z
self.toPos.z = self.fromPos.z
self.fromPos.z = tmp
end
end
function Area:getFromPos()
return self.fromPos
end
function Area:setFromPos(pos)
self.fromPos = pos
self:adjustPos()
end
function Area:getToPos()
return self.toPos
end
function Area:setToPos(pos)
self.toPos = pos
self:adjustPos()
end
function Area:getChunkSize()
return self.chunkSize
end
function Area:setChunkSize(chunkSize)
self.chunkSize = tonumber(chunkSize) or defaultChunkSize
end
function Area:getDelay()
return self.delay
end
function Area:setDelay(delay)
self.delay = tonumber(delay) or defaultDelay
end
function Area:asyncIterateChunk(chunkPos, callback)
local startPos = Position(self.fromPos.x + chunkPos.x * self.chunkSize, self.fromPos.y + chunkPos.y * self.chunkSize, self.fromPos.z + chunkPos.z)
for offsetY = startPos.y, math.min(startPos.y + self.chunkSize - 1, self.toPos.y) do
for offsetX = startPos.x, math.min(startPos.x + self.chunkSize - 1, self.toPos.x) do
local currentPos = Position(offsetX, offsetY, startPos.z)
callback(currentPos)
end
end
end
function Area:asyncIterateArea(callback)
local chunkAmount = {
x = math.floor((self.toPos.x - self.fromPos.x) / self.chunkSize),
y = math.floor((self.toPos.x - self.fromPos.x) / self.chunkSize),
z = (self.toPos.z - self.fromPos.z)
}
local n = 0
for z = 0, chunkAmount.z do
for y = 0, chunkAmount.y do
for x = 0, chunkAmount.x do
n = n + 1
addEvent(Area.asyncIterateChunk, self.delay * n, self, {x = x, y = y, z = z}, callback)
end
end
end
end
-- example code
--[[
function exampleFunction(pos, itemId)
local tile = Tile(pos) or Game.createTile(pos)
if tile then
Game.createItem(itemId, 1, pos)
end
end
function exampleCallback(pos)
exampleFunction(pos, 1284)
end
function asyncTest()
local area = Area(Position(160, 54, 7), Position(256, 256, 9), 32, 400)
area:asyncIterateArea(exampleCallback)
end
addEvent(asyncTest, 4000)
]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment