Correct crashes/item duplication with dropping carts, start API documentation

This commit is contained in:
teknomunk 2024-04-10 22:22:17 +00:00
parent 463e2eeafd
commit be664b08ec
3 changed files with 89 additions and 28 deletions

View File

@ -0,0 +1,44 @@
== Cart-Node interactions
As the cart moves thru the environment, it can interact with the surrounding blocks
thru a number of handlers in the block definitions. All these handlers are defined
as:
`function(node_position, cart_luaentity, cart_direction, cart_position)`
Arguments:
`node_position` - position of the node the cart is interacting with
`cart_luaentity` - The luaentity of the cart that is entering this block. Will
be nil for minecarts moving thru unloaded blocks
`cart_direction` - The direction the cart is moving
`cart_position` - The location of the cart
`cart_data` - Information about the cart. This will always be defined.
There are several variants of this handler:
`_mcl_minecarts_on_enter` - The cart enters this block
`_mcl_minecarts_on_enter_below` - The cart enters above this block
`_mcl_minecarts_on_enter_above` - The cart enters below this block
`_mcl_minecarts_on_enter_side` - The cart enters beside this block
Mods can also define global handlers that are called for every node. These
handlers are defined as:
`function(node_position, cart_luaentity, cart_direction, node_definition, cart_data)`
Arguments:
`node_position` - position of the node the cart is interacting with
`cart_luaentity` - The luaentity of the cart that is entering this block. Will
be nil for minecarts moving thru unloaded blocks
`cart_direction` - The direction the cart is moving
`cart_position` - The location of the cart
`cart_data` - Information about the cart. This will always be defined.
`node_definition` - The definition of the node at `node_position`
The available hooks are:
`_mcl_minecarts.on_enter` - The cart enters this block
`_mcl_minecarts.on_enter_below` - The cart enters above this block
`_mcl_minecarts.on_enter_above` - The cart enters below this block
`_mcl_minecarts.on_enter_side` - The cart enters beside this block
Only a single function can be installed in each of these handlers. Before installing,
preserve the existing handler and call it from inside your handler if not `nil`.

View File

@ -249,18 +249,10 @@ function DEFAULT_CART_DEF:on_step(dtime)
mod.update_cart_orientation(self) mod.update_cart_orientation(self)
end end
function DEFAULT_CART_DEF:on_death(killer) local function kill_cart(staticdata)
local staticdata = self._staticdata local pos
minetest.log("action", "cart #"..staticdata.uuid.." was killed") minetest.log("action", "cart #"..staticdata.uuid.." was killed")
detach_driver(self)
-- Detach passenger
if self._passenger then
local mob = self._passenger.object
mob:set_detach()
end
-- Leave nodes -- Leave nodes
if staticdata.attached_at then if staticdata.attached_at then
handle_cart_leave(self, staticdata.attached_at, staticdata.dir ) handle_cart_leave(self, staticdata.attached_at, staticdata.dir )
@ -268,23 +260,42 @@ function DEFAULT_CART_DEF:on_death(killer)
mcl_log("TODO: handle detatched minecart death") mcl_log("TODO: handle detatched minecart death")
end end
-- Handle entity-related items
local le = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
if le then
pos = le.object:get_pos()
detach_driver(le)
-- Detach passenger
if le._passenger then
local mob = le._passenger.object
mob:set_detach()
end
else
pos = mod.get_cart_position(staticdata)
end
-- Drop items
if not staticdata.dropped then
local entity_def = minetest.registered_entities[staticdata.cart_type]
if entity_def then
local drop = entity_def.drop
for d=1, #drop do
minetest.add_item(pos, drop[d])
end
-- Prevent item duplication
staticdata.dropped = true
end
end
-- Remove data -- Remove data
destroy_cart_data(staticdata.uuid) destroy_cart_data(staticdata.uuid)
-- Drop items
local drop = self.drop
if not killer or not minetest.is_creative_enabled(killer:get_player_name()) then
for d=1, #drop do
minetest.add_item(self.object:get_pos(), drop[d])
end
elseif killer and killer:is_player() then
local inv = killer:get_inventory()
for d=1, #drop do
if not inv:contains_item("main", drop[d]) then
inv:add_item("main", drop[d])
end
end
end end
function DEFAULT_CART_DEF:on_death(killer)
kill_cart(self._staticdata)
end end
-- Place a minecart at pointed_thing -- Place a minecart at pointed_thing
@ -558,8 +569,14 @@ minetest.register_globalstep(function(dtime)
local r = 0.6 local r = 0.6
for _, node_pos in pairs({{r, 0}, {0, r}, {-r, 0}, {0, -r}}) do for _, node_pos in pairs({{r, 0}, {0, r}, {-r, 0}, {0, -r}}) do
if minetest.get_node(vector.offset(pos, node_pos[1], 0, node_pos[2])).name == "mcl_core:cactus" then if minetest.get_node(vector.offset(pos, node_pos[1], 0, node_pos[2])).name == "mcl_core:cactus" then
self:on_death() kill_cart(staticdata)
self.object:remove() local le = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
if le then
le:on_death()
le.object:remove()
else
kill_cart(staticdata)
end
return return
end end
end end

View File

@ -62,11 +62,11 @@ local function handle_cart_enter_exit(staticdata, pos, next_dir, event)
-- node-specific hook -- node-specific hook
local hook_name = "_mcl_minecarts_"..event..check[4] local hook_name = "_mcl_minecarts_"..event..check[4]
local hook = node_def[hook_name] local hook = node_def[hook_name]
if hook then hook(check_pos, luaentity, next_dir, pos) end if hook then hook(check_pos, luaentity, next_dir, pos, staticdata) end
-- global minecart hook -- global minecart hook
hook = mcl_minecarts[event..check[4]] hook = mcl_minecarts[event..check[4]]
if hook then hook(check_pos, luaentity, next_dir, node_def) end if hook then hook(check_pos, luaentity, next_dir, pos, staticdata, node_def) end
end end
end end