mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
Prevent registration of certain new content after load time
This commit is contained in:
parent
ca047c3e58
commit
a9a3b05cc3
3 changed files with 55 additions and 6 deletions
|
@ -59,6 +59,9 @@ end
|
||||||
local alias_metatable = {
|
local alias_metatable = {
|
||||||
__index = function(t, name)
|
__index = function(t, name)
|
||||||
return rawget(t, core.registered_aliases[name])
|
return rawget(t, core.registered_aliases[name])
|
||||||
|
end,
|
||||||
|
__newindex = function()
|
||||||
|
error("table is read-only")
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
setmetatable(core.registered_items, alias_metatable)
|
setmetatable(core.registered_items, alias_metatable)
|
||||||
|
|
|
@ -36,6 +36,9 @@ end
|
||||||
local alias_metatable = {
|
local alias_metatable = {
|
||||||
__index = function(t, name)
|
__index = function(t, name)
|
||||||
return rawget(t, core.registered_aliases[name])
|
return rawget(t, core.registered_aliases[name])
|
||||||
|
end,
|
||||||
|
__newindex = function()
|
||||||
|
error("table is read-only")
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
setmetatable(core.registered_items, alias_metatable)
|
setmetatable(core.registered_items, alias_metatable)
|
||||||
|
|
|
@ -61,7 +61,7 @@ local function check_modname_prefix(name)
|
||||||
return name:sub(2)
|
return name:sub(2)
|
||||||
else
|
else
|
||||||
-- Enforce that the name starts with the correct mod name.
|
-- Enforce that the name starts with the correct mod name.
|
||||||
local expected_prefix = core.get_current_modname() .. ":"
|
local expected_prefix = (core.get_current_modname() or "") .. ":"
|
||||||
if name:sub(1, #expected_prefix) ~= expected_prefix then
|
if name:sub(1, #expected_prefix) ~= expected_prefix then
|
||||||
error("Name " .. name .. " does not follow naming conventions: " ..
|
error("Name " .. name .. " does not follow naming conventions: " ..
|
||||||
"\"" .. expected_prefix .. "\" or \":\" prefix required")
|
"\"" .. expected_prefix .. "\" or \":\" prefix required")
|
||||||
|
@ -95,6 +95,7 @@ function core.register_abm(spec)
|
||||||
check_node_list(spec.nodenames, "nodenames")
|
check_node_list(spec.nodenames, "nodenames")
|
||||||
check_node_list(spec.neighbors, "neighbors")
|
check_node_list(spec.neighbors, "neighbors")
|
||||||
assert(type(spec.action) == "function", "Required field 'action' of type function")
|
assert(type(spec.action) == "function", "Required field 'action' of type function")
|
||||||
|
|
||||||
core.registered_abms[#core.registered_abms + 1] = spec
|
core.registered_abms[#core.registered_abms + 1] = spec
|
||||||
spec.mod_origin = core.get_current_modname() or "??"
|
spec.mod_origin = core.get_current_modname() or "??"
|
||||||
end
|
end
|
||||||
|
@ -581,15 +582,57 @@ core.registered_on_rightclickplayers, core.register_on_rightclickplayer = make_r
|
||||||
core.registered_on_liquid_transformed, core.register_on_liquid_transformed = make_registration()
|
core.registered_on_liquid_transformed, core.register_on_liquid_transformed = make_registration()
|
||||||
core.registered_on_mapblocks_changed, core.register_on_mapblocks_changed = make_registration()
|
core.registered_on_mapblocks_changed, core.register_on_mapblocks_changed = make_registration()
|
||||||
|
|
||||||
|
-- A bunch of registrations are read by the C++ side once on env init, so we cannot
|
||||||
|
-- allow them to change afterwards (see s_env.cpp).
|
||||||
|
-- Nodes and items do not have this problem but there are obvious consistency
|
||||||
|
-- problems if this would be allowed.
|
||||||
|
|
||||||
|
local function freeze_table(t)
|
||||||
|
-- Freezing a Lua table is not actually possible without some very intrusive
|
||||||
|
-- metatable hackery, but we can trivially prevent new additions.
|
||||||
|
local mt = table.copy(getmetatable(t) or {})
|
||||||
|
mt.__newindex = function()
|
||||||
|
error("modification forbidden")
|
||||||
|
end
|
||||||
|
setmetatable(t, mt)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function generic_reg_error(what)
|
||||||
|
return function(something)
|
||||||
|
local described = what
|
||||||
|
if type(something) == "table" and type(something.name) == "string" then
|
||||||
|
described = what .. " " .. something.name
|
||||||
|
elseif type(something) == "string" then
|
||||||
|
described = what .. " " .. something
|
||||||
|
end
|
||||||
|
error("Tried to register " .. described .. " after load time!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
core.register_on_mods_loaded(function()
|
core.register_on_mods_loaded(function()
|
||||||
core.after(0, function()
|
core.after(0, function()
|
||||||
itemdefs_finalized = true
|
itemdefs_finalized = true
|
||||||
|
|
||||||
setmetatable(core.registered_on_mapblocks_changed, {
|
-- prevent direct modification
|
||||||
__newindex = function()
|
freeze_table(core.registered_abms)
|
||||||
error("on_mapblocks_changed callbacks must be registered at load time")
|
freeze_table(core.registered_lbms)
|
||||||
end,
|
freeze_table(core.registered_items)
|
||||||
})
|
freeze_table(core.registered_nodes)
|
||||||
|
freeze_table(core.registered_craftitems)
|
||||||
|
freeze_table(core.registered_tools)
|
||||||
|
freeze_table(core.registered_aliases)
|
||||||
|
freeze_table(core.registered_on_mapblocks_changed)
|
||||||
|
|
||||||
|
-- neutralize registration functions
|
||||||
|
core.register_abm = generic_reg_error("ABM")
|
||||||
|
core.register_lbm = generic_reg_error("LBM")
|
||||||
|
core.register_item = generic_reg_error("item")
|
||||||
|
core.unregister_item = function(name)
|
||||||
|
error("Refusing to unregister item " .. name .. " after load time")
|
||||||
|
end
|
||||||
|
core.register_alias = generic_reg_error("alias")
|
||||||
|
core.register_alias_force = generic_reg_error("alias")
|
||||||
|
core.register_on_mapblocks_changed = generic_reg_error("on_mapblocks_changed callback")
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue