Disable ABMs in favor of nodetimers to check if kelp is unsubmerged.

This commit is contained in:
iliekprogrammar 2021-03-28 20:29:29 +08:00
parent e76a0ba6e8
commit 24da94ec3b
1 changed files with 94 additions and 70 deletions

View File

@ -1,7 +1,11 @@
-- NOTE: whenever it becomes possible to fully implement kelp without the
-- TODO: whenever it becomes possible to fully implement kelp without the
-- plantlike_rooted limitation, please adapt the code accordingly.
--
-- TODO: In MC, you can't actually destroy kelp by bucket'ing water in the middle.
-- However, because of the plantlike_rooted hack, we'll just allow it for now.
--
-- TODO: Currently, you lose kelp if the kelp is placed on a block and then falls.
-- This is most relevant for (red)sand and gravel.
local S = minetest.get_translator("mcl_ocean")
local mod_doc = minetest.get_modpath("doc") ~= nil
@ -25,6 +29,7 @@ local mt_hash_node_position = minetest.hash_node_position
local mt_get_node_timer = minetest.get_node_timer
-- DEBUG: functions
local log = minetest.log
local chatlog = minetest.chat_send_all
--------------------------------------------------------------------------------
@ -130,7 +135,9 @@ kelp.detach_drop = detach_drop
-- Detach the kelp at dig_pos, and drop their items.
-- Synonyous to digging the kelp
-- Synonymous to digging the kelp.
-- NOTE: this is intended for whenever kelp truly becomes segmented plants
-- instead of rooted to the floor. Don't try to remove dig_pos.
local function detach_dig(dig_pos, pos, node, is_drop)
local param2 = node.param2
-- pos.y points to the surface, offset needed to point to the first kelp.
@ -159,6 +166,72 @@ kelp.detach_dig = detach_dig
-- Kelp callback functions
--------------------------------------------------------------------------------
local function surface_on_dig(pos, node, digger)
-- NOTE: if instead, kelp shouldn't drop in creative: use this instead
-- detach_dig(pos, pos, node,
-- not (digger and mt_is_creative_enabled(digger:get_player_name())))
detach_dig(pos, pos, node, true)
end
kelp.surface_on_dig = surface_on_dig
local function surface_after_dig_node(pos, node)
return mt_set_node(pos, {name=registred_nodes[node.name].node_dig_prediction})
end
kelp.surface_after_dig_node = surface_after_dig_node
local kelp_timers = {}
local kelp_timers_counter = 0
local function surface_on_timer(pos, elapsed)
local node = mt_get_node(pos)
local dig_pos = find_unsubmerged(pos, node)
if dig_pos then
detach_dig(dig_pos, pos, node, true)
end
return true
end
-- NOTE: Uncomment this to use ABMs
-- local function surface_unsubmerged_abm(pos, node)
-- local dig_pos = find_unsubmerged(pos, node)
-- if dig_pos then
-- detach_dig(dig_pos, pos, node, true)
-- end
-- return true
-- end
-- NOTE: Uncomment this to use nodetimers
local function surface_register_nodetimer(pos, node)
local pos_hash = mt_hash_node_position(pos)
if kelp_timers[pos_hash] then
return
end
local timer = mt_get_node_timer(pos)
kelp_timers[pos_hash] = timer
timer:start(0.5)
kelp_timers_counter = kelp_timers_counter + 1
chatlog("added a timer. Currently " ..tostring(kelp_timers_counter) .." timers")
end
kelp.surface_register_nodetiemr = surface_register_nodetimer
local function grow_kelp(pos, node)
local grow
-- Grow kelp by 1 node length if it would grow inside water
node.param2, grow = next_param2(node.param2)
local pos_top, node_top = get_tip(pos, node)
local def_top = registered_nodes[node_top.name]
if grow and is_submerged(node_top, def_top) then
next_grow(pos, node, pos_top, def_top,
is_downward_flowing(pos_top, node_top, def_top))
end
end
kelp.grow_kelp = grow_kelp
local function kelp_on_place(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" or not placer then
return itemstack
@ -171,6 +244,7 @@ local function kelp_on_place(itemstack, placer, pointed_thing)
local nu_name = node_under.name
local def_under = registered_nodes[nu_name]
-- Allow rightclick override.
if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then
return def_under.on_rightclick(pos_under, node_under,
placer, itemstack, pointed_thing) or itemstack
@ -222,6 +296,10 @@ local function kelp_on_place(itemstack, placer, pointed_thing)
pos_top = pos_above
node_top = mt_get_node(pos_above)
def_top = registered_nodes[node_top.name]
-- NOTE: Uncomment this to use nodetimers
-- Register nodetimer
surface_register_nodetimer(pos_under, node_under)
end
-- New kelp must also be submerged in water.
@ -244,50 +322,6 @@ local function kelp_on_place(itemstack, placer, pointed_thing)
end
kelp.kelp_on_place = kelp_on_place
local function surface_on_dig(pos, node, digger)
-- TODO: poll on whether if players like dropping kelp in creative
-- detach_dig(pos, pos, node,
-- not (digger and mt_is_creative_enabled(digger:get_player_name())))
detach_dig(pos, pos, node, true)
end
kelp.surface_on_dig = surface_on_dig
local function surface_after_dig_node(pos, node)
return mt_set_node(pos, {name=registred_nodes[node.name].node_dig_prediction})
end
kelp.surface_after_dig_node = surface_after_dig_node
local function grow_kelp(pos, node)
local grow
-- Grow kelp by 1 node length if it would grow inside water
node.param2, grow = next_param2(node.param2)
local pos_top, node_top = get_tip(pos, node)
local def_top = registered_nodes[node_top.name]
if grow and is_submerged(node_top, def_top) then
next_grow(pos, node, pos_top, def_top,
is_downward_flowing(pos_top, node_top, def_top))
end
end
kelp.grow_kelp = grow_kelp
local kelp_timers_idx = {}
local kelp_timers = {}
local function surface_register_nodetimer(pos, node)
local pos_hash = mt_hash_node_position(pos)
if kelp_timers_idx[pos_hash] then
return
end
local timer = mt_get_node_timer(pos)
table.insert(kelp_timers, timer)
kelp_timers_idx[pos_hash] = #kelp_timers
chatlog("added a timer. Currently " ..tostring(#kelp_timers) .." timers")
end
kelp.surface_register_nodetiemr = surface_register_nodetimer
--------------------------------------------------------------------------------
-- Kelp registration API
--------------------------------------------------------------------------------
@ -303,8 +337,8 @@ kelp.surfaces = surfaces
local registered_surfaces = {}
kelp.registered_surfaces = registered_surfaces
-- Commented keys are the ones obtained using register_kelp_surface.
-- If you define your own keys, that keys will be used instead.
-- Commented properties are the ones obtained using register_kelp_surface.
-- If you define your own properties, it overrides the default ones.
local surface_deftemplate = {
drawtype = "plantlike_rooted",
paramtype = "light",
@ -333,6 +367,7 @@ local surface_deftemplate = {
--node_dig_prediction = nodename,
after_dig_node = surface_after_dig_node,
on_dig = surface_on_dig,
on_timer = surface_on_timer,
drop = "", -- drops are handled in on_dig
--_mcl_falling_node_alternative = is_falling and nodename or nil,
_mcl_hardness = 0,
@ -340,7 +375,7 @@ local surface_deftemplate = {
}
kelp.surface_deftemplate = surface_deftemplate
-- Commented keys are the ones obtained using register_kelp_surface.
-- Commented properties are the ones obtained using register_kelp_surface.
local surface_docs = {
-- entry_id_orig = nodename,
_doc_items_entry_name = S("Kelp"),
@ -353,19 +388,12 @@ kelp.surface_docs = surface_docs
--[==[--
register_kelp_surface(surface[, surface_deftemplate[, surface_docs]])
surface: table with the specifications below. See also kelp.surface.
{
name="dirt",
The name of the surface. This will appended to the surface's nodedef name
nodename="mcl_core:dirt"
The nodename of the surface kelp can be planted on.
}
surface: table with its specific properties. See also kelp.surface.
surface_deftemplate: modifiable nodedef template. See also kelp.surface_deftempate.
DO NOT RE-USE THE SAME DEFTEMPLATE. create copies.
surface_docs: table with keys related to docs. See also kelp.surface_docs.
surface_docs: table with properties related to docs. See also kelp.surface_docs.
--]==]--
local leaf_sounds = mcl_sounds.node_sound_leaves_defaults()
local function register_kelp_surface(surface, surface_deftemplate, surface_docs)
@ -403,7 +431,7 @@ local function register_kelp_surface(surface, surface_deftemplate, surface_docs)
surface_deftemplate.sounds = surface_deftemplate.sound or sounds
local falling_node = mt_get_item_group(nodename, "falling_node")
surface_deftemplate.node_dig_prediction = surface_deftemplate.node_dig_prediction or nodename
surface_deftemplate.groups.faling_node = surface_deftemplate.groups.faling_node or falling_node
surface_deftemplate.groups.falling_node = surface_deftemplate.groups.falling_node or falling_node
surface_deftemplate._mcl_falling_node_alternative = surface_deftemplate._mcl_falling_node_alternative or (falling_node and nodename or nil)
minetest.register_node(surfacename, surface_deftemplate)
@ -496,7 +524,7 @@ minetest.register_craft({
-- ABMs ------------------------------------------------------------------------
minetest.register_abm({
label = "mcl_ocean:Kelp growth",
label = "Kelp growth",
nodenames = { "group:kelp" },
interval = 45,
chance = 12,
@ -504,26 +532,22 @@ minetest.register_abm({
action = grow_kelp,
})
-- NOTE: Uncomment this to use nodetimers
minetest.register_lbm({
label = "Kelp timer registration",
name = "mcl_ocean:kelp_timer_registration",
nodenames = { "group:kelp" },
run_at_every_load = true,
run_at_every_load = false,
action = surface_register_nodetimer,
})
-- TODO: test if nodetimers are more efficient than ABM
-- -- Break kelp not underwater.
-- NOTE: Uncomment this to use ABMs
-- Break kelp not underwater.
-- minetest.register_abm({
-- label = "Kelp drops",
-- nodenames = { "group:kelp" },
-- interval = 0.5,
-- interval = 1.0,
-- chance = 1,
-- catch_up = false,
-- action = function(pos, node)
-- local dig_pos = find_unsubmerged(pos, node)
-- if dig_pos then
-- detach_dig(dig_pos, pos, node, true)
-- end
-- end
-- action = surface_unsubmerged_abm,
-- })