First commit from local files.
commit
c264d75d07
|
@ -0,0 +1,53 @@
|
|||
Showbones
|
||||
=========
|
||||
|
||||
This mod saves the locations of player bones in a text file
|
||||
"database" in the world directory. Player can use new chat command "/showbones" to
|
||||
show waypoints that are visible anywhere in world showing the
|
||||
direction and distance to all recorded bones up to the server
|
||||
limit (3 by default). Waypoints are removed and updated as player, or other
|
||||
players dig them. If player is online when another player digs
|
||||
thier bones, a chat message will appear letting him/her know of
|
||||
the crime. :)
|
||||
|
||||
If a player has left more than the server limit (default 3) of bones lying
|
||||
around the world, the oldest ones are removed from the world as
|
||||
the new one is created. Waypoints are numbered 1 - server limit.
|
||||
The newest/latest bones would be 1. Bones waypoints may be hidden
|
||||
by using the /showbones chat command again.
|
||||
|
||||
This mod was created in hopes relieving the frusteration of players and
|
||||
admins trying to locate lost bones. There is also the added bonus that
|
||||
server admins will no longer need to clean up messy, discarded bones from
|
||||
all around the server. This mod will only track bones lost from the time
|
||||
of install. It also will not track bones placed from inventory.
|
||||
|
||||
License: Source code LGPL 2.1
|
||||
Credits: PilzAdam - The creator of the bones mod.
|
||||
Some code copied (on_punch function) for a needed override.
|
||||
|
||||
Adds chat command: /showbones
|
||||
Adds privilege: None at this time
|
||||
|
||||
Dependencies:
|
||||
bones
|
||||
|
||||
Forum link: To be announced
|
||||
Known bugs: To be announced when discovered.
|
||||
|
||||
Code quality: I don't want to talk about it. I'm completely new at lua.
|
||||
|
||||
|
||||
|
||||
License of source code
|
||||
----------------------
|
||||
Copyright (C) 2016 ExeterDad
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms
|
||||
of the GNU Lesser General Public License as published by the Free Software Foundation;
|
||||
either version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details:
|
||||
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
|
|
@ -0,0 +1 @@
|
|||
bones
|
|
@ -0,0 +1,2 @@
|
|||
A mod that saves bones positions in a "database".
|
||||
Using chatcommand /showbones will reveal visual waypoints of bones locations with distance to simplify recovery.
|
|
@ -0,0 +1,321 @@
|
|||
local showbones_temp = {} -- Stores temporary player data (persists until player leaves)
|
||||
|
||||
if not minetest.global_exists("showbones") then
|
||||
showbones = {
|
||||
modname = "Showbones",
|
||||
showbones_limit = 3, -- How many bones a player may have on the server until pruned.
|
||||
datafile = minetest.get_worldpath() .."/showbones.db",
|
||||
}
|
||||
end
|
||||
|
||||
-- Loads entire showbones database
|
||||
|
||||
function showbones.db_load()
|
||||
local file = io.open(showbones.datafile, "r")
|
||||
print("Reading from database")
|
||||
if file then
|
||||
local temp_table = minetest.deserialize(file:read("*all"))
|
||||
file:close()
|
||||
if type(temp_table) == "table" then
|
||||
return temp_table
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Merges new data with stored data and saves to db
|
||||
|
||||
function showbones.db_save(data)
|
||||
local orig_db = showbones.db_load() or {} -- load old db data
|
||||
local file = io.open(showbones.datafile, "w") -- open db for write
|
||||
if file then
|
||||
if type(data) == "table" then
|
||||
for k, v in pairs(data) do -- add new to old
|
||||
orig_db[k] = data[k]
|
||||
end
|
||||
data = orig_db
|
||||
end
|
||||
file:write(minetest.serialize(data))
|
||||
file:close()
|
||||
print("Writing to database")
|
||||
end
|
||||
end
|
||||
|
||||
function showbones.is_joined_player(player_name)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
if not player then
|
||||
return false, "Player not logged in"
|
||||
else
|
||||
return true, "Player is logged in"
|
||||
end
|
||||
end
|
||||
-- called from on_die_player, or bones:bones when bones dug
|
||||
function showbones.update_bones_locations(pos, player_name)
|
||||
local player_table = showbones.get_player_table(player_name)
|
||||
local bones_locations = player_table.bones_locations
|
||||
|
||||
if table.getn(bones_locations) >= showbones.showbones_limit then
|
||||
print(player_name .. " has too many bones! Pruning")
|
||||
local count = table.getn(bones_locations)
|
||||
while table.getn(bones_locations) >= showbones.showbones_limit do
|
||||
local prunepos = bones_locations[count]
|
||||
|
||||
minetest.set_node(prunepos, {name="air"})
|
||||
bones_locations[count] = nil
|
||||
bones_locations = bones_locations
|
||||
prunepos = nil
|
||||
count = count-1
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(bones_locations, 1, pos) -- add current pos to stored pos's if they are there.
|
||||
player_table.bones_locations = bones_locations -- update with new bones and also pruned
|
||||
return player_table
|
||||
|
||||
end
|
||||
|
||||
function showbones.get_player_table(player_name) -- grabs player table by passing a player_name
|
||||
if showbones_temp[player_name] then
|
||||
local player_table = showbones_temp[player_name]
|
||||
return player_table
|
||||
else
|
||||
local showbones_db = showbones.db_load() or {}
|
||||
local player_table = showbones_db[player_name] or {}
|
||||
player_table = {
|
||||
hud={},
|
||||
togglehud = "off",
|
||||
bones_locations = player_table["bones_locations"] or {}
|
||||
}
|
||||
return player_table -- return created player db entry
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function showbones.announce_bones(pos, player_name)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "bones:bones" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("showbones_owner", player_name)
|
||||
print(player_name .. " died and left us bones! " .. minetest.pos_to_string(pos))
|
||||
return pos
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function showbones.hide_hud(player_name) -- removes showbones waypoints and togglehud = "off"
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
showbones_temp[player_name] = showbones.get_player_table(player_name)
|
||||
|
||||
for i = 1, showbones.showbones_limit do
|
||||
if showbones_temp[player_name]["hud"][i] then
|
||||
player:hud_remove(i)
|
||||
showbones_temp[player_name]["hud"][i] = nil
|
||||
end
|
||||
end
|
||||
showbones_temp[player_name]["togglehud"] = "off"
|
||||
end
|
||||
-- Creates one Bones waypoint
|
||||
function showbones.update_hud(bones_locations, i, player_name)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
local pos = bones_locations[i]
|
||||
if not pos then
|
||||
return
|
||||
end
|
||||
local name = "Your Bones #".. i .. " " .. minetest.pos_to_string(pos)
|
||||
showbones_temp[player_name].hud[i] = player:hud_add({
|
||||
hud_elem_type = "waypoint",
|
||||
number = 0xffff00, -- yellow text
|
||||
name = name,
|
||||
text = " nodes away",
|
||||
world_pos = pos
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
function showbones.show_hud(player_name)
|
||||
showbones_temp[player_name] = showbones.get_player_table(player_name)
|
||||
-- make a copy bones_locations to simplify
|
||||
local bones_locations = showbones_temp[player_name]["bones_locations"]
|
||||
local total_bones_locations = table.getn(bones_locations)
|
||||
-- go through pos's and build a waypoint for each
|
||||
for i = 1, showbones.showbones_limit do
|
||||
showbones.update_hud(bones_locations, i, player_name)
|
||||
end
|
||||
showbones_temp[player_name]["togglehud"] = "on"
|
||||
|
||||
local message = ""
|
||||
if total_bones_locations == 0 then
|
||||
message = "[".. showbones.modname .. "] No bones waypoints to show."
|
||||
showbones_temp[player_name]["togglehud"] = "off"
|
||||
elseif total_bones_locations >= 1 and total_bones_locations < showbones.showbones_limit then
|
||||
message = "[".. showbones.modname .. "] Your Bones are now shown as " .. total_bones_locations .. " waypoints."
|
||||
elseif total_bones_locations >= showbones.showbones_limit then
|
||||
message = "[".. showbones.modname .. "] Your Bones are now shown as " .. total_bones_locations .. " waypoints.\nUnclaimed Bones beyond " .. showbones.showbones_limit .. " will be automatically removed from world."
|
||||
end
|
||||
|
||||
minetest.chat_send_player(player_name, message)
|
||||
return true, ""
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("showbones", {
|
||||
params = "",
|
||||
description = "Show wayoint markers of bones location(s).",
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
|
||||
if not player then
|
||||
return false, "Player not found"
|
||||
end
|
||||
|
||||
local player_name = name
|
||||
-- toggle off until turned on
|
||||
if showbones_temp[player_name] and showbones_temp[player_name]["togglehud"] == "on" then
|
||||
showbones.hide_hud(player_name)
|
||||
minetest.chat_send_player(player_name, "[".. showbones.modname .. "] Bones waypoints now hidden")
|
||||
elseif showbones_temp[player_name]["togglehud"] == "off" then
|
||||
showbones.show_hud(player_name)
|
||||
end
|
||||
|
||||
end,
|
||||
})
|
||||
|
||||
function showbones.clear_bones_pos(player_name, pos)
|
||||
showbones_temp[player_name] = showbones.get_player_table(player_name)
|
||||
local bones_locations = showbones_temp[player_name]["bones_locations"]
|
||||
for k, v in pairs(bones_locations) do -- add new to old
|
||||
-- find match of pos and remove it.
|
||||
if v.x == pos.x and v.y == pos.y and v.z == pos.z then
|
||||
bones_locations[k] = nil
|
||||
end
|
||||
end
|
||||
showbones_temp[player_name]["bones_locations"] = bones_locations
|
||||
end
|
||||
|
||||
function showbones.bones_removed(pos, player) -- called by bones:bones on_punch
|
||||
local bones_breaker = player:get_player_name()
|
||||
local showbones_owner = minetest.get_meta(pos):get_string("showbones_owner")
|
||||
if showbones_owner == bones_breaker then -- bones dug by owner
|
||||
showbones.clear_bones_pos(bones_breaker, pos)
|
||||
local player_name = bones_breaker
|
||||
if showbones_temp[player_name]["togglehud"] == "on" then
|
||||
showbones.hide_hud(player_name)
|
||||
showbones.show_hud(player_name)
|
||||
end
|
||||
else -- not dug by owner
|
||||
if showbones.is_joined_player(showbones_owner) then -- owner is online
|
||||
local player = minetest.get_player_by_name(showbones_owner) -- switch to owner player
|
||||
local player_name = player:get_player_name()
|
||||
showbones.clear_bones_pos(player_name, pos)
|
||||
-- TODO? make list of random chat messages to owner. Might get some drama going :)
|
||||
minetest.chat_send_player(player_name, "[Showbones Mod] " .. bones_breaker .. " just dug your bones!")
|
||||
if showbones_temp[player_name]["togglehud"] == "on" then -- online owner has showbones waypoints active. Need to reset
|
||||
showbones.hide_hud(player_name)
|
||||
showbones.show_hud(player_name)
|
||||
end
|
||||
else -- owner is not online. Remove pos and save for him.
|
||||
showbones.clear_bones_pos(showbones_owner, pos)
|
||||
showbones.save_player_table(player_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function showbones.save_player_table(player_name)
|
||||
showbones_temp[player_name]["hud"] = nil
|
||||
showbones_temp[player_name]["togglehud"] = nil
|
||||
showbones.db_save(showbones_temp)
|
||||
showbones_temp[player_name] = nil -- unset showbones_temp player to save memory.
|
||||
if not showbones_temp[player_name] then
|
||||
print("[" .. showbones.modname .. "] Saved " .. player_name .. "'s data, and cleared from memory.")
|
||||
end
|
||||
end
|
||||
---------------------------------------------
|
||||
-- CALLBACKS --------------------------------
|
||||
---------------------------------------------
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local player_name = player:get_player_name()
|
||||
showbones_temp[player_name] = showbones.get_player_table(player_name)
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player) -- unset "togglehud", "hud" and save in db
|
||||
local player_name = player:get_player_name()
|
||||
showbones.save_player_table(player_name)
|
||||
end)
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
for id in pairs(showbones_temp) do
|
||||
showbones_temp[id]["hud"] = nil
|
||||
showbones_temp[id]["togglehud"] = nil
|
||||
end
|
||||
showbones.db_save(showbones_temp)
|
||||
print("[" .. showbones.modname .. "] Server shutting down, saved " .. showbones.modname .. " all player(s) data to db file.")
|
||||
showbones_temp = nil
|
||||
end)
|
||||
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
local player_name = player:get_player_name()
|
||||
if minetest.setting_getbool("creative_mode") then -- in creative, no chance of bones, bail
|
||||
return
|
||||
end
|
||||
|
||||
local pos = player:getpos()
|
||||
pos.x = math.floor(pos.x+0.5)
|
||||
pos.y = math.floor(pos.y+0.5)
|
||||
pos.z = math.floor(pos.z+0.5)
|
||||
|
||||
pos = showbones.announce_bones(pos, player_name) -- announce bones if created
|
||||
|
||||
if pos then
|
||||
showbones.hide_hud(player_name) -- turn off hud or waypoints will be out of sync
|
||||
showbones_temp[player_name] = showbones.update_bones_locations(pos, player_name)
|
||||
end
|
||||
|
||||
|
||||
end)
|
||||
|
||||
local function is_owner(pos, name) -- need for below bones:bones on_punch override. Copied from bones:bones
|
||||
local owner = minetest.get_meta(pos):get_string("owner")
|
||||
if owner == "" or owner == name or minetest.check_player_privs(name, "protection_bypass") then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
minetest.override_item("bones:bones", { -- almost all on_punch copied from bones:bones for override.
|
||||
on_punch = function(pos, node, player)
|
||||
if(not is_owner(pos, player:get_player_name())) then
|
||||
return
|
||||
end
|
||||
|
||||
if(minetest.get_meta(pos):get_string("infotext") == "") then
|
||||
return
|
||||
end
|
||||
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local player_inv = player:get_inventory()
|
||||
local has_space = true
|
||||
|
||||
for i=1,inv:get_size("main") do
|
||||
local stk = inv:get_stack("main", i)
|
||||
if player_inv:room_for_item("main", stk) then
|
||||
inv:set_stack("main", i, nil)
|
||||
player_inv:add_item("main", stk)
|
||||
else
|
||||
has_space = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- remove bones if player emptied them
|
||||
if has_space then
|
||||
if player_inv:room_for_item("main", {name = "bones:bones"}) then
|
||||
player_inv:add_item("main", {name = "bones:bones"})
|
||||
else
|
||||
minetest.add_item(pos,"bones:bones")
|
||||
end
|
||||
showbones.bones_removed(pos, player) -- only thing added to this override.
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
end,
|
||||
})
|
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
Loading…
Reference in New Issue