Skip to content
Snippets Groups Projects
Commit 58e57f95 authored by Peter Nerlich's avatar Peter Nerlich
Browse files
parent 854e6d5a
No related branches found
No related tags found
No related merge requests found
-- adapted from https://github.com/pandorabox-io/pandorabox_custom/blob/master/death.lua
local WAYPOINT_EXPIRES_SECONDS = tonumber(minetest.settings:get("kif_custom.death.waypoint_expires_seconds")) or 60 * 60
local WAYPOINT_EXPIRES_SECONDS_CREATIVE = tonumber(minetest.settings:get("kif_custom.death.waypoint_expires_seconds_creative")) or 5 * 60
local UPDATE_INTERVAL = tonumber(minetest.settings:get("kif_custom.death.update_interval")) or 5
local WAYPOINT_SATURATION = tonumber(minetest.settings:get("kif_custom.death.waypoint_saturation")) or 1
local MARKERS_FILE = minetest.get_worldpath().."/death_markers.json"
-- table for deaths indexed by player name and pos
local death_markers = {}
local dirty = false
local WRITEBACK_INTERVAL_SEC = 10
-- table to remember which hud elements we know and manage (per player and pos)
local managed_hud_ids = {}
-- color calculation got a bit crazy, so let's cache these...
local color_cache = {}
local read_json_file = function(path)
local file = io.open(path, "r")
local content = {}
if file then
local json = file:read("*a")
content = minetest.parse_json(json or "[]") or {}
file:close()
end
return content
end
local write_json_file = function(path, content)
local file = io.open(path,"w")
local json = minetest.write_json(content)
if file and file:write(json) and file:close() then
return true
else
return false
end
end
death_markers = read_json_file(MARKERS_FILE)
local mark_dirty_and_schedule_writeback = function()
if not dirty then
dirty = true
minetest.after(WRITEBACK_INTERVAL_SEC, function()
if dirty then
write_json_file(MARKERS_FILE, death_markers)
dirty = false
end
end)
end
end
-- add something to the bones on_punch to remove markers when the bones are picked up
local bones_def = minetest.registered_items["bones:bones"]
assert(bones_def)
local bones_on_punch = bones_def.on_punch
assert(bones_on_punch)
assert(type(bones_on_punch) == "function")
minetest.override_item("bones:bones", {
on_punch = function(pos, node, player)
-- call original function
bones_on_punch(pos, node, player)
local player_name = player:get_player_name()
local pos_string = minetest.pos_to_string(pos)
if death_markers[player_name] ~= nil and death_markers[player_name][pos_string] ~= nil then
minetest.after(1, function()
if minetest.get_node(pos).name ~= "bones:bones" then
death_markers[player_name][pos_string] = nil
update_hud_markers(player_name)
end
end)
end
end
})
minetest.register_on_shutdown(function()
if dirty then
write_json_file(MARKERS_FILE, death_markers)
dirty = false
end
-- clean up markers (not sure if this makes sense, but I got weird results before, so...)
for player_name, hud_ids in pairs(managed_hud_ids) do
local player = minetest.get_player_by_name(player_name)
if player ~= nil then
for pos_string, marker in pairs(hud_ids) do
player:hud_remove(hud_id)
end
end
managed_hud_ids[player_name] = nil
end
end)
local interpolate = function(a, b, t)
return t*(b-a) + a
end
local calculate_color = function(t)
-- clamp t between 0 and 1, in steps of 0.01
t = math.max(0, math.min(1, math.floor(t * 100 + 0.5) / 100))
if color_cache[t] == nil then
-- helper variables
local t2 = t^2 -- t squared
local it = 1 - t -- inverse t
local it2 = it^2 -- inverse t squared
local r = t2
local g = 2*t * it
local b = it2
local avg = math.sqrt(r^2 + g^2 + b^2)
r = interpolate(avg, r, WAYPOINT_SATURATION)
g = interpolate(avg, g, WAYPOINT_SATURATION)
b = interpolate(avg, b, WAYPOINT_SATURATION)
local white_start = it2^2
local dimming = 1 - t^8
r = (r * (1-white_start) + white_start) * dimming
g = (g * (1-white_start) + white_start) * dimming
b = (b * (1-white_start) + white_start) * dimming
-- we have 255 steps per subpixel
local base = 0xFF
-- clamp values, discard fractions
r = math.floor(base * math.max(0, math.min(1, r)))
g = math.floor(base * math.max(0, math.min(1, g)))
b = math.floor(base * math.max(0, math.min(1, b)))
-- pack it into one number representing the RGB values
color_cache[t] = r*2^16 + g*2^8 + b
end
return color_cache[t]
end
local update_hud_markers = function(player_name)
if death_markers[player_name] ~= nil then
local player = minetest.get_player_by_name(player_name)
local now = os.time()
local valid_hud_ids = {}
for pos_string, marker in pairs(death_markers[player_name]) do
local t = now - marker.timestamp
if marker.is_creative then
t = t / WAYPOINT_EXPIRES_SECONDS_CREATIVE
else
t = t / WAYPOINT_EXPIRES_SECONDS
end
if managed_hud_ids[player_name] ~= nil and managed_hud_ids[player_name][pos_string] ~= nil then
local hud_id = managed_hud_ids[player_name][pos_string]
valid_hud_ids[hud_id] = hud_id
if t > 1 then
death_markers[player_name][pos_string] = nil
mark_dirty_and_schedule_writeback()
if player ~= nil then
player:hud_remove(hud_id)
managed_hud_ids[player_name][pos_string] = nil
end
else
if player ~= nil then
player:hud_change(hud_id, "name", marker.text)--.." (t = "..tostring(math.floor(t * 100 + 0.5) / 100)..")")
player:hud_change(hud_id, "number", calculate_color(t))
end
end
else
if player ~= nil and t < 1 then
if managed_hud_ids[player_name] == nil then
managed_hud_ids[player_name] = {}
end
local pos = minetest.string_to_pos(pos_string)
local hud_id = player:hud_add({
hud_elem_type = "waypoint",
name = marker.text,--.." (add | t = "..tostring(math.floor(t * 100 + 0.5) / 100)..")",
text = "m",
number = calculate_color(t),
world_pos = pos
})
managed_hud_ids[player_name][pos_string] = hud_id
valid_hud_ids[hud_id] = hud_id
end
end
end
if player ~= nil and managed_hud_ids[player_name] ~= nil then
-- everything that remains should be removed
for pos_string, hud_id in pairs(managed_hud_ids[player_name]) do
if valid_hud_ids[hud_id] == nil then
player:hud_remove(hud_id)
managed_hud_ids[player_name][pos_string] = nil
end
end
end
end
end
minetest.register_on_dieplayer(function(player)
local player_name = player:get_player_name()
local is_creative = creative and creative.is_enabled_for(player_name)
local pos = player:get_pos()
pos.x = math.floor(pos.x + 0.5)
pos.y = math.floor(pos.y + 0.5)
pos.z = math.floor(pos.z + 0.5)
local pos_string = minetest.pos_to_string(pos)
minetest.log("action", "[death] player '" .. player_name .. "' died at " .. pos_string .. (is_creative and " (creative)" or ""))
minetest.chat_send_player(player_name, "You died at " .. pos_string)
local msg_string = ""
if not is_creative then
msg_string = "Bones"
if player.get_attribute then
-- [xp_redo] keeps track of deathcount, let's see if it is there
local count = player:get_attribute("died")
if count then
msg_string = "Bone #" .. tostring(count)
end
end
else
msg_string = "Death"
end
if death_markers[player_name] == nil then
death_markers[player_name] = {}
end
death_markers[player_name][pos_string] = {
text = msg_string,
timestamp = os.time(),
is_creative = is_creative,
}
mark_dirty_and_schedule_writeback()
update_hud_markers(player_name)
end)
minetest.register_on_joinplayer(function(player)
local player_name = player:get_player_name()
update_hud_markers(player_name)
if death_markers[player_name] ~= nil then
minetest.after(2, function()
local markers = {}
for pos_string, marker in pairs(death_markers[player_name]) do
table.insert(markers, pos_string.." "..marker.text..(marker.is_creative and " (creative)" or ""))
end
--minetest.chat_send_player(player_name, "Your death markers ("..tostring(#markers).."): "..table.concat(markers, ", "))
end)
end
end)
minetest.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
--[[
for pos_string, marker in pairs(managed_hud_ids[player_name]) do
player:hud_remove(hud_id)
end
managed_hud_ids[player_name] = nil
]]--
end)
local update_loop
update_loop = function()
for player_name, markers in pairs(managed_hud_ids) do
update_hud_markers(player_name)
end
minetest.after(UPDATE_INTERVAL, update_loop)
end
update_loop()
......@@ -19,8 +19,5 @@ end
-- /spawn command
dofile(MP.."/chat/spawn.lua")
-- death message
dofile(MP.."/death.lua")
-- by popular demand
dofile(MP.."/additional_stuff/salad_pickaxe.lua")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment