Move on_step code to functions to help see profiling impact
parent
59f4a62fd6
commit
53923dd5fa
|
@ -403,7 +403,174 @@ local function cxcz(o, cw, one, zero)
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function nodes_destroy_items (self, moveresult, def, nn)
|
||||||
|
local lg = minetest.get_item_group(nn, "lava")
|
||||||
|
local fg = minetest.get_item_group(nn, "fire")
|
||||||
|
local dg = minetest.get_item_group(nn, "destroys_items")
|
||||||
|
|
||||||
|
if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then
|
||||||
|
--Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed.
|
||||||
|
if self.age > 2 and minetest.get_item_group(self.itemstring, "fire_immune") == 0 then
|
||||||
|
if dg ~= 2 then
|
||||||
|
minetest.sound_play("builtin_item_lava", { pos = self.object:get_pos(), gain = 0.5 })
|
||||||
|
end
|
||||||
|
self._removed = true
|
||||||
|
self.object:remove()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Destroy item when it collides with a cactus
|
||||||
|
if moveresult and moveresult.collides then
|
||||||
|
for _, collision in pairs(moveresult.collisions) do
|
||||||
|
local pos = collision.node_pos
|
||||||
|
if collision.type == "node" and minetest.get_node(pos).name == "mcl_core:cactus" then
|
||||||
|
-- TODO We need to play a sound when it gets destroyed
|
||||||
|
self._removed = true
|
||||||
|
self.object:remove()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function push_out_item_stuck_in_solid(self, dtime, p, def, is_in_water)
|
||||||
|
if not is_in_water and def and def.walkable and def.groups and def.groups.opaque == 1 then
|
||||||
|
local shootdir
|
||||||
|
local cx = (p.x % 1) - 0.5
|
||||||
|
local cz = (p.z % 1) - 0.5
|
||||||
|
local order = {}
|
||||||
|
|
||||||
|
-- First prepare the order in which the 4 sides are to be checked.
|
||||||
|
-- 1st: closest
|
||||||
|
-- 2nd: other direction
|
||||||
|
-- 3rd and 4th: other axis
|
||||||
|
if math.abs(cx) < math.abs(cz) then
|
||||||
|
order = cxcz(order, cx, "x", "z")
|
||||||
|
order = cxcz(order, cz, "z", "x")
|
||||||
|
else
|
||||||
|
order = cxcz(order, cz, "z", "x")
|
||||||
|
order = cxcz(order, cx, "x", "z")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check which one of the 4 sides is free
|
||||||
|
for o = 1, #order do
|
||||||
|
local nn = minetest.get_node(vector.add(p, order[o])).name
|
||||||
|
local def = minetest.registered_nodes[nn]
|
||||||
|
if def and def.walkable == false and nn ~= "ignore" then
|
||||||
|
shootdir = order[o]
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- If none of the 4 sides is free, shoot upwards
|
||||||
|
if shootdir == nil then
|
||||||
|
shootdir = vector.new(0, 1, 0)
|
||||||
|
local nn = minetest.get_node(vector.add(p, shootdir)).name
|
||||||
|
if nn == "ignore" then
|
||||||
|
-- Do not push into ignore
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set new item moving speed accordingly
|
||||||
|
local newv = vector.multiply(shootdir, 3)
|
||||||
|
self.object:set_acceleration(vector.zero())
|
||||||
|
self.object:set_velocity(newv)
|
||||||
|
disable_physics(self.object, self, false, false)
|
||||||
|
|
||||||
|
|
||||||
|
if shootdir.y == 0 then
|
||||||
|
self._force = newv
|
||||||
|
p.x = math.floor(p.x)
|
||||||
|
p.y = math.floor(p.y)
|
||||||
|
p.z = math.floor(p.z)
|
||||||
|
self._forcestart = p
|
||||||
|
self._forcetimer = 1
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This code is run after the entity got a push from above “push away” code.
|
||||||
|
-- It is responsible for making sure the entity is entirely outside the solid node
|
||||||
|
-- (with its full collision box), not just its center.
|
||||||
|
if self._forcetimer > 0 then
|
||||||
|
local cbox = self.object:get_properties().collisionbox
|
||||||
|
local ok = false
|
||||||
|
if self._force.x > 0 and (p.x > (self._forcestart.x + 0.5 + (cbox[4] - cbox[1]) / 2)) then ok = true
|
||||||
|
elseif self._force.x < 0 and (p.x < (self._forcestart.x + 0.5 - (cbox[4] - cbox[1]) / 2)) then ok = true
|
||||||
|
elseif self._force.z > 0 and (p.z > (self._forcestart.z + 0.5 + (cbox[6] - cbox[3]) / 2)) then ok = true
|
||||||
|
elseif self._force.z < 0 and (p.z < (self._forcestart.z + 0.5 - (cbox[6] - cbox[3]) / 2)) then ok = true end
|
||||||
|
-- Item was successfully forced out. No more pushing
|
||||||
|
if ok then
|
||||||
|
self._forcetimer = -1
|
||||||
|
self._force = nil
|
||||||
|
enable_physics(self.object, self)
|
||||||
|
else
|
||||||
|
self._forcetimer = self._forcetimer - dtime
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
elseif self._force then
|
||||||
|
self._force = nil
|
||||||
|
enable_physics(self.object, self)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function move_items_in_water (self, p, def, node, is_floating, is_in_water)
|
||||||
|
-- Move item around on flowing liquids; add 'source' check to allow items to continue flowing a bit in the source block of flowing water.
|
||||||
|
if def and not is_floating and (def.liquidtype == "flowing" or def.liquidtype == "source") then
|
||||||
|
self._flowing = true
|
||||||
|
|
||||||
|
--[[ Get flowing direction (function call from flowlib), if there's a liquid.
|
||||||
|
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
|
||||||
|
Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]]
|
||||||
|
local vec = flowlib.quick_flow(p, node)
|
||||||
|
-- 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.2
|
||||||
|
-- Set new item moving speed into the direciton of the liquid
|
||||||
|
local newv = vector.multiply(vec, f)
|
||||||
|
-- Swap to acceleration instead of a static speed to better mimic MC mechanics.
|
||||||
|
self.object:set_acceleration(vector.new(newv.x, -0.22, newv.z))
|
||||||
|
|
||||||
|
self.physical_state = true
|
||||||
|
self._flowing = true
|
||||||
|
self.object:set_properties({
|
||||||
|
physical = true
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if is_in_water and def.liquidtype == "source" then
|
||||||
|
local cur_vec = self.object:get_velocity()
|
||||||
|
-- apply some acceleration in the opposite direction so it doesn't slide forever
|
||||||
|
local vec = {
|
||||||
|
x = 0 - cur_vec.x * 0.9,
|
||||||
|
y = 3 - cur_vec.y * 0.9,
|
||||||
|
z = 0 - cur_vec.z * 0.9
|
||||||
|
}
|
||||||
|
self.object:set_acceleration(vec)
|
||||||
|
-- slow down the item in water
|
||||||
|
local vel = self.object:get_velocity()
|
||||||
|
if vel.y < 0 then
|
||||||
|
vel.y = vel.y * 0.9
|
||||||
|
end
|
||||||
|
self.object:set_velocity(vel)
|
||||||
|
if self.physical_state ~= false or self._flowing ~= true then
|
||||||
|
self.physical_state = true
|
||||||
|
self._flowing = true
|
||||||
|
self.object:set_properties({
|
||||||
|
physical = true
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif self._flowing == true and not is_in_water and not is_floating then
|
||||||
|
-- Disable flowing physics if not on/in flowing liquid
|
||||||
|
self._flowing = false
|
||||||
|
enable_physics(self.object, self, true)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_entity(":__builtin:item", {
|
minetest.register_entity(":__builtin:item", {
|
||||||
initial_properties = {
|
initial_properties = {
|
||||||
|
@ -672,8 +839,7 @@ minetest.register_entity(":__builtin:item", {
|
||||||
-- otherwise there might have some data corruption.
|
-- otherwise there might have some data corruption.
|
||||||
if self.itemstring == "" then
|
if self.itemstring == "" then
|
||||||
minetest.log("warning",
|
minetest.log("warning",
|
||||||
"Item entity with empty itemstring found at " .. minetest.pos_to_string(self.object:get_pos()) ..
|
"Item entity with empty itemstring found and being deleted at: " .. minetest.pos_to_string(self.object:get_pos()))
|
||||||
"! Deleting it now.")
|
|
||||||
self._removed = true
|
self._removed = true
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
return
|
return
|
||||||
|
@ -724,167 +890,12 @@ minetest.register_entity(":__builtin:item", {
|
||||||
-- Destroy item in lava, fire or special nodes
|
-- Destroy item in lava, fire or special nodes
|
||||||
|
|
||||||
local def = minetest.registered_nodes[nn]
|
local def = minetest.registered_nodes[nn]
|
||||||
local lg = minetest.get_item_group(nn, "lava")
|
|
||||||
local fg = minetest.get_item_group(nn, "fire")
|
|
||||||
local dg = minetest.get_item_group(nn, "destroys_items")
|
|
||||||
if (def and (lg ~= 0 or fg ~= 0 or dg == 1)) then
|
|
||||||
--Wait 2 seconds to allow mob drops to be cooked, & picked up instead of instantly destroyed.
|
|
||||||
if self.age > 2 and minetest.get_item_group(self.itemstring, "fire_immune") == 0 then
|
|
||||||
if dg ~= 2 then
|
|
||||||
minetest.sound_play("builtin_item_lava", { pos = self.object:get_pos(), gain = 0.5 })
|
|
||||||
end
|
|
||||||
self._removed = true
|
|
||||||
self.object:remove()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Destroy item when it collides with a cactus
|
if nodes_destroy_items(self, moveresult, def, nn) then return end
|
||||||
if moveresult and moveresult.collides then
|
|
||||||
for _, collision in pairs(moveresult.collisions) do
|
|
||||||
local pos = collision.node_pos
|
|
||||||
if collision.type == "node" and minetest.get_node(pos).name == "mcl_core:cactus" then
|
|
||||||
self._removed = true
|
|
||||||
self.object:remove()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Push item out when stuck inside solid opaque node
|
if push_out_item_stuck_in_solid(self, dtime, p, def, is_in_water) then return end
|
||||||
if not is_in_water and def and def.walkable and def.groups and def.groups.opaque == 1 then
|
|
||||||
local shootdir
|
|
||||||
local cx = (p.x % 1) - 0.5
|
|
||||||
local cz = (p.z % 1) - 0.5
|
|
||||||
local order = {}
|
|
||||||
|
|
||||||
-- First prepare the order in which the 4 sides are to be checked.
|
if move_items_in_water (self, p, def, node, is_floating, is_in_water) then return end
|
||||||
-- 1st: closest
|
|
||||||
-- 2nd: other direction
|
|
||||||
-- 3rd and 4th: other axis
|
|
||||||
if math.abs(cx) < math.abs(cz) then
|
|
||||||
order = cxcz(order, cx, "x", "z")
|
|
||||||
order = cxcz(order, cz, "z", "x")
|
|
||||||
else
|
|
||||||
order = cxcz(order, cz, "z", "x")
|
|
||||||
order = cxcz(order, cx, "x", "z")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check which one of the 4 sides is free
|
|
||||||
for o = 1, #order do
|
|
||||||
local nn = minetest.get_node(vector.add(p, order[o])).name
|
|
||||||
local def = minetest.registered_nodes[nn]
|
|
||||||
if def and def.walkable == false and nn ~= "ignore" then
|
|
||||||
shootdir = order[o]
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- If none of the 4 sides is free, shoot upwards
|
|
||||||
if shootdir == nil then
|
|
||||||
shootdir = vector.new(0, 1, 0)
|
|
||||||
local nn = minetest.get_node(vector.add(p, shootdir)).name
|
|
||||||
if nn == "ignore" then
|
|
||||||
-- Do not push into ignore
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set new item moving speed accordingly
|
|
||||||
local newv = vector.multiply(shootdir, 3)
|
|
||||||
self.object:set_acceleration(vector.zero())
|
|
||||||
self.object:set_velocity(newv)
|
|
||||||
disable_physics(self.object, self, false, false)
|
|
||||||
|
|
||||||
|
|
||||||
if shootdir.y == 0 then
|
|
||||||
self._force = newv
|
|
||||||
p.x = math.floor(p.x)
|
|
||||||
p.y = math.floor(p.y)
|
|
||||||
p.z = math.floor(p.z)
|
|
||||||
self._forcestart = p
|
|
||||||
self._forcetimer = 1
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- This code is run after the entity got a push from above “push away” code.
|
|
||||||
-- It is responsible for making sure the entity is entirely outside the solid node
|
|
||||||
-- (with its full collision box), not just its center.
|
|
||||||
if self._forcetimer > 0 then
|
|
||||||
local cbox = self.object:get_properties().collisionbox
|
|
||||||
local ok = false
|
|
||||||
if self._force.x > 0 and (p.x > (self._forcestart.x + 0.5 + (cbox[4] - cbox[1]) / 2)) then ok = true
|
|
||||||
elseif self._force.x < 0 and (p.x < (self._forcestart.x + 0.5 - (cbox[4] - cbox[1]) / 2)) then ok = true
|
|
||||||
elseif self._force.z > 0 and (p.z > (self._forcestart.z + 0.5 + (cbox[6] - cbox[3]) / 2)) then ok = true
|
|
||||||
elseif self._force.z < 0 and (p.z < (self._forcestart.z + 0.5 - (cbox[6] - cbox[3]) / 2)) then ok = true end
|
|
||||||
-- Item was successfully forced out. No more pushing
|
|
||||||
if ok then
|
|
||||||
self._forcetimer = -1
|
|
||||||
self._force = nil
|
|
||||||
enable_physics(self.object, self)
|
|
||||||
else
|
|
||||||
self._forcetimer = self._forcetimer - dtime
|
|
||||||
end
|
|
||||||
return
|
|
||||||
elseif self._force then
|
|
||||||
self._force = nil
|
|
||||||
enable_physics(self.object, self)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Move item around on flowing liquids; add 'source' check to allow items to continue flowing a bit in the source block of flowing water.
|
|
||||||
if def and not is_floating and (def.liquidtype == "flowing" or def.liquidtype == "source") then
|
|
||||||
self._flowing = true
|
|
||||||
|
|
||||||
--[[ Get flowing direction (function call from flowlib), if there's a liquid.
|
|
||||||
NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7.
|
|
||||||
Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]]
|
|
||||||
local vec = flowlib.quick_flow(p, node)
|
|
||||||
-- 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.2
|
|
||||||
-- Set new item moving speed into the direciton of the liquid
|
|
||||||
local newv = vector.multiply(vec, f)
|
|
||||||
-- Swap to acceleration instead of a static speed to better mimic MC mechanics.
|
|
||||||
self.object:set_acceleration(vector.new(newv.x, -0.22, newv.z))
|
|
||||||
|
|
||||||
self.physical_state = true
|
|
||||||
self._flowing = true
|
|
||||||
self.object:set_properties({
|
|
||||||
physical = true
|
|
||||||
})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if is_in_water and def.liquidtype == "source" then
|
|
||||||
local cur_vec = self.object:get_velocity()
|
|
||||||
-- apply some acceleration in the opposite direction so it doesn't slide forever
|
|
||||||
local vec = {
|
|
||||||
x = 0 - cur_vec.x * 0.9,
|
|
||||||
y = 3 - cur_vec.y * 0.9,
|
|
||||||
z = 0 - cur_vec.z * 0.9
|
|
||||||
}
|
|
||||||
self.object:set_acceleration(vec)
|
|
||||||
-- slow down the item in water
|
|
||||||
local vel = self.object:get_velocity()
|
|
||||||
if vel.y < 0 then
|
|
||||||
vel.y = vel.y * 0.9
|
|
||||||
end
|
|
||||||
self.object:set_velocity(vel)
|
|
||||||
if self.physical_state ~= false or self._flowing ~= true then
|
|
||||||
self.physical_state = true
|
|
||||||
self._flowing = true
|
|
||||||
self.object:set_properties({
|
|
||||||
physical = true
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif self._flowing == true and not is_in_water and not is_floating then
|
|
||||||
-- Disable flowing physics if not on/in flowing liquid
|
|
||||||
self._flowing = false
|
|
||||||
enable_physics(self.object, self, true)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If node is not registered or node is walkably solid and resting on nodebox
|
-- If node is not registered or node is walkably solid and resting on nodebox
|
||||||
local nn = minetest.get_node(vector.offset(p, 0, -0.5, 0)).name
|
local nn = minetest.get_node(vector.offset(p, 0, -0.5, 0)).name
|
||||||
|
|
Loading…
Reference in New Issue