Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add convenience functions for overriding ABMs, LBMs and entities #14178

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions builtin/game/register.lua
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,46 @@ 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")
core.registered_abms[#core.registered_abms + 1] = 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")
Expand All @@ -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")
Expand All @@ -128,7 +184,35 @@ 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
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
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

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")
Expand Down Expand Up @@ -204,6 +288,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.")
Expand All @@ -225,11 +313,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
Expand All @@ -242,6 +338,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

Expand Down Expand Up @@ -293,6 +393,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
Expand All @@ -307,6 +411,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
Expand Down
16 changes: 12 additions & 4 deletions doc/lua_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -9314,14 +9317,18 @@ between all instances of an entity.
ABM (ActiveBlockModifier) definition
------------------------------------

Used by `core.register_abm`.
Used by `core.register_abm` and `core.override_abm`.

```lua
{
label = "Lava cooling",
-- 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:<whatever> convention.

nodenames = {"default:lava_source"},
-- Apply `action` function to these nodes.
-- `group:groupname` can also be used here.
Expand Down Expand Up @@ -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
Expand All @@ -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:<whatever> convention
-- Identifier of the LBM, should follow the modname:<whatever> convention.
-- Also used for overriding LBM.

nodenames = {"default:lava_source"},
-- List of node names to trigger the LBM on.
Expand Down
1 change: 0 additions & 1 deletion games/devtest/mods/testabms/after_node.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ core.register_node("testabms:after_abm", {

groups = { dig_immediate = 3 },
})

1 change: 0 additions & 1 deletion games/devtest/mods/testabms/chances.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,3 @@ core.register_abm({
meta:set_string("infotext", "ABM testabsm:chance_20 changed this node.")
end
})

1 change: 1 addition & 0 deletions games/devtest/mods/testabms/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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")
1 change: 0 additions & 1 deletion games/devtest/mods/testabms/intervals.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,3 @@ core.register_abm({
meta:set_string("infotext", "ABM testabsm:interval_60 changed this node.")
end
})

1 change: 0 additions & 1 deletion games/devtest/mods/testabms/min_max.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,3 @@ core.register_abm({
meta:set_string("infotext", "ABM testabsm:max_y changed this node.")
end
})

1 change: 0 additions & 1 deletion games/devtest/mods/testabms/neighbors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,3 @@ core.register_abm({
"ABM testabsm:required_missing_neighbor changed this node.")
end
})

40 changes: 40 additions & 0 deletions games/devtest/mods/testabms/override.lua
Original file line number Diff line number Diff line change
@@ -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
})
5 changes: 5 additions & 0 deletions games/devtest/mods/testlbms/README.md
Original file line number Diff line number Diff line change
@@ -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.

45 changes: 45 additions & 0 deletions games/devtest/mods/testlbms/init.lua
Original file line number Diff line number Diff line change
@@ -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,
})

2 changes: 2 additions & 0 deletions games/devtest/mods/testlbms/mod.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name = testlbms
description = Contains some nodes for test LBMs.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading