First commit from local files.

master
ExeterDad 2016-09-03 13:31:31 -04:00
commit c264d75d07
5 changed files with 377 additions and 0 deletions

53
README.txt Normal file
View File

@ -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

1
depends.txt Normal file
View File

@ -0,0 +1 @@
bones

2
description.txt Normal file
View File

@ -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.

321
init.lua Normal file
View File

@ -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,
})

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB