mods that hopefully work for a TechAge-based pack
This commit is contained in:
@@ -0,0 +1,676 @@
|
||||
--functions
|
||||
|
||||
eye_spy = {}
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
eye_spy.S = S
|
||||
-- eye_spy.cg is set in init.lua after game detection
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Mod storage (called ONCE at load time)
|
||||
------------------------------------------------------------
|
||||
eye_spy.storage = minetest.get_mod_storage()
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Shared runtime tables
|
||||
------------------------------------------------------------
|
||||
eye_spy.state = { players = {} }
|
||||
eye_spy.cache = { tool_info = {} }
|
||||
eye_spy.edit_mode = {}
|
||||
eye_spy.pending_preview_updates = {}
|
||||
eye_spy.pending_layout_refreshes = {}
|
||||
eye_spy.ui_drafts = {}
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Shared helper functions
|
||||
------------------------------------------------------------
|
||||
|
||||
-- Returns a human-readable name from a node/item id string, or nil on failure.
|
||||
-- Callers are responsible for providing their own fallback string.
|
||||
function eye_spy.readable_name_from_id(name)
|
||||
if not name or name == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local raw = tostring(name)
|
||||
local stripped = raw:match(":(.+)$") or raw
|
||||
|
||||
stripped = stripped
|
||||
:gsub("_source$", "")
|
||||
:gsub("_flowing$", "")
|
||||
:gsub("[_%-%./]+", " ")
|
||||
:gsub("%s+", " ")
|
||||
:gsub("^%s+", "")
|
||||
:gsub("%s+$", "")
|
||||
|
||||
if stripped == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
return (stripped:gsub("(%a)([%w']*)", function(a, b)
|
||||
return string.upper(a) .. string.lower(b)
|
||||
end))
|
||||
end
|
||||
|
||||
-- Returns the mod portion of a namespaced id (e.g. "default" from "default:stone").
|
||||
function eye_spy.get_modname_from_obj(obj_name)
|
||||
if not obj_name then return nil end
|
||||
return obj_name:match("([^:]+)")
|
||||
end
|
||||
|
||||
-- Rounds x to one decimal place, or returns nil if x is falsy.
|
||||
function eye_spy.round1(x)
|
||||
if x then
|
||||
return math.floor(x * 10 + 0.5) / 10
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Strips everything from the first texture-modifier caret (^) onwards.
|
||||
function eye_spy.strip_texture_modifiers(tex)
|
||||
if type(tex) ~= "string" then
|
||||
return tex
|
||||
end
|
||||
|
||||
local pos = tex:find("%^")
|
||||
if not pos then
|
||||
return tex
|
||||
end
|
||||
|
||||
return tex:sub(1, pos - 1)
|
||||
end
|
||||
|
||||
-- Parses an "R, G, B" string and returns three numbers.
|
||||
-- Falls back to 26, 26, 27 for any component that cannot be parsed.
|
||||
function eye_spy.get_rgb(v)
|
||||
if not v or v == "" then
|
||||
return 26, 26, 27
|
||||
end
|
||||
|
||||
v = v:gsub("%s", "")
|
||||
|
||||
local r, g, b = v:match("^(%d+),(%d+),(%d+)$")
|
||||
r, g, b = tonumber(r), tonumber(g), tonumber(b)
|
||||
|
||||
return r or 26, g or 26, b or 27
|
||||
end
|
||||
|
||||
-- Converts three 0-255 channel values to an uppercase hex string.
|
||||
function eye_spy.rgb_to_hex(r, g, b)
|
||||
return string.format("%02X%02X%02X", r, g, b)
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Interval system
|
||||
------------------------------------------------------------
|
||||
|
||||
local function clamp_interval_ms(value)
|
||||
return math.max(50, math.min(5000, tonumber(value) or 250))
|
||||
end
|
||||
|
||||
local function default_interval_for_mode()
|
||||
if minetest.is_singleplayer and minetest.is_singleplayer() then
|
||||
return 100
|
||||
end
|
||||
return 150
|
||||
end
|
||||
|
||||
function eye_spy.get_server_default_interval_ms()
|
||||
local raw = eye_spy.storage:get_string("server_default_interval_ms")
|
||||
if raw and raw ~= "" then
|
||||
return clamp_interval_ms(raw)
|
||||
end
|
||||
return default_interval_for_mode()
|
||||
end
|
||||
|
||||
function eye_spy.set_server_default_interval_ms(interval_ms)
|
||||
eye_spy.storage:set_string(
|
||||
"server_default_interval_ms",
|
||||
tostring(clamp_interval_ms(interval_ms))
|
||||
)
|
||||
end
|
||||
|
||||
function eye_spy.get_player_interval_override_ms(player_name)
|
||||
if not player_name or player_name == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local raw = eye_spy.storage:get_string("player_interval_ms:" .. player_name)
|
||||
if raw == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
return clamp_interval_ms(raw)
|
||||
end
|
||||
|
||||
function eye_spy.set_player_interval_override_ms(player_name, interval_ms)
|
||||
if not player_name or player_name == "" then
|
||||
return
|
||||
end
|
||||
|
||||
local key = "player_interval_ms:" .. player_name
|
||||
|
||||
if interval_ms == nil then
|
||||
eye_spy.storage:set_string(key, "")
|
||||
return
|
||||
end
|
||||
|
||||
eye_spy.storage:set_string(key, tostring(clamp_interval_ms(interval_ms)))
|
||||
end
|
||||
|
||||
function eye_spy.get_effective_interval_ms(player_name)
|
||||
return eye_spy.get_player_interval_override_ms(player_name)
|
||||
or eye_spy.get_server_default_interval_ms()
|
||||
end
|
||||
|
||||
function eye_spy.apply_player_interval(player)
|
||||
if not player then return end
|
||||
local meta = player:get_meta()
|
||||
local player_name = player:get_player_name()
|
||||
meta:set_int("es_update_interval_ms", eye_spy.get_effective_interval_ms(player_name))
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Admin / player disable system
|
||||
------------------------------------------------------------
|
||||
|
||||
-- Returns true if a server admin has suppressed this player's HUD.
|
||||
function eye_spy.is_player_server_disabled(player_name)
|
||||
if not player_name or player_name == "" then return false end
|
||||
return eye_spy.storage:get_string("player_disabled:" .. player_name) == "true"
|
||||
end
|
||||
|
||||
-- Sets or clears the server-level disable flag for a player.
|
||||
function eye_spy.set_player_server_disabled(player_name, disabled)
|
||||
if not player_name or player_name == "" then return end
|
||||
eye_spy.storage:set_string(
|
||||
"player_disabled:" .. player_name,
|
||||
disabled and "true" or ""
|
||||
)
|
||||
end
|
||||
|
||||
-- Returns true if the player has self-disabled their HUD via meta.
|
||||
function eye_spy.is_player_self_disabled(player_name)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
if not player then return false end
|
||||
return player:get_meta():get_string("es_hud_enabled") == "false"
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Player state management
|
||||
------------------------------------------------------------
|
||||
|
||||
-- Returns the runtime state table for a player, creating it if absent.
|
||||
function eye_spy.get_player_state(player)
|
||||
local player_name = player:get_player_name()
|
||||
local state = eye_spy.state.players[player_name]
|
||||
|
||||
if not state then
|
||||
state = {
|
||||
timer = 0,
|
||||
edit_mode = false,
|
||||
last_target_key = nil,
|
||||
last_render_key = nil,
|
||||
last_geom_key = nil,
|
||||
last_probe_pos = nil,
|
||||
last_probe_dir = nil,
|
||||
cached_target = nil,
|
||||
skip_static_acquire = false,
|
||||
hud_hidden_since_us = nil,
|
||||
last_recover_try_us = 0,
|
||||
hud_ids = { lines = {} },
|
||||
}
|
||||
eye_spy.state.players[player_name] = state
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
-- Clears all cached per-player data and the layout signature.
|
||||
function eye_spy.invalidate_player(player)
|
||||
local player_name = player:get_player_name()
|
||||
local state = eye_spy.get_player_state(player)
|
||||
|
||||
state.last_target_key = nil
|
||||
state.last_render_key = nil
|
||||
state.last_geom_key = nil
|
||||
state.cached_target = nil
|
||||
state.last_probe_pos = nil
|
||||
state.last_probe_dir = nil
|
||||
state.skip_static_acquire = false
|
||||
state.hud_hidden_since_us = nil
|
||||
state.last_recover_try_us = 0
|
||||
|
||||
if eye_spy.render and eye_spy.render.invalidate_layout_sig then
|
||||
eye_spy.render.invalidate_layout_sig(player_name)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Edit mode
|
||||
------------------------------------------------------------
|
||||
|
||||
function eye_spy.enter_edit_mode(player)
|
||||
if not player then return end
|
||||
|
||||
local player_name = player:get_player_name()
|
||||
local state = eye_spy.get_player_state(player)
|
||||
|
||||
if not state.edit_mode then
|
||||
eye_spy.ensure_player_defaults(player)
|
||||
state.edit_mode = true
|
||||
state.timer = 0
|
||||
eye_spy.edit_mode[player_name] = true
|
||||
|
||||
if eye_spy.ui_drafts then
|
||||
eye_spy.ui_drafts[player_name] = nil
|
||||
end
|
||||
|
||||
minetest.show_formspec(player_name, "eye_spy:ui", eye_spy.get_ui(player, { reopen = false }))
|
||||
end
|
||||
end
|
||||
|
||||
function eye_spy.exit_edit_mode(player)
|
||||
if not player then return end
|
||||
|
||||
local player_name = player:get_player_name()
|
||||
local state = eye_spy.get_player_state(player)
|
||||
|
||||
if state.edit_mode then
|
||||
local meta = player:get_meta()
|
||||
meta:set_string("es_last_obj", "")
|
||||
meta:set_int("es_last_health", -1)
|
||||
|
||||
state.edit_mode = false
|
||||
state.last_render_key = nil
|
||||
state.timer = 0
|
||||
|
||||
eye_spy.edit_mode[player_name] = false
|
||||
eye_spy.pending_preview_updates[player_name] = nil
|
||||
|
||||
if eye_spy.ui_drafts then
|
||||
eye_spy.ui_drafts[player_name] = nil
|
||||
end
|
||||
|
||||
minetest.close_formspec(player_name, "eye_spy:ui")
|
||||
minetest.close_formspec(player_name, "eye_spy:layout_ui")
|
||||
|
||||
if eye_spy.render and eye_spy.render.hide then
|
||||
eye_spy.render.hide(state, player)
|
||||
end
|
||||
|
||||
if eye_spy.render and eye_spy.render.invalidate_layout_sig then
|
||||
eye_spy.render.invalidate_layout_sig(player_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Player defaults
|
||||
------------------------------------------------------------
|
||||
|
||||
function eye_spy.ensure_player_defaults(player)
|
||||
local meta = player:get_meta()
|
||||
|
||||
if meta:get_string("es_hud_color") == "" then
|
||||
meta:set_string("es_hud_color", "26, 26, 27")
|
||||
end
|
||||
|
||||
if meta:get_string("es_hud_alignment") == "" then
|
||||
meta:set_string("es_hud_alignment", "Top-Middle")
|
||||
end
|
||||
|
||||
if meta:get_string("es_hud_health_in") == "" then
|
||||
meta:set_string("es_hud_health_in", "Points")
|
||||
end
|
||||
|
||||
if meta:get_string("es_auto_text_color") == "" then
|
||||
meta:set_string("es_auto_text_color", "true")
|
||||
end
|
||||
|
||||
if meta:get_string("es_title_color_val") == "" then
|
||||
meta:set_int("es_title_color_val", 255)
|
||||
end
|
||||
|
||||
if meta:get_string("es_subtitle_color_val") == "" then
|
||||
meta:set_int("es_subtitle_color_val", 255)
|
||||
end
|
||||
|
||||
if meta:get_string("es_footer_color_val") == "" then
|
||||
meta:set_int("es_footer_color_val", 255)
|
||||
end
|
||||
|
||||
if meta:get_string("es_line_color_val") == "" then
|
||||
meta:set_int("es_line_color_val", 255)
|
||||
end
|
||||
|
||||
if meta:get_string("es_growth_color_val") == "" then
|
||||
meta:set_int("es_growth_color_val", 110)
|
||||
end
|
||||
|
||||
if meta:get_string("es_soil_color_val") == "" then
|
||||
meta:set_int("es_soil_color_val", 165)
|
||||
end
|
||||
|
||||
if meta:get_string("es_show_growth") == "" then
|
||||
meta:set_string("es_show_growth", eye_spy.config.show_growth and "true" or "false")
|
||||
end
|
||||
|
||||
if meta:get_string("es_show_icons") == "" then
|
||||
meta:set_string("es_show_icons", eye_spy.config.show_icons and "true" or "false")
|
||||
end
|
||||
|
||||
if meta:get_string("es_layout_target") == "" then
|
||||
meta:set_string("es_layout_target", "Global")
|
||||
end
|
||||
|
||||
if meta:get_string("es_layout_step") == "" then
|
||||
meta:set_int("es_layout_step", 2)
|
||||
end
|
||||
|
||||
if meta:get_string("es_layout_page") == "" then
|
||||
meta:set_string("es_layout_page", "Position")
|
||||
end
|
||||
|
||||
if meta:get_string("es_footer_mode") == "" then
|
||||
meta:set_string("es_footer_mode", "compact")
|
||||
end
|
||||
|
||||
if meta:get_string("es_show_coords") == "" then
|
||||
meta:set_string("es_show_coords", eye_spy.config.default_show_coords and "true" or "false")
|
||||
end
|
||||
|
||||
if meta:get_string("es_show_light_level") == "" then
|
||||
meta:set_string("es_show_light_level", eye_spy.config.default_show_light_level and "true" or "false")
|
||||
end
|
||||
|
||||
if meta:get_string("es_show_spawn_hint") == "" then
|
||||
meta:set_string("es_show_spawn_hint", eye_spy.config.default_show_spawn_hint and "true" or "false")
|
||||
end
|
||||
|
||||
if meta:get_string("es_show_liquid_info") == "" then
|
||||
meta:set_string("es_show_liquid_info", eye_spy.config.default_show_liquid_info and "true" or "false")
|
||||
end
|
||||
|
||||
if meta:get_string("es_show_dig_time") == "" then
|
||||
meta:set_string("es_show_dig_time", eye_spy.config.default_show_dig_time and "true" or "false")
|
||||
end
|
||||
|
||||
if meta:get_string("es_spawn_safe_light_threshold") == "" then
|
||||
meta:set_int("es_spawn_safe_light_threshold", 8)
|
||||
end
|
||||
|
||||
-- Initialise hud-enabled flag so the disable check has a reliable baseline.
|
||||
if meta:get_string("es_hud_enabled") == "" then
|
||||
meta:set_string("es_hud_enabled", "true")
|
||||
end
|
||||
|
||||
eye_spy.apply_player_interval(player)
|
||||
|
||||
local int_defaults = {
|
||||
es_global_offset_x = 0,
|
||||
es_global_offset_y = 0,
|
||||
es_bg_offset_x = 0,
|
||||
es_bg_offset_y = 0,
|
||||
es_icon_offset_x = 0,
|
||||
es_icon_offset_y = 0,
|
||||
es_title_offset_x = 0,
|
||||
es_title_offset_y = 0,
|
||||
es_subtitle_offset_x = 0,
|
||||
es_subtitle_offset_y = 0,
|
||||
es_lines_offset_x = 0,
|
||||
es_lines_offset_y = 0,
|
||||
es_footer_offset_x = 0,
|
||||
es_footer_offset_y = 0,
|
||||
es_bg_pad_left = 7,
|
||||
es_bg_pad_right = 0,
|
||||
es_bg_pad_top = 5,
|
||||
es_bg_pad_bottom = 0,
|
||||
es_bg_extra_w = 0,
|
||||
es_bg_extra_h = 0,
|
||||
es_bg_scale_x_pct = 100,
|
||||
es_bg_scale_y_pct = 100,
|
||||
es_icon_size = 56,
|
||||
es_title_scale_pct = 100,
|
||||
es_subtitle_scale_pct = 100,
|
||||
es_line_scale_pct = 100,
|
||||
es_footer_scale_pct = 100,
|
||||
es_first_line_y_adj = 0,
|
||||
es_line_step_adj = -2, -- matches LAYOUT_META_DEFAULTS in ui.lua
|
||||
es_footer_nudge_adj = 0,
|
||||
es_text_base_x_adj = 0,
|
||||
es_icon_base_x_adj = 0,
|
||||
es_top_margin_adj = 0,
|
||||
es_bottom_margin_adj = 0,
|
||||
}
|
||||
|
||||
for key, value in pairs(int_defaults) do
|
||||
if meta:get_string(key) == "" then
|
||||
meta:set_int(key, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Core update pipeline
|
||||
------------------------------------------------------------
|
||||
|
||||
local function probe_state_matches(state, player)
|
||||
if not state.last_probe_pos or not state.last_probe_dir then
|
||||
return false
|
||||
end
|
||||
|
||||
local pos = player:get_pos()
|
||||
local dir = player:get_look_dir()
|
||||
local dx = math.abs((pos.x or 0) - (state.last_probe_pos.x or 0))
|
||||
local dy = math.abs((pos.y or 0) - (state.last_probe_pos.y or 0))
|
||||
local dz = math.abs((pos.z or 0) - (state.last_probe_pos.z or 0))
|
||||
local ddx = math.abs((dir.x or 0) - (state.last_probe_dir.x or 0))
|
||||
local ddy = math.abs((dir.y or 0) - (state.last_probe_dir.y or 0))
|
||||
local ddz = math.abs((dir.z or 0) - (state.last_probe_dir.z or 0))
|
||||
|
||||
return dx < 0.05 and dy < 0.05 and dz < 0.05
|
||||
and ddx < 0.01 and ddy < 0.01 and ddz < 0.01
|
||||
end
|
||||
|
||||
local function remember_probe_state(state, player, target)
|
||||
local pos = player:get_pos()
|
||||
local dir = player:get_look_dir()
|
||||
state.last_probe_pos = vector.new(pos)
|
||||
state.last_probe_dir = vector.new(dir)
|
||||
state.cached_target = target
|
||||
end
|
||||
|
||||
function eye_spy.update_player(player, opts)
|
||||
if not player or not eye_spy.target or not eye_spy.render then
|
||||
return
|
||||
end
|
||||
|
||||
local perf_on = eye_spy.perf.enabled and minetest.get_us_time
|
||||
local update_start_us = perf_on and minetest.get_us_time() or 0
|
||||
local options = opts or {}
|
||||
local state = eye_spy.get_player_state(player)
|
||||
local target
|
||||
|
||||
if not options.force
|
||||
and not options.preview
|
||||
and state.cached_target
|
||||
and probe_state_matches(state, player)
|
||||
and state.skip_static_acquire
|
||||
then
|
||||
target = state.cached_target
|
||||
state.skip_static_acquire = false
|
||||
else
|
||||
local acquire_start_us = perf_on and minetest.get_us_time() or 0
|
||||
target = eye_spy.target.acquire(player, options)
|
||||
if perf_on then
|
||||
eye_spy.perf_record("target_acquire", minetest.get_us_time() - acquire_start_us)
|
||||
end
|
||||
|
||||
if not options.preview then
|
||||
remember_probe_state(state, player, target)
|
||||
state.skip_static_acquire = target and target.kind ~= "air"
|
||||
end
|
||||
end
|
||||
|
||||
if not target or target.kind == "air" then
|
||||
local now_us = minetest.get_us_time and minetest.get_us_time() or 0
|
||||
|
||||
eye_spy.render.hide(state, player)
|
||||
state.last_target_key = nil
|
||||
state.last_render_key = nil
|
||||
state.cached_target = nil
|
||||
state.skip_static_acquire = false
|
||||
|
||||
if now_us > 0 and not state.hud_hidden_since_us then
|
||||
state.hud_hidden_since_us = now_us
|
||||
end
|
||||
|
||||
if perf_on then
|
||||
eye_spy.perf_record("update_player_total", minetest.get_us_time() - update_start_us)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local build_start_us = perf_on and minetest.get_us_time() or 0
|
||||
local view_model = eye_spy.render.build_view_model(player, target, options)
|
||||
if perf_on then
|
||||
eye_spy.perf_record("build_view_model", minetest.get_us_time() - build_start_us)
|
||||
end
|
||||
|
||||
if not options.force and view_model.key == state.last_render_key then
|
||||
state.last_target_key = target.key
|
||||
eye_spy.perf_inc_counter("render_skip_same_key")
|
||||
if perf_on then
|
||||
eye_spy.perf_record("update_player_total", minetest.get_us_time() - update_start_us)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local render_start_us = perf_on and minetest.get_us_time() or 0
|
||||
eye_spy.render.apply(state, player, view_model)
|
||||
if perf_on then
|
||||
eye_spy.perf_record("render_apply", minetest.get_us_time() - render_start_us)
|
||||
end
|
||||
|
||||
state.last_target_key = target.key
|
||||
state.last_render_key = view_model.key
|
||||
state.hud_hidden_since_us = nil
|
||||
state.last_recover_try_us = 0
|
||||
|
||||
if perf_on then
|
||||
eye_spy.perf_record("update_player_total", minetest.get_us_time() - update_start_us)
|
||||
end
|
||||
end
|
||||
|
||||
-- Thin wrapper used by the UI and preview system.
|
||||
function eye_spy.get_hud(player, data)
|
||||
eye_spy.update_player(player, data or {})
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Main step function
|
||||
------------------------------------------------------------
|
||||
|
||||
function eye_spy.step(dtime)
|
||||
local perf_on = eye_spy.perf.enabled and minetest.get_us_time
|
||||
local step_start_us = perf_on and minetest.get_us_time() or 0
|
||||
local now_us = minetest.get_us_time and minetest.get_us_time() or 0
|
||||
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local state = eye_spy.get_player_state(player)
|
||||
local player_name = player:get_player_name()
|
||||
local pending_preview = eye_spy.pending_preview_updates[player_name]
|
||||
|
||||
-- Service pending edit-mode preview updates.
|
||||
if state.edit_mode and pending_preview then
|
||||
local due_at = pending_preview.due_at_us or 0
|
||||
|
||||
if pending_preview.force or due_at <= now_us then
|
||||
eye_spy.pending_preview_updates[player_name] = nil
|
||||
eye_spy.update_player(player, {
|
||||
preview = true,
|
||||
preview_type = pending_preview.preview_type,
|
||||
force = pending_preview.force == true,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Service pending layout-UI refreshes.
|
||||
local pending_layout_refresh = eye_spy.pending_layout_refreshes[player_name]
|
||||
if state.edit_mode
|
||||
and pending_layout_refresh
|
||||
and pending_layout_refresh.due_at_us <= now_us
|
||||
then
|
||||
eye_spy.pending_layout_refreshes[player_name] = nil
|
||||
minetest.show_formspec(player_name, "eye_spy:layout_ui", eye_spy.get_layout_ui(player))
|
||||
end
|
||||
|
||||
if not state.edit_mode then
|
||||
local meta = player:get_meta()
|
||||
|
||||
-- Check both server-admin and player-self disable flags.
|
||||
local hud_disabled = eye_spy.is_player_server_disabled(player_name)
|
||||
or (meta:get_string("es_hud_enabled") == "false")
|
||||
|
||||
if hud_disabled then
|
||||
if state.last_render_key then
|
||||
eye_spy.render.hide(state, player)
|
||||
state.last_target_key = nil
|
||||
state.last_render_key = nil
|
||||
state.cached_target = nil
|
||||
state.skip_static_acquire = false
|
||||
end
|
||||
state.timer = 0
|
||||
goto continue_player
|
||||
end
|
||||
|
||||
local interval_ms = meta:get_int("es_update_interval_ms")
|
||||
local interval = eye_spy.get_server_default_interval_ms() / 1000
|
||||
|
||||
if interval_ms > 0 then
|
||||
interval = interval_ms / 1000
|
||||
end
|
||||
|
||||
interval = math.max(0.05, math.min(5, interval))
|
||||
state.timer = state.timer + math.min(dtime, interval)
|
||||
|
||||
if state.timer >= interval then
|
||||
state.timer = 0
|
||||
eye_spy.update_player(player, { preview = false })
|
||||
end
|
||||
|
||||
-- Focus-loss / self-heal: if the HUD appears stuck hidden while we still
|
||||
-- have a valid cached target, force an occasional refresh attempt.
|
||||
if state.hud_hidden_since_us
|
||||
and state.cached_target
|
||||
and state.cached_target.kind ~= "air"
|
||||
then
|
||||
local hidden_for_us = now_us - state.hud_hidden_since_us
|
||||
local recover_cooldown_us = 900000
|
||||
|
||||
if hidden_for_us >= 1200000
|
||||
and (state.last_recover_try_us or 0) + recover_cooldown_us <= now_us
|
||||
then
|
||||
state.last_recover_try_us = now_us
|
||||
eye_spy.perf_inc_counter("hud_recover_forced_refresh")
|
||||
eye_spy.update_player(player, { preview = false, force = true })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
::continue_player::
|
||||
end
|
||||
|
||||
if perf_on then
|
||||
eye_spy.perf_record("step_total", minetest.get_us_time() - step_start_us)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------
|
||||
-- HUD cleanup
|
||||
------------------------------------------------------------
|
||||
|
||||
function eye_spy.remove_huds(player)
|
||||
if eye_spy.render then eye_spy.render.remove(player) end
|
||||
end
|
||||
Reference in New Issue
Block a user