summaryrefslogtreecommitdiff
path: root/builtin/game
diff options
context:
space:
mode:
authorsfan5 <sfan5@live.de>2020-04-14 16:55:16 +0200
committersfan5 <sfan5@live.de>2020-04-27 20:45:46 +0200
commitb9377f26a198d0383b82c76cf6904bc1797e8187 (patch)
tree0be40b4d2708bceb9a01751f07e997f874bba9e2 /builtin/game
parent3475759d1adbd4a64c6250fd87981f783e64f69c (diff)
downloadminetest-b9377f26a198d0383b82c76cf6904bc1797e8187.tar.gz
minetest-b9377f26a198d0383b82c76cf6904bc1797e8187.tar.bz2
minetest-b9377f26a198d0383b82c76cf6904bc1797e8187.zip
Rewrite builtin item entity to use collision info
fixes #8967
Diffstat (limited to 'builtin/game')
-rw-r--r--builtin/game/item_entity.lua104
1 files changed, 56 insertions, 48 deletions
diff --git a/builtin/game/item_entity.lua b/builtin/game/item_entity.lua
index 968daac97..a85eba977 100644
--- a/builtin/game/item_entity.lua
+++ b/builtin/game/item_entity.lua
@@ -34,7 +34,6 @@ core.register_entity(":__builtin:item", {
itemstring = "",
moving_state = true,
- slippery_state = false,
physical_state = true,
-- Item expiry
age = 0,
@@ -157,7 +156,7 @@ core.register_entity(":__builtin:item", {
end
end,
- on_step = function(self, dtime)
+ on_step = function(self, dtime, moveresult)
self.age = self.age + dtime
if time_to_live > 0 and self.age > time_to_live then
self.itemstring = ""
@@ -178,6 +177,36 @@ core.register_entity(":__builtin:item", {
return
end
+ if self.force_out then
+ -- This code runs after the entity got a push from the is_stuck code.
+ -- It makes sure the entity is entirely outside the solid node
+ local c = self.object:get_properties().collisionbox
+ local s = self.force_out_start
+ local f = self.force_out
+ local ok = (f.x > 0 and pos.x + c[1] > s.x + 0.5) or
+ (f.y > 0 and pos.y + c[2] > s.y + 0.5) or
+ (f.z > 0 and pos.z + c[3] > s.z + 0.5) or
+ (f.x < 0 and pos.x + c[4] < s.x - 0.5) or
+ (f.z < 0 and pos.z + c[6] < s.z - 0.5)
+ if ok then
+ -- Item was successfully forced out
+ self.force_out = nil
+ self:enable_physics()
+ return
+ end
+ end
+
+ if not self.physical_state then
+ return -- Don't do anything
+ end
+
+ assert(moveresult)
+ if not moveresult.collides then
+ -- future TODO: items should probably decelerate in air
+ return
+ end
+
+ -- Push item out when stuck inside solid node
local is_stuck = false
local snode = core.get_node_or_nil(pos)
if snode then
@@ -187,7 +216,6 @@ core.register_entity(":__builtin:item", {
and (sdef.node_box == nil or sdef.node_box.type == "regular")
end
- -- Push item out when stuck inside solid node
if is_stuck then
local shootdir
local order = {
@@ -223,69 +251,49 @@ core.register_entity(":__builtin:item", {
self.force_out_start = vector.round(pos)
return
end
- elseif self.force_out then
- -- This code runs after the entity got a push from the above code.
- -- It makes sure the entity is entirely outside the solid node
- local c = self.object:get_properties().collisionbox
- local s = self.force_out_start
- local f = self.force_out
- local ok = (f.x > 0 and pos.x + c[1] > s.x + 0.5) or
- (f.y > 0 and pos.y + c[2] > s.y + 0.5) or
- (f.z > 0 and pos.z + c[3] > s.z + 0.5) or
- (f.x < 0 and pos.x + c[4] < s.x - 0.5) or
- (f.z < 0 and pos.z + c[6] < s.z - 0.5)
- if ok then
- -- Item was successfully forced out
- self.force_out = nil
- self:enable_physics()
- end
end
- if not self.physical_state then
- return -- Don't do anything
+ node = nil -- ground node we're colliding with
+ if moveresult.touching_ground then
+ for _, info in ipairs(moveresult.collisions) do
+ if info.axis == "y" then
+ node = core.get_node(info.node_pos)
+ break
+ end
+ end
end
-- Slide on slippery nodes
- local vel = self.object:get_velocity()
local def = node and core.registered_nodes[node.name]
- local is_moving = (def and not def.walkable) or
- vel.x ~= 0 or vel.y ~= 0 or vel.z ~= 0
- local is_slippery = false
+ local keep_movement = false
- if def and def.walkable then
+ if def then
local slippery = core.get_item_group(node.name, "slippery")
- is_slippery = slippery ~= 0
- if is_slippery and (math.abs(vel.x) > 0.2 or math.abs(vel.z) > 0.2) then
+ local vel = self.object:get_velocity()
+ if slippery ~= 0 and (math.abs(vel.x) > 0.1 or math.abs(vel.z) > 0.1) then
-- Horizontal deceleration
- local slip_factor = 4.0 / (slippery + 4)
- self.object:set_acceleration({
- x = -vel.x * slip_factor,
+ local factor = math.min(4 / (slippery + 4) * dtime, 1)
+ self.object:set_velocity({
+ x = vel.x * (1 - factor),
y = 0,
- z = -vel.z * slip_factor
+ z = vel.z * (1 - factor)
})
- elseif vel.y == 0 then
- is_moving = false
+ keep_movement = true
end
end
- if self.moving_state == is_moving and
- self.slippery_state == is_slippery then
- -- Do not update anything until the moving state changes
- return
+ if not keep_movement then
+ self.object:set_velocity({x=0, y=0, z=0})
end
- self.moving_state = is_moving
- self.slippery_state = is_slippery
-
- if is_moving then
- self.object:set_acceleration({x = 0, y = -gravity, z = 0})
- else
- self.object:set_acceleration({x = 0, y = 0, z = 0})
- self.object:set_velocity({x = 0, y = 0, z = 0})
+ if self.moving_state == keep_movement then
+ -- Do not update anything until the moving state changes
+ return
end
+ self.moving_state = keep_movement
- --Only collect items if not moving
- if is_moving then
+ -- Only collect items if not moving
+ if self.moving_state then
return
end
-- Collect the items around to merge with