From ed2e0ada40dcf06118e91f0bc751981e8f44f704 Mon Sep 17 00:00:00 2001 From: stujones11 Date: Sun, 30 Jun 2019 21:42:14 +0100 Subject: [PATCH] Add player iteration methods to builtin, optimization of many mods --- builtin/game/register.lua | 93 +++++++++++++++++++++++++++++++++++++++ builtin/game/statbars.lua | 17 ++----- doc/lua_api.txt | 11 +++++ multicraft.conf.example | 4 ++ 4 files changed, 112 insertions(+), 13 deletions(-) diff --git a/builtin/game/register.lua b/builtin/game/register.lua index 16dc0fe8..16311035 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -556,6 +556,99 @@ core.registered_on_protection_violation, core.register_on_protection_violation = core.registered_on_item_eats, core.register_on_item_eat = make_registration() core.registered_on_punchplayers, core.register_on_punchplayer = make_registration() +-- Player step iterration + +players_per_step = core.settings:get("players_per_globalstep") +players_per_step = players_per_step and tonumber(players_per_step) or 20 + +local player_iter = nil +local player_iter_forced = nil +local playerstep_iter = nil +local playerstep_funcs = {} +local playerstep_funcs_forced = {} +local playernames = {} +local playernames_forced = {} + +core.register_playerstep = function(func, force) + local funcs = force and playerstep_funcs_forced or playerstep_funcs + funcs[#funcs + 1] = func +end + +local function table_iter(t) + local i = 0 + local n = table.getn(t) + return function () + i = i + 1 + if i <= n then + return t[i] + end + end +end + +function core.get_player_iter() + local names = {} + for player in table_iter(core.get_connected_players()) do + local name = player:get_player_name() + if name then + names[#names + 1] = name + end + end + return table_iter(names) +end + +local function get_playerstep_func() + if playerstep_iter == nil then + playerstep_iter = table_iter(playerstep_funcs) + playernames = {} + for _ = 1, players_per_step do + if player_iter == nil then + player_iter = core.get_player_iter() + end + local name = player_iter() + if not name then + player_iter = nil + break + end + playernames[#playernames + 1] = name + end + end + local func = playerstep_iter() + playerstep_iter = func and playerstep_iter + return func or get_playerstep_func() +end + +-- Run playerstep callbacks + +core.register_globalstep(function(dtime) + -- Run forced callbacks + if #playerstep_funcs_forced ~= 0 then + playernames_forced = {} + for _ = 1, players_per_step do + if player_iter_forced == nil then + player_iter_forced = core.get_player_iter() + end + local name = player_iter_forced() + if not name then + player_iter_forced = nil + break + end + playernames_forced[#playernames_forced + 1] = name + end + for func in table_iter(playerstep_funcs_forced) do + if type(func) == "function" then + func(dtime, playernames_forced) + end + end + end + if #playerstep_funcs ~= 0 then + -- Run single step callbacks + local func = get_playerstep_func() + if type(func) == "function" then + func(dtime, playernames) + end + end +end) + -- -- Compatibility for on_mapgen_init() -- diff --git a/builtin/game/statbars.lua b/builtin/game/statbars.lua index d42e8fe7..a2982f6d 100644 --- a/builtin/game/statbars.lua +++ b/builtin/game/statbars.lua @@ -185,16 +185,9 @@ core.register_on_joinplayer(function(player) initialize_builtin_statbars(player) end) - -local time = 0 -local update_time = 1 -core.register_globalstep(function(dtime) - time = time + dtime - if time > update_time then - - local players = core.get_connected_players() - for i = 1, #players do - local player = players[i] +minetest.register_playerstep(function(dtime, playernames) + for _, name in pairs(playernames) do + local player = minetest.get_player_by_name(name) local player_name = player:get_player_name() local wielded_item = player:get_wielded_item() @@ -224,6 +217,4 @@ core.register_globalstep(function(dtime) hud.change_item(player, "itemname", {text = description}) end end - time = 0 - end -end) +end, minetest.is_singleplayer()) -- Force step in singlplayer mode only diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 68a0506c..79c04417 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2363,6 +2363,17 @@ Call these functions only at load time! * `minetest.register_globalstep(func(dtime))` * Called every server step, usually interval of 0.1s +* `minetest.register_playerstep(function(dtime, playernames), force)` + * Called one registration per step, see `force` + * `dtime` : Delta time since last callback, see `dedicated_server_step` setting + * `playernames` : Table of player names, see `players_per_globalstep` setting + * `force` : Boolean value (optional) + * Force this callback to run on every server step, default: `false` + * Note: This callback should not be rate limited or players may be missed! + * See the [fire] mod for an example of how this may be done reliably +* `minetest.get_player_iter()` + * Returns a player name iterrator, as used by `minetest.register_playerstep` + * See `builtin/game/register.lua` for example usage * `minetest.register_on_shutdown(func())` * Called before server shutdown * **Warning**: If the server terminates abnormally (i.e. crashes), the registered diff --git a/multicraft.conf.example b/multicraft.conf.example index e17976e0..8ab277c1 100644 --- a/multicraft.conf.example +++ b/multicraft.conf.example @@ -1115,6 +1115,10 @@ # type: float # dedicated_server_step = 0.1 +# Maxumim number of players to process per step, see `minetest.register_playerstep` +# type: int +# players_per_globalstep = 20 + # Time in between active block management cycles # type: float # active_block_mgmt_interval = 2.0