blockgame/mods/bg_api/random_tick.lua
2023-10-15 17:38:11 +02:00

87 lines
2.4 KiB
Lua

--[[
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]
if not node_def then return end
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)