From 0e4b06aaa2739cd4cb8711bbee5c40b2d1302a85 Mon Sep 17 00:00:00 2001 From: SFENCE Date: Mon, 25 Dec 2023 11:33:45 +0100 Subject: [PATCH 1/3] Add override posibility for abm, lbm and entities. --- builtin/game/register.lua | 105 ++++++++++++++++++++++++++++++++ src/script/cpp_api/s_client.cpp | 4 ++ src/script/cpp_api/s_server.cpp | 4 ++ 3 files changed, 113 insertions(+) diff --git a/builtin/game/register.lua b/builtin/game/register.lua index 3e4b9be968ac7..ceda61b90a651 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -91,7 +91,14 @@ local function check_node_list(list, field) end function core.register_abm(spec) + if core.is_mods_loaded then + core.log("error", "Function register_abm cannot be called after mods are loaded.") + return + end -- Add to core.registered_abms + if spec.name then + check_modname_prefix(spec.name) + end check_node_list(spec.nodenames, "nodenames") check_node_list(spec.neighbors, "neighbors") assert(type(spec.action) == "function", "Required field 'action' of type function") @@ -99,7 +106,31 @@ function core.register_abm(spec) spec.mod_origin = core.get_current_modname() or "??" end +function core.override_abm(name, redefinition) + if core.is_mods_loaded then + core.log("error", "Function override_abm cannot be called after mods are loaded.") + return + end + -- Override abm in core.registered_abms + if redefinition.name ~= nil then + error("Attempt to redefine abm name of "..name.." to "..dump(redefinition.name), 2) + end + check_node_list(redefinition.nodenames, "nodenames") + for _, abm in pairs(core.registered_abms) do + if (abm.name == name) then + for k, v in pairs(redefinition) do + rawset(abm, k, v) + end + return + end + end +end + function core.register_lbm(spec) + if core.is_mods_loaded then + core.log("error", "Function register_lbm cannot be called after mods are loaded.") + return + end -- Add to core.registered_lbms check_modname_prefix(spec.name) check_node_list(spec.nodenames, "nodenames") @@ -113,7 +144,32 @@ function core.register_lbm(spec) spec.mod_origin = core.get_current_modname() or "??" end +function core.override_lbm(name, redefinition) + if core.is_mods_loaded then + core.log("error", "Function override_lbm cannot be called after mods are loaded.") + return + end + -- Override lbm in core.registered_lbms + if redefinition.name ~= nil then + error("Attempt to redefine lbm name of "..name.." to "..dump(redefinition.name), 2) + end + check_node_list(redefinition.nodenames, "nodenames") + assert(type(redefinition.action) == "function", "Required field 'action' of type function") + for _, lbm in pairs(core.registered_lbms) do + if (lbm.name == name) then + for k, v in pairs(redefinition) do + rawset(lbm, k, v) + end + return + end + end +end + function core.register_entity(name, prototype) + if core.is_mods_loaded then + core.log("error", "Function register_entity cannot be called after mods are loaded.") + return + end -- Check name if name == nil then error("Unable to register entity: Name is nil") @@ -128,7 +184,32 @@ function core.register_entity(name, prototype) prototype.mod_origin = core.get_current_modname() or "??" end +function core.override_entity(name, redefinition) + if core.is_mods_loaded then + core.log("error", "Function override_entity cannot be called after mods are loaded.") + return + end + if redefinition.name ~= nil then + error("Attempt to redefine entity name of "..name.." to "..dump(redefinition.name), 2) + end + if redefinition.type ~= nil then + error("Attempt to redefine type of "..name.." to "..dump(redefinition.type), 2) + end + local entity = core.registered_entities[name] + if not entity then + error("Attempt to override non-existent entity "..name, 2) + end + for k, v in pairs(redefinition) do + rawset(entity, k, v) + end + core.registered_entities[name] = entity +end + function core.register_item(name, itemdef) + if core.is_mods_loaded then + core.log("error", "Function register_item cannot be called after mods are loaded.") + return + end -- Check name if name == nil then error("Unable to register item: Name is nil") @@ -204,6 +285,10 @@ function core.register_item(name, itemdef) end function core.unregister_item(name) + if core.is_mods_loaded then + core.log("error", "Function unregister_item cannot be called after mods are loaded.") + return + end if not core.registered_items[name] then core.log("warning", "Not unregistering item " ..name.. " because it doesn't exist.") @@ -225,11 +310,19 @@ function core.unregister_item(name) end function core.register_node(name, nodedef) + if core.is_mods_loaded then + core.log("error", "Function register_node cannot be called after mods are loaded.") + return + end nodedef.type = "node" core.register_item(name, nodedef) end function core.register_craftitem(name, craftitemdef) + if core.is_mods_loaded then + core.log("error", "Function register_craftitem cannot be called after mods are loaded.") + return + end craftitemdef.type = "craft" -- BEGIN Legacy stuff @@ -242,6 +335,10 @@ function core.register_craftitem(name, craftitemdef) end function core.register_tool(name, tooldef) + if core.is_mods_loaded then + core.log("error", "Function register_tool cannot be called after mods are loaded.") + return + end tooldef.type = "tool" tooldef.stack_max = 1 @@ -293,6 +390,10 @@ function core.register_tool(name, tooldef) end function core.register_alias(name, convert_to) + if core.is_mods_loaded then + core.log("error", "Function register_alias cannot be called after mods are loaded.") + return + end if forbidden_item_names[name] then error("Unable to register alias: Name is forbidden: " .. name) end @@ -307,6 +408,10 @@ function core.register_alias(name, convert_to) end function core.register_alias_force(name, convert_to) + if core.is_mods_loaded then + core.log("error", "Function register_alias_force cannot be called after mods are loaded.") + return + end if forbidden_item_names[name] then error("Unable to register alias: Name is forbidden: " .. name) end diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 772bc24121af1..2c3c7e58cdaa9 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -25,6 +25,10 @@ void ScriptApiClient::on_mods_loaded() } catch (LuaError &e) { getClient()->setFatalError(e); } + // set is_mods_loaded + lua_getglobal(L, "core"); + lua_pushboolean(L, true); + lua_setfield(L, -2, "is_mods_loaded"); } void ScriptApiClient::on_shutdown() diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp index faacf97141f7a..933ded7367496 100644 --- a/src/script/cpp_api/s_server.cpp +++ b/src/script/cpp_api/s_server.cpp @@ -147,6 +147,10 @@ void ScriptApiServer::on_mods_loaded() lua_getfield(L, -1, "registered_on_mods_loaded"); // Call callbacks runCallbacks(0, RUN_CALLBACKS_MODE_FIRST); + // set is_mods_loaded + lua_getglobal(L, "core"); + lua_pushboolean(L, true); + lua_setfield(L, -2, "is_mods_loaded"); } void ScriptApiServer::on_shutdown() From 356a0aa5c6b360a908c91f2e10485b6dde1c139f Mon Sep 17 00:00:00 2001 From: SFENCE Date: Fri, 29 Dec 2023 12:06:50 +0100 Subject: [PATCH 2/3] Documentation update. --- doc/lua_api.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index 6db358c85c5e5..19d1b9c32e038 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -5851,8 +5851,11 @@ Call these functions only at load time! `name` from `core.registered_items` and from the associated item table according to its nature: `core.registered_nodes`, etc. * `core.register_entity(name, entity definition)` +* `core.override_entity(name, entity definition)` * `core.register_abm(abm definition)` +* `core.override_abm(name, abm definition)` * `core.register_lbm(lbm definition)` +* `core.override_lbm(name, lbm definition)` * `core.register_alias(alias, original_name)` * Also use this to set the 'mapgen aliases' needed in a game for the core mapgens. See [Mapgen aliases] section above. @@ -9276,7 +9279,7 @@ Player properties need to be saved manually. Entity definition ----------------- -Used by `core.register_entity`. +Used by `core.register_entity` and `core.override_entity`. The entity definition table becomes a metatable of a newly created per-entity luaentity table, meaning its fields (e.g. `initial_properties`) will be shared between all instances of an entity. @@ -9314,7 +9317,7 @@ between all instances of an entity. ABM (ActiveBlockModifier) definition ------------------------------------ -Used by `core.register_abm`. +Used by `core.register_abm` and `core.override_abm`. ```lua { @@ -9322,6 +9325,10 @@ Used by `core.register_abm`. -- Descriptive label for profiling purposes (optional). -- Definitions with identical labels will be listed as one. + name = "modname:replace_legacy_door", + -- Optional filed, required for make ABM overridable. + -- Identifier of the ABM, should follow the modname: convention. + nodenames = {"default:lava_source"}, -- Apply `action` function to these nodes. -- `group:groupname` can also be used here. @@ -9368,7 +9375,7 @@ Used by `core.register_abm`. LBM (LoadingBlockModifier) definition ------------------------------------- -Used by `core.register_lbm`. +Used by `core.register_lbm` and `core.override_lbm`. A loading block modifier (LBM) is used to define a function that is called for specific nodes (defined by `nodenames`) when a mapblock which contains such nodes @@ -9386,7 +9393,8 @@ contain a matching node. -- Definitions with identical labels will be listed as one. name = "modname:replace_legacy_door", - -- Identifier of the LBM, should follow the modname: convention + -- Identifier of the LBM, should follow the modname: convention. + -- Also used for overriding LBM. nodenames = {"default:lava_source"}, -- List of node names to trigger the LBM on. From 227c304685e2e856a98e8ff9b79b272f1056f57a Mon Sep 17 00:00:00 2001 From: SFENCE Date: Fri, 29 Dec 2023 20:20:09 +0100 Subject: [PATCH 3/3] Add test nodes and unittest for override entity. Fix bugs. --- builtin/game/register.lua | 11 +++-- games/devtest/mods/testabms/after_node.lua | 1 - games/devtest/mods/testabms/chances.lua | 1 - games/devtest/mods/testabms/init.lua | 1 + games/devtest/mods/testabms/intervals.lua | 1 - games/devtest/mods/testabms/min_max.lua | 1 - games/devtest/mods/testabms/neighbors.lua | 1 - games/devtest/mods/testabms/override.lua | 40 ++++++++++++++++ games/devtest/mods/testlbms/README.md | 5 ++ games/devtest/mods/testlbms/init.lua | 45 ++++++++++++++++++ games/devtest/mods/testlbms/mod.conf | 2 + .../testlbms/textures/testlbms_after_node.png | Bin 0 -> 194 bytes .../testlbms/textures/testlbms_wait_node.png | Bin 0 -> 183 bytes games/devtest/mods/unittests/entity.lua | 27 ++++++++++- src/unittest/test_servermodmanager.cpp | 2 +- 15 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 games/devtest/mods/testabms/override.lua create mode 100644 games/devtest/mods/testlbms/README.md create mode 100644 games/devtest/mods/testlbms/init.lua create mode 100644 games/devtest/mods/testlbms/mod.conf create mode 100644 games/devtest/mods/testlbms/textures/testlbms_after_node.png create mode 100644 games/devtest/mods/testlbms/textures/testlbms_wait_node.png diff --git a/builtin/game/register.lua b/builtin/game/register.lua index ceda61b90a651..b41fd0c3e55af 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -192,15 +192,18 @@ function core.override_entity(name, redefinition) if redefinition.name ~= nil then error("Attempt to redefine entity name of "..name.." to "..dump(redefinition.name), 2) end - if redefinition.type ~= nil then - error("Attempt to redefine type of "..name.." to "..dump(redefinition.type), 2) - end local entity = core.registered_entities[name] if not entity then error("Attempt to override non-existent entity "..name, 2) end for k, v in pairs(redefinition) do - rawset(entity, k, v) + if k ~= "initial_properties" then + rawset(entity, k, v) + else + for k2, v2 in pairs(v) do + rawset(entity.initial_properties, k2, v2) + end + end end core.registered_entities[name] = entity end diff --git a/games/devtest/mods/testabms/after_node.lua b/games/devtest/mods/testabms/after_node.lua index fa2b3ab1600ca..d0d9d8866a345 100644 --- a/games/devtest/mods/testabms/after_node.lua +++ b/games/devtest/mods/testabms/after_node.lua @@ -9,4 +9,3 @@ core.register_node("testabms:after_abm", { groups = { dig_immediate = 3 }, }) - diff --git a/games/devtest/mods/testabms/chances.lua b/games/devtest/mods/testabms/chances.lua index a84e75260fcae..06f22605aca9b 100644 --- a/games/devtest/mods/testabms/chances.lua +++ b/games/devtest/mods/testabms/chances.lua @@ -53,4 +53,3 @@ core.register_abm({ meta:set_string("infotext", "ABM testabsm:chance_20 changed this node.") end }) - diff --git a/games/devtest/mods/testabms/init.lua b/games/devtest/mods/testabms/init.lua index 8bf4975cf9738..0926f6498cda0 100644 --- a/games/devtest/mods/testabms/init.lua +++ b/games/devtest/mods/testabms/init.lua @@ -5,3 +5,4 @@ dofile(path.."/chances.lua") dofile(path.."/intervals.lua") dofile(path.."/min_max.lua") dofile(path.."/neighbors.lua") +dofile(path.."/override.lua") diff --git a/games/devtest/mods/testabms/intervals.lua b/games/devtest/mods/testabms/intervals.lua index 928406508b160..8f432f21d3352 100644 --- a/games/devtest/mods/testabms/intervals.lua +++ b/games/devtest/mods/testabms/intervals.lua @@ -53,4 +53,3 @@ core.register_abm({ meta:set_string("infotext", "ABM testabsm:interval_60 changed this node.") end }) - diff --git a/games/devtest/mods/testabms/min_max.lua b/games/devtest/mods/testabms/min_max.lua index b5df4e40ec00d..7b26b08d9d48e 100644 --- a/games/devtest/mods/testabms/min_max.lua +++ b/games/devtest/mods/testabms/min_max.lua @@ -55,4 +55,3 @@ core.register_abm({ meta:set_string("infotext", "ABM testabsm:max_y changed this node.") end }) - diff --git a/games/devtest/mods/testabms/neighbors.lua b/games/devtest/mods/testabms/neighbors.lua index 0ce21c23cec2f..ca79edfc2b52b 100644 --- a/games/devtest/mods/testabms/neighbors.lua +++ b/games/devtest/mods/testabms/neighbors.lua @@ -96,4 +96,3 @@ core.register_abm({ "ABM testabsm:required_missing_neighbor changed this node.") end }) - diff --git a/games/devtest/mods/testabms/override.lua b/games/devtest/mods/testabms/override.lua new file mode 100644 index 0000000000000..6c2fe0918e6af --- /dev/null +++ b/games/devtest/mods/testabms/override.lua @@ -0,0 +1,40 @@ +-- test ABMs with override + +local S = core.get_translator("testabms") + +-- ABM override +core.register_node("testabms:override", { + description = S("Node for test ABM override"), + drawtype = "normal", + tiles = { "testabms_wait_node.png" }, + + groups = { dig_immediate = 3 }, + + on_construct = function (pos) + local meta = core.get_meta(pos) + meta:set_string("infotext", "Waiting for ABM testabms:overrid") + end, +}) + +core.register_abm({ + label = "testabms:override", + name = "testabms:override", + nodenames = "testabms:override", + interval = 1000, + chance = 5000, + action = function (pos) + core.swap_node(pos, {name="testabms:after_abm"}) + local meta = core.get_meta(pos) + meta:set_string("infotext", "ABM testabms:override changed this node.") + end + }) + +core.override_abm("testabms:override", { + interval = 1, + chance = 1, + action = function (pos) + core.swap_node(pos, {name="testabms:after_abm"}) + local meta = core.get_meta(pos) + meta:set_string("infotext", "Override ABM testabms:override changed this node.") + end + }) diff --git a/games/devtest/mods/testlbms/README.md b/games/devtest/mods/testlbms/README.md new file mode 100644 index 0000000000000..0be7847bb882e --- /dev/null +++ b/games/devtest/mods/testlbms/README.md @@ -0,0 +1,5 @@ +# Test LBMs + +This mod contains a nodes and related LBM actions. +By placing these nodes, you can test basic LBM behaviours. + diff --git a/games/devtest/mods/testlbms/init.lua b/games/devtest/mods/testlbms/init.lua new file mode 100644 index 0000000000000..06d11d7fd2ee2 --- /dev/null +++ b/games/devtest/mods/testlbms/init.lua @@ -0,0 +1,45 @@ +local S = minetest.get_translator("testlbms") + +-- After LBM node +minetest.register_node("testlbms:after_lbm", { + description = S("After LBM processed node."), + drawtype = "normal", + tiles = { "testlbms_after_node.png" }, + + groups = { dig_immediate = 3 }, +}) + +-- LBM onload change +minetest.register_node("testlbms:onload_change", { + description = S("Node for test LBM"), + drawtype = "normal", + tiles = { "testlbms_wait_node.png" }, + + groups = { dig_immediate = 3 }, + + on_construct = function (pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Waiting for LBM testlbms:chance_5") + end, +}) + +minetest.register_lbm({ + label = "testlbms:onload_change", + name = "testlbms:onload_change", + nodenames = "testlbms:onload_change", + run_at_every_load = true, + action = function (pos) + minetest.swap_node(pos, {name="testlbms:after_lbm"}) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "LBM testlbms:onload_change changed this node.") + end + }) + +minetest.override_lbm("testlbms:onload_change", { + action = function (pos) + minetest.swap_node(pos, {name="testlbms:after_lbm"}) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Override LBM testlbms:onload_change changed this node.") + end, + }) + diff --git a/games/devtest/mods/testlbms/mod.conf b/games/devtest/mods/testlbms/mod.conf new file mode 100644 index 0000000000000..b94f5e1301e63 --- /dev/null +++ b/games/devtest/mods/testlbms/mod.conf @@ -0,0 +1,2 @@ +name = testlbms +description = Contains some nodes for test LBMs. diff --git a/games/devtest/mods/testlbms/textures/testlbms_after_node.png b/games/devtest/mods/testlbms/textures/testlbms_after_node.png new file mode 100644 index 0000000000000000000000000000000000000000..9bdb1987d979a7a8677b5d69a6e29ecf17bb3728 GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf-HME>E{iEB7#oC1mh6vvDC019?XSk2+e|i!yV=c-U|RBc-rqV~M^S!