Fix and optimize line of sight checks

- Check destination medium against source, since it's possible
  to transition from a fluid to air and raycast will NOT collide
  with the air, causing from-fluid-to-air transitions not to be
  detected.
- Pre-cache fluid medium data for all node defs instead of running
  through logic at runtime.
master
Aaron Suen 2022-05-03 07:10:15 -04:00
parent 0a9ba9c210
commit 64f28532f1
1 changed files with 39 additions and 35 deletions

View File

@ -94,42 +94,8 @@ local function setcamera(player, pos, target)
return player:set_pos(pos)
end
local function fluidmedium(pos)
local node = minetest.get_node(pos)
local def = minetest.registered_items[node.name]
if not def then return node.name end
if def.sunlight_propagates then return "CLEAR" end
return def.liquid_alternative_source or node.name
end
local function sightblocked(from, to)
local fsrc = fluidmedium(from)
for pt in minetest.raycast(from, to, false, true) do
if pt.type == "node" then
if fluidmedium(pt.under) ~= fsrc then
return pt.above
end
end
end
end
local getdata
do
local datastore = {}
function getdata(p)
local pname = type(p) == "string" and p or p:get_player_name()
local data = datastore[pname]
if not data then
data = {}
datastore[pname] = data
end
return data
end
minetest.register_on_leaveplayer(function(player)
datastore[player:get_player_name()] = nil
end)
end
local allow
local fluidmedium
do
local allow_drawtypes = {
airlike = true,
@ -149,17 +115,55 @@ do
local allow_nodes = {
ignore = true
}
local fluids = {}
minetest.after(0, function()
for k, v in pairs(minetest.registered_nodes) do
if allow_drawtypes[v.drawtype]
and v.paramtype == "light" then
allow_nodes[k] = true
end
if v.sunlight_propagates then
fluids[k] = "CLEAR"
else
fluids[k] = v.liquid_alternative_source or k
end
end
end)
allow = function(pos)
return allow_nodes[minetest.get_node(pos).name]
end
fluidmedium = function(pos)
return fluids[minetest.get_node(pos).name]
end
end
local function sightblocked(from, to)
local fsrc = fluidmedium(from)
for pt in minetest.raycast(from, to, false, true) do
if pt.type == "node" then
if fluidmedium(pt.under) ~= fsrc then
return pt.above
end
end
end
if fluidmedium(to) ~= fsrc then return to end
end
local getdata
do
local datastore = {}
function getdata(p)
local pname = type(p) == "string" and p or p:get_player_name()
local data = datastore[pname]
if not data then
data = {}
datastore[pname] = data
end
return data
end
minetest.register_on_leaveplayer(function(player)
datastore[player:get_player_name()] = nil
end)
end
local function hudset(player, data, key, def)