Guard against dummy objects in 5.3+
Some time in the 5.3 dev stream (docs updated at 217f3a42), object refs started being invalidated immediately on calling obj:remove(), such that obj:get_pos() starts to return nil instead of the object's last known position. This can cause some crashes in NodeCore, where we assume that our object is still valid (or usable as if it were still valid) even though we're looping through handlers and any one of them may have remove()d the object before other handlers get a chance to fire. Instead, just watch for unexpected nil returns from functions we expect would never return nil (e.g. get_pos or get_properties) and return if we hit one. We can assume all other calls will be non-nil after that one, as long as we stay in the same function flow.
This commit is contained in:
parent
1d0f9aa81f
commit
9c9eb4b85a
@ -116,15 +116,21 @@ nodecore.register_item_entity_step(function(self, dtime)
|
||||
local t = (self.aismtimer or 0) + dtime
|
||||
while t >= 1 do
|
||||
t = t - 1
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local setstack
|
||||
checkstack(ItemStack(self.itemstring), {
|
||||
pos = self.object:get_pos(),
|
||||
pos = pos,
|
||||
obj = self.object,
|
||||
ent = self,
|
||||
set = function(s)
|
||||
if s:is_empty() then return self.object:remove() end
|
||||
self.itemstring = s:to_string()
|
||||
end
|
||||
set = function(s) setstack = s end
|
||||
})
|
||||
if setstack then
|
||||
if setstack:is_empty() then
|
||||
return self.object:remove()
|
||||
end
|
||||
self.itemstring = setstack:to_string()
|
||||
end
|
||||
end
|
||||
self.aismtimer = t
|
||||
end)
|
||||
|
@ -73,6 +73,7 @@ nodecore.register_limited_abm({
|
||||
})
|
||||
|
||||
local function dynamic_light_add(pos, level, ttl)
|
||||
if not pos then return end
|
||||
local name = minetest.get_node(pos).name
|
||||
if not canreplace[name] then return end
|
||||
if level < 1 then return end
|
||||
|
@ -96,6 +96,7 @@ end
|
||||
function nodecore.entity_settle_check(on_settle, isnode)
|
||||
return function(self)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
if pos.y < nodecore.map_limit_min then
|
||||
pos.y = nodecore.map_limit_min
|
||||
self.object:set_pos(pos)
|
||||
|
@ -8,6 +8,7 @@ local math_floor, math_random
|
||||
local cache = {}
|
||||
|
||||
function nodecore.item_ent_merge(pos)
|
||||
if not pos then return end
|
||||
pos = vector.round(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
|
||||
|
@ -21,6 +21,7 @@ end
|
||||
|
||||
function nodecore.ent_prop_set(obj, def)
|
||||
local old = obj:get_properties()
|
||||
if not old then return end
|
||||
if type(def) == "function" then
|
||||
def = def(old, obj)
|
||||
end
|
||||
|
@ -20,16 +20,17 @@ minetest.register_entity(modname .. ":stackent", {
|
||||
initial_properties = nodecore.stackentprops(),
|
||||
is_stack = true,
|
||||
itemcheck = function(self)
|
||||
local pos = self.object:get_pos()
|
||||
local obj = self.object
|
||||
local pos = obj:get_pos()
|
||||
if not pos then return end
|
||||
local stack = nodecore.stack_get(pos)
|
||||
if not stack or stack:is_empty() then return self.object:remove() end
|
||||
if not stack or stack:is_empty() then return obj:remove() end
|
||||
|
||||
local rp = vector.round(pos)
|
||||
local props, scale, yaw = nodecore.stackentprops(stack,
|
||||
rp.x * 3 + rp.y * 5 + rp.z * 7)
|
||||
rp.y = rp.y + scale - 31/64
|
||||
|
||||
local obj = self.object
|
||||
nodecore.ent_prop_set(obj, props)
|
||||
if obj:get_yaw() ~= yaw then
|
||||
obj:set_yaw(yaw)
|
||||
|
@ -10,7 +10,9 @@ nodecore.register_falling_node_on_setnode(function(self, node, meta)
|
||||
and meta and meta.inventory and meta.inventory.solo then
|
||||
local stack = ItemStack(meta.inventory.solo[1] or "")
|
||||
if not stack:is_empty() then
|
||||
local ent = minetest.add_item(self.object:get_pos(), stack)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
local ent = minetest.add_item(pos, stack)
|
||||
if ent then ent:set_velocity(self.object:get_velocity()) end
|
||||
self.object:remove()
|
||||
return true
|
||||
|
@ -19,6 +19,7 @@ local function maketick(mult, getname, oldtick)
|
||||
end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
pos.y = pos.y - 1
|
||||
local vel = self.object:get_velocity()
|
||||
local v = vel and -vel.y or 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user