2020-03-25 21:49:54 +01:00
|
|
|
local update_interval = 0.2
|
|
|
|
local level_delta = 2
|
|
|
|
local shiny_items = {}
|
|
|
|
|
|
|
|
--- Shining API ---
|
|
|
|
wielded_light = {}
|
|
|
|
|
|
|
|
function wielded_light.update_light(pos, light_level)
|
|
|
|
local around_vector = {
|
|
|
|
{x=0, y=0, z=0},
|
|
|
|
{x=0, y=1, z=0}, {x=0, y=-1, z=0},
|
|
|
|
{x=1, y=0, z=0}, {x=-1, y=0, z=0},
|
|
|
|
{x=0, y=0, z=1}, {x=0, y=0, z=1},
|
|
|
|
}
|
|
|
|
local do_update = false
|
|
|
|
local old_value = 0
|
|
|
|
local timer
|
|
|
|
local light_pos
|
|
|
|
for _, around in ipairs(around_vector) do
|
|
|
|
light_pos = vector.add(pos, around)
|
|
|
|
local name = minetest.get_node(light_pos).name
|
|
|
|
if name == "air" and (minetest.get_node_light(light_pos) or 0) < light_level then
|
|
|
|
do_update = true
|
|
|
|
break
|
|
|
|
elseif name:sub(1,13) == "wielded_light" then -- Update existing light node and timer
|
|
|
|
old_value = tonumber(name:sub(15))
|
|
|
|
if light_level > old_value then
|
|
|
|
do_update = true
|
|
|
|
else
|
|
|
|
timer = minetest.get_node_timer(light_pos)
|
|
|
|
local elapsed = timer:get_elapsed()
|
|
|
|
if elapsed > (update_interval * 1.5) then
|
|
|
|
-- The timer is set to 3x update_interval
|
|
|
|
-- This node was not updated the last interval and may
|
|
|
|
-- is disabled before the next step
|
|
|
|
-- Therefore the light should be re-set to avoid flicker
|
|
|
|
do_update = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if do_update then
|
|
|
|
timer = timer or minetest.get_node_timer(light_pos)
|
|
|
|
if light_level ~= old_value then
|
|
|
|
minetest.swap_node(light_pos, {name = "wielded_light:"..light_level})
|
|
|
|
end
|
|
|
|
timer:start(update_interval*3)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wielded_light.update_light_by_item(item, pos)
|
|
|
|
local stack = ItemStack(item)
|
|
|
|
local light_level = shiny_items[stack:get_name()]
|
|
|
|
local itemdef = stack:get_definition()
|
|
|
|
if not light_level and not itemdef then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
light_level = light_level or ((itemdef.light_source or 0) - level_delta)
|
|
|
|
|
|
|
|
if light_level > 0 then
|
|
|
|
wielded_light.update_light(pos, light_level)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function wielded_light.register_item_light(itemname, light_level)
|
|
|
|
shiny_items[itemname] = light_level
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- Register helper nodes
|
|
|
|
for i=1, 14 do
|
|
|
|
minetest.register_node("wielded_light:"..i, {
|
|
|
|
drawtype = "airlike",
|
|
|
|
groups = {not_in_creative_inventory = 1},
|
|
|
|
walkable = false,
|
|
|
|
paramtype = "light",
|
|
|
|
sunlight_propagates = true,
|
|
|
|
light_source = i,
|
|
|
|
pointable = false,
|
|
|
|
buildable_to = true,
|
|
|
|
drops = {},
|
|
|
|
on_timer = function(pos, elapsed)
|
|
|
|
minetest.swap_node(pos, {name = "air"})
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Wielded item shining globalstep
|
|
|
|
local timer = 0
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
|
|
timer = timer + dtime;
|
|
|
|
if timer < update_interval then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
timer = 0
|
|
|
|
|
|
|
|
for _, player in pairs(minetest.get_connected_players()) do
|
|
|
|
-- predict where the player will be the next time we place the light
|
|
|
|
-- assume that on average we're slightly past 1/2 of the next interval, hence 1.5
|
|
|
|
-- (since the scheduling is a bit behind)
|
|
|
|
-- experimentally this also works nicely
|
|
|
|
local pos = vector.add (
|
|
|
|
vector.add({x = 0, y = 1, z = 0}, vector.round(player:getpos())),
|
|
|
|
vector.round(vector.multiply(player:get_player_velocity(), update_interval * 1.5))
|
|
|
|
)
|
|
|
|
|
|
|
|
wielded_light.update_light_by_item(player:get_wielded_item(), pos)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
|
|
-- Dropped item on_step override
|
|
|
|
-- https://github.com/minetest/minetest/issues/6909
|
|
|
|
local builtin_item = minetest.registered_entities["__builtin:item"]
|
|
|
|
local item = {
|
|
|
|
on_step = function(self, dtime)
|
|
|
|
builtin_item.on_step(self, dtime)
|
|
|
|
|
|
|
|
self.shining_timer = (self.shining_timer or 0) + dtime
|
|
|
|
if self.shining_timer >= update_interval then
|
|
|
|
self.shining_timer = 0
|
|
|
|
local pos = self.object:get_pos()
|
|
|
|
if pos then
|
|
|
|
wielded_light.update_light_by_item(self.itemstring, pos)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
}
|
|
|
|
setmetatable(item, {__index = builtin_item})
|
|
|
|
minetest.register_entity(":__builtin:item", item)
|
|
|
|
|
|
|
|
|
|
|
|
---TEST
|
|
|
|
--wielded_light.register_item_light('default:dirt', 14)
|
|
|
|
|
2020-03-25 22:28:05 +01:00
|
|
|
wielded_light.register_item_light('starsnodes:lightsaberongreen', 14)
|
|
|
|
wielded_light.register_item_light('starsnodes:lightsaberonblue', 14)
|
|
|
|
wielded_light.register_item_light('starsnodes:lightsaberonyellow', 14)
|
|
|
|
wielded_light.register_item_light('starsnodes:lightsaberonpurple', 14)
|
|
|
|
wielded_light.register_item_light('starsnodes:lightsaberonred', 14)
|