Aaron Suen 3d72999ef6 Log player push-out
It seems as though there might be something
weird happening with this on join.  Add extra
logging so we can see what's happening.
2020-09-16 19:59:07 -04:00

98 lines
2.8 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore, pairs, string, tonumber, type, vector
= math, minetest, nodecore, pairs, string, tonumber, type, vector
local math_random, string_format
= math.random, string.format
-- LUALOCALS > ---------------------------------------------------------
local mintime = tonumber(minetest.settings:get(nodecore.product:lower() .. "_pushout_time")) or 2
local stepdist = tonumber(minetest.settings:get(nodecore.product:lower() .. "_pushout_stepdist")) or 5
local function normalbox(box)
if not box then return true end
if type(box) ~= "table" then return end
if box.fixed then return normalbox(box.fixed) end
if #box == 1 then return box[1] end
return box[1] == -0.5 and box[2] == -0.5 and box[3] == -0.5
and box[4] == 0.5 and box[5] == 0.5 and box[6] == 0.5
end
local solids = {}
minetest.after(0, function()
for k, v in pairs(minetest.registered_nodes) do
if v.walkable and v.liquidtype == "none"
and normalbox(v.collision_box) then
solids[k] = true
end
end
solids.ignore = nil
end)
local function isroom(pos)
return not (solids[minetest.get_node(pos).name]
or solids[minetest.get_node({
x = pos.x,
y = pos.y + 1,
z = pos.z
}).name])
end
nodecore.player_pushout_disable = nodecore.player_pushout_disable or function() end
nodecore.register_playerstep({
label = "push player out of solids",
action = function(player, data, dtime)
local function reset() data.pushout = nil end
if minetest.check_player_privs(player, "noclip")
or nodecore.player_pushout_disable(player, data)
then return reset() end
local pos = vector.round(player:get_pos())
if isroom(pos) then return reset() end
local podata = data.pushout or {}
local oldpos = podata.pos or pos
if not vector.equals(pos, oldpos) then return reset() end
local pt = (podata.time or 0) + dtime
if pt < mintime then
data.pushout = {time = pt, pos = pos}
return
end
local function pushto(newpos)
local dist = vector.distance(pos, newpos)
if dist > 1 then
nodecore.addphealth(player, -dist + 1, {
nc_type = "pushout"
})
end
newpos.y = newpos.y - 0.49
nodecore.log("action", string_format("player %q pushed out of"
.. " solid from %s to %s",
player:get_player_name(),
minetest.pos_to_string(pos),
minetest.pos_to_string(newpos)))
player:set_pos(newpos)
return reset()
end
for rel in nodecore.settlescan() do
local p = vector.add(pos, rel)
if isroom(p) then
return pushto(p)
end
end
local function bias(n)
return n + ((n > 0) and math_random(-stepdist - 1, stepdist - 1)
or math_random(-stepdist + 1, stepdist + 1))
end
return pushto({
x = bias(pos.x),
y = bias(pos.y),
z = bias(pos.z)
})
end
})