More accurate entity settling

Under heavy lag conditions, physical entities may
land on the ground at any point during a time
step, but if they have a lot of horizontal velocity
then they may "slide" along the ground, and if we
only check for settling based on their pos at step
times, they may have already slid some distance
dependent on luck and the actual amount of
server lag.  This means that under heavy lag
conditions, items may spread out inconsistently
from their landing positions and make a messy
pile.

Using the MT 5.3+ moveresult parameter of
entity steps, we can easily find out when the
initial ground contact occured, and use that as
the settling position, which should be more
consistent under lag conditions.

This has the effect of making entities more
consistently "sticky" so they always tend to
stick at the point of initial contact and rarely
slide or glance along the ground, unless they
hit an edge/corner.
This commit is contained in:
Aaron Suen 2021-12-12 10:01:24 -05:00
parent 67e4c5d476
commit f3bdf91dc6
3 changed files with 17 additions and 6 deletions

View File

@ -196,9 +196,20 @@ function nodecore.entity_settle_recurse(pos)
entity_settle_recursing = nil
end
local function groundpos(moveresult)
if not (moveresult and moveresult.touching_ground) then return end
local collisions = moveresult.collisions
if not collisions then return end
local first = collisions[1]
if not (first and first.type == "node") then return end
local pos = first.nodepos
if not pos then return end
return {x = pos.x, y = pos.y + 0.55, z = pos.z}
end
function nodecore.entity_settle_check(on_settle, isnode)
return function(self)
local pos = self.object:get_pos()
return function(self, _, moveresult)
local pos = groundpos(moveresult) or self.object:get_pos()
if not pos then return end
if pos.y < nodecore.map_limit_min then
pos.y = nodecore.map_limit_min

View File

@ -115,7 +115,7 @@ minetest.register_entity(":__builtin:falling_node", {
on_step = function(self, ...)
if not self.node then return self.object:remove() end
nodecore.entity_update_maxy(self)
if self:settle_check() then return end
if self:settle_check(...) then return end
for _, func in ipairs(nodecore.registered_falling_node_steps) do
if func(self, ...) == true then return end

View File

@ -85,13 +85,13 @@ minetest.register_entity(":__builtin:item", {
end
end),
on_step = function(self, dtime, ...)
on_step = function(self, ...)
if not self.itemstring then return self.object:remove() end
nodecore.entity_update_maxy(self)
if self:settle_check() then return end
if self:settle_check(...) then return end
for _, func in ipairs(nodecore.registered_item_entity_steps) do
if func(self, dtime, ...) == true then return end
if func(self, ...) == true then return end
end
end,
})