2020-02-22 21:57:08 -05:00
|
|
|
-- LUALOCALS < ---------------------------------------------------------
|
2020-05-12 07:22:41 -04:00
|
|
|
local ItemStack, minetest, nodecore, pairs, setmetatable, vector
|
|
|
|
= ItemStack, minetest, nodecore, pairs, setmetatable, vector
|
2020-02-22 21:57:08 -05:00
|
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
|
2020-05-12 07:22:41 -04:00
|
|
|
-- Register nodes that can be replaced by dynamic lights
|
|
|
|
|
2020-05-26 19:26:08 -04:00
|
|
|
local canreplace = {air = 0}
|
2020-02-22 21:57:08 -05:00
|
|
|
|
2020-03-29 20:05:11 -04:00
|
|
|
local true_airlike = {
|
|
|
|
drawtype = "airlike",
|
|
|
|
pointable = false,
|
|
|
|
walkable = false,
|
|
|
|
climbable = false,
|
|
|
|
buildable_to = true,
|
|
|
|
floodable = true,
|
|
|
|
air_equivalent = true,
|
|
|
|
paramtype = "light",
|
|
|
|
light_source = 0,
|
|
|
|
sunlight_propagates = true,
|
|
|
|
}
|
|
|
|
|
2020-05-12 06:55:11 -04:00
|
|
|
minetest.after(0, function()
|
|
|
|
for k, v in pairs(minetest.registered_nodes) do
|
|
|
|
local ok = not canreplace[k]
|
|
|
|
for dk, dv in pairs(true_airlike) do
|
|
|
|
ok = ok and v[dk] == dv
|
|
|
|
end
|
2020-05-26 19:26:08 -04:00
|
|
|
if ok then canreplace[k] = 0 end
|
2020-05-12 06:55:11 -04:00
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2020-05-26 07:50:57 -04:00
|
|
|
-- API for checking if dynamic lights are valid
|
|
|
|
|
|
|
|
local ttl = 0.25
|
|
|
|
|
|
|
|
local active_lights = {}
|
|
|
|
|
|
|
|
local function setup_light(pos, check)
|
|
|
|
active_lights[minetest.hash_node_position(pos)] = {
|
|
|
|
exp = nodecore.gametime + ttl,
|
|
|
|
check = check
|
|
|
|
}
|
|
|
|
minetest.get_node_timer(pos):start(ttl)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function check_light(pos)
|
|
|
|
local data = active_lights[minetest.hash_node_position(pos)]
|
|
|
|
if not data then return minetest.remove_node(pos) end
|
|
|
|
if nodecore.gametime < data.exp then return end
|
2020-05-26 18:46:06 -04:00
|
|
|
if data.check and data.check() then
|
2020-05-26 07:50:57 -04:00
|
|
|
data.exp = nodecore.gametime + ttl
|
|
|
|
minetest.get_node_timer(pos):start(ttl)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
minetest.remove_node(pos)
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2020-05-12 07:22:41 -04:00
|
|
|
-- Register dynamic light nodes
|
|
|
|
|
2020-05-12 06:55:11 -04:00
|
|
|
local nodes = {}
|
|
|
|
|
2020-05-12 07:13:36 -04:00
|
|
|
local function dynamic_light_node(level) return modname .. ":light" .. level end
|
|
|
|
nodecore.dynamic_light_node = dynamic_light_node
|
2020-05-12 06:55:11 -04:00
|
|
|
|
|
|
|
for level = 1, nodecore.light_sun - 1 do
|
2020-02-22 21:57:08 -05:00
|
|
|
if nodes[level] then return nodes[level] end
|
2020-05-12 07:13:36 -04:00
|
|
|
local name = dynamic_light_node(level)
|
2020-03-29 20:05:11 -04:00
|
|
|
local def = {
|
|
|
|
light_source = level,
|
2020-05-26 07:50:57 -04:00
|
|
|
on_timer = check_light,
|
2020-05-31 15:59:53 -04:00
|
|
|
air_equivalent = true,
|
2020-03-29 20:05:11 -04:00
|
|
|
groups = {dynamic_light = level}
|
|
|
|
}
|
|
|
|
for k, v in pairs(true_airlike) do def[k] = def[k] or v end
|
|
|
|
minetest.register_node(":" .. name, def)
|
2020-02-22 21:57:08 -05:00
|
|
|
nodes[level] = name
|
2020-05-26 19:26:08 -04:00
|
|
|
canreplace[name] = level
|
2020-02-22 21:57:08 -05:00
|
|
|
end
|
|
|
|
|
2020-05-12 07:13:36 -04:00
|
|
|
minetest.register_alias("nc_torch:wield_light", dynamic_light_node(8))
|
2020-02-22 21:57:08 -05:00
|
|
|
|
2020-05-12 07:22:41 -04:00
|
|
|
-- API for adding dynamic lights to world
|
|
|
|
|
2020-02-22 21:57:08 -05:00
|
|
|
nodecore.register_limited_abm({
|
|
|
|
label = "dynamic light cleanup",
|
|
|
|
interval = 1,
|
|
|
|
chance = 1,
|
|
|
|
nodenames = {"group:dynamic_light"},
|
2020-05-26 07:50:57 -04:00
|
|
|
action = check_light
|
2020-02-22 21:57:08 -05:00
|
|
|
})
|
|
|
|
|
2020-05-26 18:46:06 -04:00
|
|
|
local function dynamic_light_add(pos, level, check, exact)
|
2020-05-18 18:36:06 -04:00
|
|
|
if not pos then return end
|
2020-03-15 08:20:56 -04:00
|
|
|
local name = minetest.get_node(pos).name
|
2020-05-26 19:26:08 -04:00
|
|
|
local curlight = canreplace[name]
|
|
|
|
if not curlight then
|
2020-05-26 18:46:06 -04:00
|
|
|
if exact then return end
|
|
|
|
return dynamic_light_add({x = pos.x, y = pos.y - 1, z = pos.z}, level, check, true)
|
|
|
|
or dynamic_light_add({x = pos.x, y = pos.y + 1, z = pos.z}, level, check, true)
|
|
|
|
or dynamic_light_add({x = pos.x + 1, y = pos.y, z = pos.z}, level, check, true)
|
|
|
|
or dynamic_light_add({x = pos.x - 1, y = pos.y, z = pos.z}, level, check, true)
|
|
|
|
or dynamic_light_add({x = pos.x, y = pos.y, z = pos.z + 1}, level, check, true)
|
|
|
|
or dynamic_light_add({x = pos.x, y = pos.y, z = pos.z - 1}, level, check, true)
|
|
|
|
end
|
2020-05-12 07:25:58 -04:00
|
|
|
if level < 1 then return end
|
|
|
|
if level > nodecore.light_sun - 1 then level = nodecore.light_sun - 1 end
|
2020-05-12 07:13:36 -04:00
|
|
|
local setname = dynamic_light_node(level)
|
2020-03-15 08:20:56 -04:00
|
|
|
pos = vector.round(pos)
|
2020-05-26 19:26:08 -04:00
|
|
|
if curlight <= level then
|
|
|
|
local ll = nodecore.get_node_light(pos)
|
|
|
|
if ll and ll > level then return end
|
|
|
|
end
|
|
|
|
if curlight > level and not check_light(pos) then return end
|
2020-05-12 06:55:11 -04:00
|
|
|
if name ~= setname then minetest.set_node(pos, {name = setname}) end
|
2020-05-26 07:50:57 -04:00
|
|
|
setup_light(pos, check)
|
2020-05-26 18:46:06 -04:00
|
|
|
return true
|
2020-02-22 21:57:08 -05:00
|
|
|
end
|
2020-05-12 07:13:36 -04:00
|
|
|
nodecore.dynamic_light_add = dynamic_light_add
|
|
|
|
|
2020-05-12 07:22:41 -04:00
|
|
|
-- Automatic player wield lights
|
|
|
|
|
|
|
|
local function lightsrc(stack)
|
|
|
|
local def = minetest.registered_items[stack:get_name()] or {}
|
|
|
|
return def.light_source or 0
|
|
|
|
end
|
|
|
|
|
2020-05-12 07:13:36 -04:00
|
|
|
local function player_wield_light(player)
|
2020-05-30 19:00:22 -04:00
|
|
|
local glow = 0
|
2020-05-12 07:13:36 -04:00
|
|
|
for _, stack in pairs(player:get_inventory():get_list("main")) do
|
2020-05-12 07:22:41 -04:00
|
|
|
local src = lightsrc(stack)
|
|
|
|
if src > glow then glow = src end
|
2020-05-12 07:13:36 -04:00
|
|
|
end
|
|
|
|
if glow < 1 then return end
|
|
|
|
local pos = player:get_pos()
|
|
|
|
pos.y = pos.y + player:get_properties().eye_height
|
2020-05-26 18:46:06 -04:00
|
|
|
pos = vector.round(pos)
|
2020-05-26 07:50:57 -04:00
|
|
|
local pname = player:get_player_name()
|
2020-05-26 18:46:06 -04:00
|
|
|
return dynamic_light_add(pos, glow, function()
|
2020-05-26 07:50:57 -04:00
|
|
|
local pl = minetest.get_player_by_name(pname)
|
|
|
|
if not pl then return end
|
|
|
|
local pp = pl:get_pos()
|
|
|
|
pp.y = pp.y + pl:get_properties().eye_height
|
2020-05-26 18:46:06 -04:00
|
|
|
return vector.equals(pos, vector.round(pp))
|
2020-05-26 07:50:57 -04:00
|
|
|
end)
|
2020-05-12 07:13:36 -04:00
|
|
|
end
|
|
|
|
|
2020-06-15 07:21:39 -04:00
|
|
|
nodecore.register_globalstep_perplayer("player wield light", function(player)
|
|
|
|
if nodecore.player_visible(player) then
|
|
|
|
return player_wield_light(player)
|
2020-05-12 07:13:36 -04:00
|
|
|
end
|
|
|
|
end)
|
2020-05-12 07:22:41 -04:00
|
|
|
|
|
|
|
-- Automatic entity light sources
|
|
|
|
|
|
|
|
local function entlight(self, ...)
|
|
|
|
local stack = ItemStack(self.node and self.node.name or self.itemstring or "")
|
|
|
|
local src = lightsrc(stack)
|
2020-05-26 07:50:57 -04:00
|
|
|
if src > 0 then
|
2020-05-26 18:46:06 -04:00
|
|
|
local pos = self.object:get_pos()
|
|
|
|
if not pos then return ... end
|
|
|
|
pos = vector.round(pos)
|
|
|
|
nodecore.dynamic_light_add(pos, src, function()
|
2020-05-26 07:50:57 -04:00
|
|
|
for _, v in pairs(nodecore.get_objects_at_pos(pos)) do
|
|
|
|
if v == self.object then return true end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
2020-05-12 07:22:41 -04:00
|
|
|
return ...
|
|
|
|
end
|
|
|
|
for _, name in pairs({"item", "falling_node"}) do
|
|
|
|
local def = minetest.registered_entities["__builtin:" .. name]
|
|
|
|
local ndef = {
|
|
|
|
on_step = function(self, ...)
|
|
|
|
return entlight(self, def.on_step(self, ...))
|
|
|
|
end
|
|
|
|
}
|
|
|
|
setmetatable(ndef, def)
|
|
|
|
minetest.register_entity(":__builtin:" .. name, ndef)
|
|
|
|
end
|