2020-10-08 20:29:39 +02:00
|
|
|
-- Use the movement gravity for the downwards acceleration.
|
|
|
|
-- The setting may change in-game but for simplicity we don't support this.
|
|
|
|
local movement_gravity = tonumber(core.settings:get("movement_gravity")) or 9.81
|
2014-08-31 14:44:42 +02:00
|
|
|
|
2020-10-10 17:46:06 +02:00
|
|
|
local function is_flowing_liquid(nodename)
|
|
|
|
local def = minetest.registered_nodes[nodename]
|
|
|
|
return def and def.liquidtype == "flowing"
|
|
|
|
end
|
|
|
|
|
2020-10-10 18:07:58 +02:00
|
|
|
-- get_flow_raw determines the horizontal flow vector for a flowing liquid node,
|
|
|
|
-- or returns nothing if the flow is zero
|
2020-10-08 19:35:12 +02:00
|
|
|
local neighbour_offsets = {
|
|
|
|
{x=-1, y=0, z=0},
|
|
|
|
{x=1, y=0, z=0},
|
|
|
|
{x=0, y=0, z=-1},
|
|
|
|
{x=0, y=0, z=1}
|
|
|
|
}
|
2020-10-10 17:46:06 +02:00
|
|
|
local function get_flow_raw(pos)
|
|
|
|
-- FIXME: Do we need to treat nodes with special liquid_range differently?
|
2020-10-08 20:29:39 +02:00
|
|
|
local param2 = minetest.get_node(pos).param2
|
2020-10-10 17:46:06 +02:00
|
|
|
if param2 == 15 then
|
|
|
|
-- The liquid has full height and flows downwards
|
2020-10-08 20:29:39 +02:00
|
|
|
return
|
2020-10-08 19:35:12 +02:00
|
|
|
end
|
2020-10-10 18:07:58 +02:00
|
|
|
local flow = {x = 0, y = 0, z = 0}
|
|
|
|
local height = param2 % 8
|
2020-10-08 19:35:12 +02:00
|
|
|
for n = 1, 4 do
|
2020-10-10 18:07:58 +02:00
|
|
|
local node = minetest.get_node(vector.add(pos, neighbour_offsets[n]))
|
|
|
|
local def = minetest.registered_nodes[node.name]
|
|
|
|
local height_other
|
|
|
|
if not def or def.walkable then
|
|
|
|
-- A solid node, so no flow happens
|
|
|
|
height_other = height
|
|
|
|
elseif def.liquidtype == "source" then
|
|
|
|
-- Assume that relevant liquid comes from this source
|
|
|
|
height_other = 8
|
|
|
|
elseif def.liquidtype == "flowing" then
|
|
|
|
-- This neighbour is also a flowing liquid
|
|
|
|
height_other = node.param2 % 8
|
|
|
|
else
|
|
|
|
-- There is a free space, e.g. air or a plant
|
|
|
|
height_other = 0
|
2012-09-25 16:29:37 +02:00
|
|
|
end
|
2020-10-10 18:07:58 +02:00
|
|
|
local fl = vector.multiply(neighbour_offsets[n], height - height_other)
|
|
|
|
flow = vector.add(flow, fl)
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
2020-10-10 18:07:58 +02:00
|
|
|
if vector.equals(flow, {x = 0, y = 0, z = 0}) then
|
|
|
|
return
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
2020-10-10 18:07:58 +02:00
|
|
|
return vector.normalize(flow)
|
2020-10-08 20:29:39 +02:00
|
|
|
end
|
|
|
|
|
2020-10-10 17:46:06 +02:00
|
|
|
-- get_flow caches the results from get_flow_raw for 10 s
|
|
|
|
local flow_cache = {}
|
|
|
|
setmetatable(flow_cache, {__mode = "kv"})
|
|
|
|
local function get_flow(pos)
|
2020-10-08 20:29:39 +02:00
|
|
|
local vi = minetest.hash_node_position(pos)
|
|
|
|
local t = minetest.get_us_time()
|
2020-10-10 17:46:06 +02:00
|
|
|
if flow_cache[vi]
|
|
|
|
and t - flow_cache[vi][1] < 10 * 1000000 then
|
|
|
|
return flow_cache[vi][2]
|
2020-10-08 20:29:39 +02:00
|
|
|
end
|
2020-10-10 17:46:06 +02:00
|
|
|
local flow = get_flow_raw(pos)
|
|
|
|
flow_cache[vi] = {t, flow}
|
|
|
|
return flow
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
2012-09-25 16:29:37 +02:00
|
|
|
|
2014-08-31 14:12:32 +02:00
|
|
|
local item_entity = minetest.registered_entities["__builtin:item"]
|
2020-10-08 20:29:39 +02:00
|
|
|
local old_on_step = item_entity.on_step
|
2012-09-25 16:29:37 +02:00
|
|
|
|
2016-02-18 18:45:59 +01:00
|
|
|
item_entity.makes_footstep_sound = true
|
2020-10-08 20:29:39 +02:00
|
|
|
-- The "bt_" prefix shows that the value comes from builtin_item
|
2016-02-21 12:31:33 +01:00
|
|
|
item_entity.bt_timer = 0
|
2020-05-09 17:42:51 +02:00
|
|
|
item_entity.on_step = function(self, dtime, ...)
|
2020-10-08 20:29:39 +02:00
|
|
|
-- Remember the velocity before an original on_step can change it
|
|
|
|
local vel_desired
|
|
|
|
if self.bt_reset_velocity then
|
|
|
|
vel_desired = self.object:get_velocity()
|
|
|
|
end
|
2015-06-05 11:30:34 +02:00
|
|
|
|
2020-10-08 20:29:39 +02:00
|
|
|
old_on_step(self, dtime, ...)
|
2020-10-08 19:35:12 +02:00
|
|
|
|
2020-10-08 20:29:39 +02:00
|
|
|
-- Ignore the item if it should not interact with physics
|
|
|
|
if not self.physical_state then
|
|
|
|
return
|
2016-05-26 12:17:00 +02:00
|
|
|
end
|
2020-10-08 19:35:12 +02:00
|
|
|
|
2020-10-08 20:29:39 +02:00
|
|
|
-- Reset the velocity if needed
|
|
|
|
if vel_desired
|
|
|
|
and not vector.equals(self.object:get_velocity(), vel_desired) then
|
|
|
|
self.object:set_velocity(vel_desired)
|
2016-05-26 12:17:00 +02:00
|
|
|
end
|
|
|
|
|
2020-10-08 20:29:39 +02:00
|
|
|
-- For performance reasons, skip the remaining code in frequent steps
|
2020-10-08 19:35:12 +02:00
|
|
|
self.bt_timer = self.bt_timer + dtime
|
2020-10-08 20:29:39 +02:00
|
|
|
if self.bt_timer < 0.1 then
|
2016-02-21 12:31:33 +01:00
|
|
|
return
|
|
|
|
end
|
|
|
|
self.bt_timer = 0
|
|
|
|
|
2020-08-01 21:12:24 +02:00
|
|
|
local p = self.object:get_pos()
|
2016-05-26 12:17:00 +02:00
|
|
|
local pos = vector.round(p)
|
2020-10-08 20:29:39 +02:00
|
|
|
local nodename = minetest.get_node(pos).name
|
2015-06-05 11:30:34 +02:00
|
|
|
|
2020-10-08 20:29:39 +02:00
|
|
|
if self.bt_reset_velocity then
|
|
|
|
-- Set the item acceleration to its default (changed again below)
|
|
|
|
self.object:set_acceleration({x=0, y=-movement_gravity, z=0})
|
|
|
|
self.bt_reset_velocity = nil
|
2016-05-26 12:17:00 +02:00
|
|
|
end
|
2020-10-08 20:29:39 +02:00
|
|
|
local def = minetest.registered_nodes[nodename]
|
|
|
|
if not def or not def.liquidtype or def.liquidtype ~= "flowing" then
|
2020-10-08 19:35:12 +02:00
|
|
|
return
|
|
|
|
end
|
2020-10-10 17:46:06 +02:00
|
|
|
local flow = get_flow(pos)
|
|
|
|
if not flow then
|
2020-10-08 19:35:12 +02:00
|
|
|
return
|
|
|
|
end
|
2020-10-08 20:29:39 +02:00
|
|
|
local vel_current = vel_desired or self.object:get_velocity()
|
2020-10-10 17:46:06 +02:00
|
|
|
local acc
|
|
|
|
if vector.dot(vel_current, flow) < 1.0 then
|
|
|
|
acc = vector.multiply(flow, 2.0)
|
|
|
|
else
|
|
|
|
-- The item is already accelerated by the fluids
|
|
|
|
acc = {x = 0, y = 0, z = 0}
|
2020-10-08 20:29:39 +02:00
|
|
|
end
|
|
|
|
acc.y = -movement_gravity
|
|
|
|
self.object:set_acceleration(acc)
|
|
|
|
self.bt_reset_velocity = true
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
minetest.register_entity(":__builtin:item", item_entity)
|