Aaron Suen d7819762e5 Full proper support for spectator mods.
If players are invisible, NodeCore will not add any visible or
audible effects for them, allowing such players to be completely
non-interactive with gameplay.

This allows things like spectator or stealth-admin mods to
function properly.
2019-12-11 06:52:09 -05:00

151 lines
3.7 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, os, pairs, table
= minetest, nodecore, os, pairs, table
local os_date, table_concat
= os.date, table.concat
-- LUALOCALS > ---------------------------------------------------------
nodecore.amcoremod()
local modname = minetest.get_current_modname()
local anim = {
stand = {x = 0, y = 0},
sit = {x = 1, y = 1},
walk = {x = 2, y = 42},
mine = {x = 43, y = 57, speed = 0.85},
lay = {x = 58, y = 58},
walk_mine = {x = 59, y = 103},
swim_up = {x = 105, y = 162, speed = 0.4},
swim_down = {x = 163, y = 223, speed = 0.4},
swim_mine = {x = 224, y = 281, speed = 0.5}
}
local function setcached(func)
local cache = {}
return function(player, value)
local pname = player:get_player_name()
if cache[pname] == value then return end
cache[pname] = value
return func(player, value)
end
end
local setanim = setcached(function(player, x)
local a = anim[x] or anim.stand
player:set_animation({x = a.x, y = a.y},
72 * (a.speed or 1))
end)
local setskin = setcached(function(player, x)
player:set_properties({textures = {x}})
end)
local skintimes = {}
local dayskins = {
day_2_14 = true,
day_3_17 = true,
day_4_1 = true,
day_10_31 = true
}
local liquids = {}
minetest.after(0, function()
for k, v in pairs(minetest.registered_items) do
if v.liquidtype and v.liquidtype ~= "none" then
liquids[k] = true
end
end
end)
local function swimming(player)
local pos = player:get_pos()
local r = 0.6
for dz = -r, r, r do
for dx = -r, r, r do
local p = {
x = pos.x + dx,
y = pos.y,
z = pos.z + dz
}
local node = minetest.get_node(p)
if (node.name == "air" or liquids[node.name]) then
p.y = p.y - 0.35
node = minetest.get_node(p)
end
if not liquids[node.name] then return end
end
end
return true
end
local function updatevisuals(player)
local hp = player:get_hp()
if hp <= 0 then
setanim(player, "lay")
else
local ctl = player:get_player_control()
local walk = ctl.up or ctl.down or ctl.right or ctl.left
local mine = ctl.LMB or ctl.RMB
if not swimming(player) then
if walk and mine then
setanim(player, "walk_mine")
elseif walk then
setanim(player, "walk")
elseif mine then
setanim(player, "mine")
else
setanim(player, "stand")
end
else
local v = player:get_player_velocity()
if mine then
setanim(player, "swim_mine")
elseif v and v.y >= -0.5 then
setanim(player, "swim_up")
else
setanim(player, "swim_down")
end
end
end
local pname = player:get_player_name()
local now = minetest.get_us_time() / 1000000
local last = skintimes[pname] or 0
if now < last + 2 then return end
skintimes[pname] = now
local layers = {"base.png"}
local date = os_date("!*t")
local bare = "day_" .. date.month .. "_" .. date.day
if dayskins[bare] then layers[#layers + 1] = bare .. ".png" end
local privs = minetest.get_player_privs(player:get_player_name())
if not privs.interact then layers[#layers + 1] = "no_interact.png" end
if not privs.shout then layers[#layers + 1] = "no_shout.png" end
for k, v in pairs(layers) do
layers[k] = "(" .. modname .. "_" .. v .. ")"
end
setskin(player, table_concat(layers, "^") .. "^[makealpha:254,0,253")
end
minetest.register_on_joinplayer(function(player)
player:set_properties({
visual = "mesh",
visual_size = {x = 0.9, y = 0.9, z = 0.9},
mesh = modname .. ".b3d"
})
setskin(player, "dummy")
setanim(player, "dummy")
updatevisuals(player)
end)
minetest.register_globalstep(function()
for _, player in pairs(minetest.get_connected_players()) do
if nodecore.player_visible(player) then
updatevisuals(player)
end
end
end)