2020-10-08 19:35:12 +02:00
|
|
|
-- Use the movement gravity for the downwards direction. Get the setting rarely
|
|
|
|
local cached_gravity
|
|
|
|
local function get_gravity()
|
|
|
|
if cached_gravity then
|
|
|
|
return cached_gravity
|
|
|
|
end
|
|
|
|
cached_gravity = tonumber(core.settings:get("movement_gravity")) or 9.81
|
|
|
|
core.after(50, function()
|
|
|
|
cached_gravity = nil
|
|
|
|
end)
|
|
|
|
return cached_gravity
|
2015-06-05 11:30:34 +02:00
|
|
|
end
|
2014-08-31 14:44:42 +02:00
|
|
|
|
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}
|
|
|
|
}
|
|
|
|
local neighbours_cache = {}
|
|
|
|
setmetatable(neighbours_cache, {__mode = "kv"})
|
|
|
|
local function get_neighbour_nodes(pos)
|
|
|
|
-- Use previously found neighbours if they are not too old
|
|
|
|
local vi = minetest.hash_node_position(pos)
|
|
|
|
local t = minetest.get_us_time()
|
|
|
|
if neighbours_cache[vi]
|
|
|
|
and t - neighbours_cache[vi][1] < 10 * 1000000 then
|
|
|
|
return neighbours_cache[vi][2]
|
|
|
|
end
|
|
|
|
local neighbours = {}
|
|
|
|
for n = 1, 4 do
|
|
|
|
local p = vector.add(pos, neighbour_offsets[n])
|
|
|
|
neighbours[n] = p
|
|
|
|
neighbours[n + 4] = minetest.get_node(p)
|
|
|
|
end
|
|
|
|
neighbours_cache[vi] = {t, neighbours}
|
|
|
|
return neighbours
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
2012-09-25 16:29:37 +02:00
|
|
|
|
2020-10-08 19:35:12 +02:00
|
|
|
-- This function determines position to which the water flows
|
|
|
|
local function get_flow_target(pos)
|
|
|
|
local neighbours = get_neighbour_nodes(pos)
|
2014-08-31 14:12:32 +02:00
|
|
|
local param2 = minetest.get_node(pos).param2
|
|
|
|
if param2 > 7 then
|
|
|
|
return
|
|
|
|
end
|
2020-10-08 19:35:12 +02:00
|
|
|
for i = 1, 4 do
|
|
|
|
-- If a neighbour has a lower height, flow to it
|
|
|
|
local node = neighbours[i + 4]
|
|
|
|
if node.name == "default:water_flowing"
|
|
|
|
and node.param2 < param2 then
|
|
|
|
return neighbours[i]
|
2012-09-25 16:29:37 +02:00
|
|
|
end
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
2020-10-08 19:35:12 +02:00
|
|
|
for i = 1, 4 do
|
|
|
|
-- TODO
|
|
|
|
local node = neighbours[i + 4]
|
|
|
|
if node.name == "default:water_flowing"
|
|
|
|
and node.param2 >= 11 then
|
|
|
|
return neighbours[i]
|
2012-09-25 16:29:37 +02:00
|
|
|
end
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
2020-10-08 19:35:12 +02:00
|
|
|
for i = 1, 4 do
|
|
|
|
-- TODO
|
|
|
|
local node = neighbours[i + 4]
|
|
|
|
if node.name ~= "default:water_flowing" then
|
|
|
|
local def = minetest.registered_nodes[node.name]
|
|
|
|
if def and not def.walkable then
|
|
|
|
return neighbours[i]
|
|
|
|
end
|
2012-09-25 16:29:37 +02:00
|
|
|
end
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
|
|
|
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"]
|
|
|
|
local old_on_step = item_entity.on_step or function()end
|
2012-09-25 16:29:37 +02:00
|
|
|
|
2016-02-18 18:45:59 +01:00
|
|
|
item_entity.makes_footstep_sound = true
|
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, ...)
|
|
|
|
old_on_step(self, dtime, ...)
|
2015-06-05 11:30:34 +02:00
|
|
|
|
2020-10-08 19:35:12 +02:00
|
|
|
--~ if not self.physical_state then
|
|
|
|
--~ return
|
|
|
|
--~ end
|
|
|
|
|
|
|
|
-- Force-adjust an acceleration and/or velocity if needed
|
2016-05-26 12:17:00 +02:00
|
|
|
if self.bt_acc
|
2020-08-01 21:12:24 +02:00
|
|
|
and not vector.equals(self.object:get_acceleration(), self.bt_acc) then
|
2018-10-03 17:37:20 +02:00
|
|
|
self.object:set_acceleration(self.bt_acc)
|
2016-05-26 12:17:00 +02:00
|
|
|
end
|
|
|
|
if self.bt_vel
|
2020-08-01 21:12:24 +02:00
|
|
|
and not vector.equals(self.object:get_velocity(), self.bt_vel) then
|
2018-10-03 17:37:20 +02:00
|
|
|
self.object:set_velocity(self.bt_vel)
|
2016-05-26 12:17:00 +02:00
|
|
|
end
|
2020-10-08 19:35:12 +02:00
|
|
|
|
|
|
|
-- TODO: was ist pyhsical state?
|
2016-05-26 12:17:00 +02:00
|
|
|
if self.bt_phys ~= nil
|
|
|
|
and self.physical_state ~= self.bt_phys then
|
|
|
|
self.physical_state = self.bt_phys
|
|
|
|
self.object:set_properties({
|
|
|
|
physical = self.bt_phys
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
2020-10-08 19:35:12 +02:00
|
|
|
-- For performance reasons, skip the remaining code except every second
|
|
|
|
self.bt_timer = self.bt_timer + dtime
|
2016-02-21 12:31:33 +01:00
|
|
|
if self.bt_timer < 1 then
|
|
|
|
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)
|
2015-06-05 11:30:34 +02:00
|
|
|
|
2016-05-26 12:17:00 +02:00
|
|
|
local name = minetest.get_node(pos).name
|
2014-08-31 14:12:32 +02:00
|
|
|
if name == "default:lava_flowing"
|
2020-10-08 19:35:12 +02:00
|
|
|
or name == "default:lava_source" then
|
|
|
|
-- TODO: more generic burn cases
|
2014-08-31 14:12:32 +02:00
|
|
|
minetest.sound_play("builtin_item_lava", {pos=p})
|
2015-04-09 22:31:21 +02:00
|
|
|
minetest.add_particlespawner({
|
|
|
|
amount = 3,
|
|
|
|
time = 0.1,
|
|
|
|
minpos = {x=p.x, y=p.y, z=p.z},
|
|
|
|
maxpos = {x=p.x, y=p.y+0.2, z=p.z},
|
|
|
|
minacc = {x=-0.5,y=5,z=-0.5},
|
|
|
|
maxacc = {x=0.5,y=5,z=0.5},
|
|
|
|
minexptime = 0.1,
|
|
|
|
minsize = 2,
|
|
|
|
maxsize = 4,
|
|
|
|
texture = "smoke_puff.png"
|
|
|
|
})
|
2015-04-09 21:55:14 +02:00
|
|
|
minetest.add_particlespawner ({
|
|
|
|
amount = 1, time = 0.4,
|
|
|
|
minpos = {x = p.x, y= p.y + 0.25, z= p.z},
|
|
|
|
maxpos = {x = p.x, y= p.y + 0.5, z= p.z},
|
|
|
|
minexptime = 0.2, maxexptime = 0.4,
|
|
|
|
minsize = 4, maxsize = 6,
|
|
|
|
collisiondetection = false,
|
|
|
|
vertical = false,
|
|
|
|
texture = "fire_basic_flame.png",
|
|
|
|
})
|
2014-08-31 14:12:32 +02:00
|
|
|
self.object:remove()
|
|
|
|
return
|
|
|
|
end
|
2012-09-25 16:29:37 +02:00
|
|
|
|
2020-10-08 19:35:12 +02:00
|
|
|
local def = minetest.registered_nodes[name]
|
|
|
|
if not def then
|
2016-05-26 12:17:00 +02:00
|
|
|
return
|
|
|
|
end
|
2020-10-08 19:35:12 +02:00
|
|
|
-- Adjust the acceleration in liquid nodes
|
|
|
|
self.bt_acc = nil
|
|
|
|
self.bt_vel = nil
|
|
|
|
if def.liquidtype then
|
|
|
|
-- Set the strongest acceleration when we are in the middle of the node
|
|
|
|
local acc_strength = 1.0 - ((p.y - 0.5) % 1.0) * 0.9
|
|
|
|
local acc = {x = 0, y = -acc_strength * get_gravity(), z = 0}
|
2018-10-03 17:37:20 +02:00
|
|
|
self.object:set_acceleration(acc)
|
2016-05-26 12:17:00 +02:00
|
|
|
self.bt_acc = acc
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
2020-10-08 19:35:12 +02:00
|
|
|
if def.liquidtype ~= "flowing" then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local vec = get_flow_target(pos)
|
|
|
|
if not vec then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local v = vector.add(
|
|
|
|
self.object:get_velocity(),
|
|
|
|
vector.multiply(vector.subtract(vec, pos),.5)
|
|
|
|
)
|
|
|
|
self.bt_vel = v
|
|
|
|
self.object:set_velocity(v)
|
|
|
|
self.physical_state = true
|
|
|
|
self.bt_phys = true
|
|
|
|
self.object:set_properties({
|
|
|
|
physical = true
|
|
|
|
})
|
2014-08-31 14:12:32 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
minetest.register_entity(":__builtin:item", item_entity)
|