--- --Bones --Copyright (C) 2012 Bad_Command -- --This library 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 General Public License for more details. -- --You should have received a copy of the GNU Lesser General Public --License along with this library; if not, write to the Free Software --Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ---- bones.replaceable_node_types = { "default:lava_source", "default:lava_flowing", "default:water_source", "default:water_flowing", "air" } bones.allow_inventory_take = function(pos, listname, index, stack, player) local meta = minetest.env:get_meta(pos) if not bones.privilege(meta, player) then minetest.log("action", player:get_player_name().. " tried to access bones belonging to ".. meta:get_string("owner").." at ".. minetest.pos_to_string(pos)) return 0 end return stack:get_count() end bones.on_inventory_take = function(pos, listname, index, stack, player) local fresh = meta:get_int("fresh") or 1 if fresh > 0 then fresh = "fresh" else fresh = "old" end minetest.log("action", player:get_player_name().. " picks from "..meta:get_string("owner").."'s "..fresh.." bones at "..minetest.pos_to_string(pos)) end bones.privilege=function(meta, player) local name = player:get_player_name() local privs = minetest.get_player_privs(name) if not privs["interact"] then return false end local fresh = meta:get_int("fresh") or 0 if fresh > 0 and name ~= meta:get_string("owner") and not privs["server"] then return false end return true end bones.action=function(pos, node, active_object_count, active_object_count_wider) local meta = minetest.env:get_meta(pos) local fresh = meta:get_int("fresh") or 0 if fresh > 0 then local bonetime = meta:get_float("bonetime") or 0 if worldtime_get() - bonetime > bones.age_after then local name = meta:get_string("owner") or "" meta:set_string("infotext", name .. "'s old bones") meta:set_int("fresh", -1) end end end bones.create = function(player, pos) local name = player:get_player_name() minetest.env:set_node(pos, {name="bones:bones", param1=0, param2=0}) local meta = minetest.env:get_meta(pos) meta:set_string("formspec", "invsize[8,9;]".. "list[current_name;main;0,0;8,4;]".. "list[current_player;main;0,5;8,4;]") meta:set_string("infotext", name .. "'s fresh bones") meta:set_string("owner", name) meta:set_float("bonetime", worldtime_get()) meta:set_int("fresh", 1) -- test to see if node was created local node = minetest.env:get_node_or_nil(pos) if node == nil or node.name ~= "bones:bones" then minetest.log("error", 'Bones: Failed to create bones node for '..name) return false end local bones_inv = meta:get_inventory() bones_inv:set_size("main", 8*4) local player_inv = player:get_inventory() if ( player_inv == nil ) then minetest.log("error", 'Bones: Unable to get player '..name..' inventory') return false end for i=1,32 do local stack = player_inv:get_stack("main", i) if stack ~= nil and not stack:is_empty() then bones_inv:set_stack("main", i, stack:to_table()) player_inv:set_stack("main", i, nil) end end for i=1,9 do local stack = player_inv:get_stack("craft", i) if stack ~= nil and not stack:is_empty() then local leftover = bones_inv:add_item("main", stack) if leftover ~= nil and not leftover:is_empty() then minetest.env:add_item({ x=pos.x, y=pos.y + 1.1, z=pos.z}, leftover) end player_inv:set_stack("craft", i, nil) end end return true end bones.settle_type = function(nodename) for i=1,#bones.replaceable_node_types do if nodename == bones.replaceable_node_types[i] then return true end end return false end bones.on_punch = function(pos, node, player) if node == nil or node.name ~= "bones:bones" then return end local meta = minetest.env:get_meta(pos) local fresh = meta:get_int("fresh") or 0 if fresh == 0 then return end local name = player:get_player_name() if name ~= meta:get_string("owner") then return end local meta = minetest.env:get_meta(pos) local bones_inv = meta:get_inventory() if ( bones_inv == nil ) then return end local player_inv = player:get_inventory() if ( player_inv == nil ) then minetest.log("error", 'Bones: Unable to get player '..name..' inventory') return end for i=1,32 do local stack = bones_inv:get_stack("main", i) if stack ~= nil and not stack:is_empty() then local leftover = player_inv:add_item("main", stack) bones_inv:set_stack("main", i, nil) if leftover ~= nil and not leftover:is_empty() then bones_inv:set_stack("main", i, leftover) else bones_inv:set_stack("main", i, nil) end end end minetest.log("action", name.." unloaded his fresh bones at "..minetest.pos_to_string(pos)) end bones.settle_bones = function(pos) local nextpos = pos; local node -- find ground beneath player repeat pos = nextpos nextpos = {x=pos.x, y=pos.y-1, z=pos.z} node = minetest.env:get_node_or_nil(nextpos) until node == nil or not bones.settle_type(node.name) node = minetest.env:get_node_or_nil(pos) -- if the player is inside rock or something if node == nil or not bones.settle_type(node.name) then -- find nearby empty node pos = minetest.env:find_node_near(pos, 3, bones.replaceable_node_types) end -- if nothing nearby is empty if pos == nil then return nil end return pos;--{x=math.floor(pos.x*10)/10, y=math.floor(pos.y*10)/10, z=math.floor(pos.z*10)/10} end bones.pos_to_string = function(pos) return math.floor(pos.x + 0.5) .. "," .. math.floor(pos.y+0.5) .. "," .. math.floor(pos.z+0.5) end bones.on_dieplayer = function(player) if player == nil then minetest.log("error", 'Unknown player died (player = nil)') return end local name = player:get_player_name() local privs = minetest.get_player_privs(name) local inv = player:get_inventory() if not privs["interact"] or (inv:is_empty("main") and inv:is_empty("craft")) then return end local playerpos = player:getpos() playerpos = { x=math.floor(playerpos.x+0.5), y=math.floor(playerpos.y+0.5), z=math.floor(playerpos.z+0.5) } local bonepos = bones.settle_bones(playerpos); if bonepos == nil then minetest.log("action", player:get_player_name().." dies at "..minetest.pos_to_string(playerpos)..' without dropping gear.') minetest.chat_send_player(name, 'Bones: There was no room to drop your bones. You get to keep your gear.') return else if bones.create(player, bonepos) then minetest.log("action", player:get_player_name().." dies at "..minetest.pos_to_string(playerpos)..', gear dropped at '..minetest.pos_to_string(bonepos)) minetest.chat_send_player(name, 'Bones: Your bones were left at '..bones.pos_to_string(bonepos).. '. Go there to find your gear. Bones stay fresh for '.. (math.floor(bones.age_after/360+0.5)/10)..'hrs.') else minetest.chat_send_player(name, 'Bones: Lucky you! You get to respawn with your bones.') end end end