zbizu
Legendary OT User
In preparation to version 12, I've wrote a code that could be used for feyrist day/night cycle or for any server to create alternative versions of specific areas.
What it does:
video: i.imgur.com/HX0TqjC.mp4
how to use:
I recommend writing a globalevent yourself. Either onStartup (os.date(...) for seasons) or onThink (getWorldTime() for day/night cycle)
the code:
asyncArea.lua:
transformArea.lua:
What it does:
- It transforms a large area into another biome (you have to fill biomes table manually).
- It does that in delays so the server doesn't lag during the processing.
- It's a mod. This means that both files will go to data/scripts folder.
video: i.imgur.com/HX0TqjC.mp4
how to use:
I recommend writing a globalevent yourself. Either onStartup (os.date(...) for seasons) or onThink (getWorldTime() for day/night cycle)
the code:
asyncArea.lua:
Code:
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)
]]
transformArea.lua:
Code:
BIOME_SPRING = 1
BIOME_SUMMER = 2
BIOME_AUTUMN = 3
BIOME_WINTER = 4
local biomeMachine = {
{ -- ground
[BIOME_SPRING] = 106,
[BIOME_SUMMER] = 4526,
[BIOME_AUTUMN] = 8326,
[BIOME_WINTER] = 670,
},
{ -- border north west big
[BIOME_SPRING] = 4792,
[BIOME_SUMMER] = 4550,
[BIOME_AUTUMN] = 8355,
[BIOME_WINTER] = 4745,
},
{ -- tree
[BIOME_SPRING] = 2712,
[BIOME_SUMMER] = 2712,
[BIOME_AUTUMN] = 2719,
[BIOME_WINTER] = 2697,
},
{ -- bush
[BIOME_SPRING] = 2767,
[BIOME_SUMMER] = 2767,
[BIOME_AUTUMN] = 2784,
[BIOME_WINTER] = 2684,
},
{ -- fir tree
[BIOME_SPRING] = 2700,
[BIOME_SUMMER] = 2700,
[BIOME_AUTUMN] = 2719,
[BIOME_WINTER] = 2698,
},
}
local biomeDatabase = {}
function registerBiomes()
for i = 1, #biomeMachine do
local itemsToRegister = {}
for biomeId, itemId in pairs(biomeMachine[i]) do
table.insert(itemsToRegister, itemId)
end
for j = 1, #itemsToRegister do
local itemId = itemsToRegister[j]
if not biomeDatabase[itemId] then
biomeDatabase[itemId] = {}
end
for biomeId, toItemId in pairs(biomeMachine[i]) do
biomeDatabase[itemId][biomeId] = toItemId
end
end
end
end
registerBiomes()
function transferBiome(pos, toBiome)
local tile = Tile(pos)
if tile then
local tileStack = tile:getItems()
local ground = tile:getGround()
if ground then
table.insert(tileStack, ground)
end
for k, v in pairs(tileStack) do
local itemId = v:getId()
if biomeDatabase[itemId] and biomeDatabase[itemId][toBiome] then
v:transform(biomeDatabase[itemId][toBiome])
end
end
end
end
-- example code
--[[
function biomeCallback(pos)
transferBiome(pos, BIOME_SUMMER)
end
function biomeTransferTest()
local fromPos = Position(201, 65, 7)
local toPos = Position(221, 72, 7)
local area = Area(fromPos, toPos, 4, 1000)
area:asyncIterateArea(biomeCallback)
end
addEvent(biomeTransferTest, 10000)
]]