Merge pull request 'Major changes to item physics' (#181) from Gustavo6046/MineClone5:item-physics into master

Reviewed-on: MineClone5/MineClone5#181
This commit is contained in:
kay27 2022-02-09 11:22:42 +00:00
commit 52712f9133
3 changed files with 88 additions and 11 deletions

View File

@ -27,6 +27,11 @@ local mcl_item_entity = {}
local item_drop_settings = {} --settings table
item_drop_settings.dug_buffer = 0.65 -- the warm up period before a dug item can be collected
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
item_drop_settings.fluid_flow_rate = 1.39 --the speed of a flowing fluid, used when computing push and drag forces of water on items; default is tuned to Minecraft
item_drop_settings.fluid_drag = 1.8 --how much drag water has on items (how quickly an item's motion will settle onto the water's flow speed)
item_drop_settings.ground_drag = 3.0 --how much friction with the ground slows items sliding on it
item_drop_settings.slippery_drag_factor = 0.25 --scales item friction with the ground on slippery floors (e.g. ice)
item_drop_settings.slippery_fluid_drag_factor = 0.4 --scales item drag with waterflow on slippery floors (e.g. ice)
item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect!
item_drop_settings.radius_collect = 0.2 --radius of collection
@ -778,11 +783,35 @@ minetest.register_entity(":__builtin:item", {
-- Just to make sure we don't manipulate the speed for no reason
if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then
-- Minecraft Wiki: Flowing speed is "about 1.39 meters per second"
local f = 1.39
-- Set new item moving speed into the direciton of the liquid
local newv = vector.multiply(vec, f)
local f = item_drop_settings.fluid_flow_rate --1.39
-- Apply the force of the flowing liquid onto the item's velocity
local newv = vector.multiply(vec, f)
self.object:set_acceleration({x = 0, y = 0, z = 0})
self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z})
local oldvel = self.object:get_velocity() -- v is vector, vel is velocity
-- drag
local fluid_drag = item_drop_settings.fluid_drag
local floornn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
local floornode = floornn and minetest.registered_nodes[floornn]
if floornode and minetest.get_item_group(floornode.name, "slippery") then
-- scale fluid drag on slippery floors
fluid_drag = fluid_drag * item_drop_settings.slippery_fluid_drag_factor
end
newv.x = newv.x - (oldvel.x - newv.x) * fluid_drag * dtime
newv.y = newv.y - (oldvel.y - newv.y) * fluid_drag * dtime
newv.z = newv.z - (oldvel.z - newv.z) * fluid_drag * dtime
newv.y = newv.y + -0.22 -- (keep slight downward thrust from previous version of code)
-- NOTE: is there any particular reason we have this, anyway?
-- since fluid drag is now on, we could as well just
-- apply gravity here; drag will slow down the fall
-- realistically
self.object:set_velocity({x = oldvel.x + newv.x * dtime, y = oldvel.y + newv.y * dtime, z = oldvel.z + newv.z * dtime})
self.physical_state = true
self._flowing = true
@ -794,15 +823,17 @@ minetest.register_entity(":__builtin:item", {
elseif self._flowing == true then
-- Disable flowing physics if not on/in flowing liquid
self._flowing = false
enable_physics(self.object, self, true)
--enable_physics(self.object, self, true) -- do not reset velocity upon leaving water!
self.object:set_acceleration({x=0,y=-get_gravity(),z=0}) -- resume applying gravity
return
end
-- If node is not registered or node is walkably solid and resting on nodebox
local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name
local v = self.object:get_velocity()
local node = nn and minetest.registered_nodes[nn]
if not minetest.registered_nodes[nn] or minetest.registered_nodes[nn].walkable and v.y == 0 then
if not node or node.walkable and v.y == 0 then
if self.physical_state then
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
-- Merge with close entities of the same item
@ -815,7 +846,28 @@ minetest.register_entity(":__builtin:item", {
end
end
end
disable_physics(self.object, self)
--disable_physics(self.object, self)
-- apply ground drag
local oldvel = self.object:get_velocity()
-- ignore momentum if it's tiny
if math.abs(oldvel.x) < 0.05 and math.abs(oldvel.z) < 0.05 then
disable_physics(self.object, self)
return
end
local ground_drag = item_drop_settings.ground_drag
if node and minetest.get_item_group(node.name, "slippery") ~= 0 then
ground_drag = ground_drag * item_drop_settings.slippery_drag_factor
end
local newvel = {
x = oldvel.x - oldvel.x * ground_drag * dtime,
y = 0,
z = oldvel.z - oldvel.z * ground_drag * dtime
}
self.object:set_velocity(newvel)
end
else
if self._magnet_active == false then

View File

@ -260,9 +260,22 @@ local dispenserdef = {
end
else
-- Drop item otherwise
minetest.add_item(droppos, dropitem)
stack:take_item()
inv:set_stack("main", stack_id, stack)
-- Drop item normally
local dropitemobj = minetest.add_item(droppos, dropitem)
stack:take_item()
inv:set_stack("main", stack_id, stack)
-- Set item velocity (overrides the default random drop direction)
local shoot_force = 1.3
local newv = minetest.facedir_to_dir(node.param2)
newv = {
x = newv.x * shoot_force,
y = newv.y * shoot_force,
z = newv.z * shoot_force
}
dropitemobj:set_velocity(newv)
end
end

View File

@ -134,9 +134,21 @@ local dropperdef = {
-- No container?
if not dropped and not dropnodedef.groups.container then
-- Drop item normally
minetest.add_item(droppos, dropitem)
local dropitemobj = minetest.add_item(droppos, dropitem)
stack:take_item()
inv:set_stack("main", stack_id, stack)
-- Set item velocity (overrides the default random drop direction)
local shoot_force = 1.3
local newv = minetest.facedir_to_dir(node.param2)
newv = {
x = -newv.x * shoot_force,
y = -newv.y * shoot_force,
z = -newv.z * shoot_force
}
dropitemobj:set_velocity(newv)
end
end
end,