2023-10-13 11:22:56 +00:00
|
|
|
--[[
|
|
|
|
|
|
|
|
outline:
|
|
|
|
|
|
|
|
do the following regularly:
|
|
|
|
|
|
|
|
1. create an empty list for mapblocks to process.
|
|
|
|
2. for every online player:
|
|
|
|
2.1. go through every mapblock near them, and add the mapblock to the list if it's not already added.
|
|
|
|
3. for every mapblock in the list:
|
|
|
|
3.1. load the mapblock.
|
|
|
|
|
|
|
|
- the "keep track of loaded mapblocks" part could be useful for other things too.
|
|
|
|
|
|
|
|
]]--
|
|
|
|
|
|
|
|
-- max distance from players, in mapblocks, within which mapblocks will be random-ticked.
|
|
|
|
local max_load_range = 4
|
|
|
|
-- max amount of mapblocks to get random-ticked each server step.
|
|
|
|
local max_ticked_block_count = 200
|
|
|
|
-- amount of random ticks to apply to each mapblock.
|
|
|
|
local random_tick_count = 4
|
|
|
|
|
|
|
|
local settings = minetest.settings
|
|
|
|
local view_range = settings:get("viewing_range")
|
|
|
|
|
|
|
|
local load_range = math.min(math.floor(view_range / 16), max_load_range)
|
|
|
|
|
|
|
|
local function random_tick (mapblock_pos)
|
|
|
|
for i=1, random_tick_count do
|
|
|
|
local x = mapblock_pos.x * 16 + math.random(0, 15)
|
|
|
|
local y = mapblock_pos.y * 16 + math.random(0, 15)
|
|
|
|
local z = mapblock_pos.z * 16 + math.random(0, 15)
|
|
|
|
local pos = vector.new(x, y, z)
|
|
|
|
|
|
|
|
local node_def = minetest.registered_nodes[minetest.get_node(pos).name]
|
2023-10-15 15:38:11 +00:00
|
|
|
if not node_def then return end
|
2023-10-13 11:22:56 +00:00
|
|
|
if type(node_def.on_random_tick) == "function" then
|
|
|
|
node_def.on_random_tick(pos, node, i)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
blockgame.register_globalstep(function ()
|
|
|
|
-- find loaded mapblocks
|
|
|
|
|
|
|
|
local mapblocks = {}
|
|
|
|
local visited_blocks = {}
|
|
|
|
|
|
|
|
for _, player in pairs(minetest.get_connected_players()) do
|
|
|
|
local node_pos = player:get_pos()
|
|
|
|
local mapblock_pos = {}
|
|
|
|
for key, value in pairs(node_pos) do
|
|
|
|
mapblock_pos[key] = math.floor(value / 16)
|
|
|
|
end
|
|
|
|
|
|
|
|
for x = mapblock_pos.x - load_range, mapblock_pos.x + load_range do
|
|
|
|
for y = mapblock_pos.y - load_range, mapblock_pos.y + load_range do
|
|
|
|
for z = mapblock_pos.z - load_range, mapblock_pos.z + load_range do
|
|
|
|
local hash = x .. "," .. y .. "," .. z
|
|
|
|
if not visited_blocks[hash] then
|
|
|
|
visited_blocks[hash] = true
|
|
|
|
table.insert(mapblocks, vector.new(x, y, z))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
mapblocks = blockgame.shuffle(mapblocks)
|
|
|
|
|
|
|
|
-- tick mapblocks
|
|
|
|
|
|
|
|
local ticked_mapblock_count = 0
|
|
|
|
repeat
|
|
|
|
ticked_mapblock_count = ticked_mapblock_count + 1
|
|
|
|
|
|
|
|
local index = math.random(1, #mapblocks)
|
|
|
|
local mapblock = mapblocks[index]
|
|
|
|
|
|
|
|
table.remove(mapblocks, index)
|
|
|
|
|
|
|
|
if mapblock then
|
|
|
|
random_tick(mapblock)
|
|
|
|
end
|
|
|
|
until ticked_mapblock_count >= max_ticked_block_count or #mapblocks == 0
|
|
|
|
end)
|