170 lines
5.7 KiB
Lua
170 lines
5.7 KiB
Lua
local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200
|
|
|
|
local function serializeContents(contents)
|
|
if not contents then return "" end
|
|
|
|
local tabs = {}
|
|
for i, stack in ipairs(contents) do
|
|
tabs[i] = stack and stack:to_table() or ""
|
|
end
|
|
|
|
return minetest.serialize(tabs)
|
|
end
|
|
|
|
local function deserializeContents(data)
|
|
if not data or data == "" then return nil end
|
|
local tabs = minetest.deserialize(data)
|
|
if not tabs or type(tabs) ~= "table" then return nil end
|
|
|
|
local contents = {}
|
|
for i, tab in ipairs(tabs) do
|
|
contents[i] = ItemStack(tab)
|
|
end
|
|
|
|
return contents
|
|
end
|
|
|
|
minetest.register_entity("bones_entity:entity", {
|
|
hp_max = 1,
|
|
physical = false,
|
|
weight = 5,
|
|
collisionbox = {-0.3, -1, -0.3, 0.3, -.4, 0.3},
|
|
visual = "mesh",
|
|
mesh = "character.b3d",
|
|
textures = {"invisible.png"},
|
|
is_visible = true,
|
|
makes_footstep_sound = false,
|
|
automatic_rotate = false,
|
|
on_activate = function(self, staticdata, dtime_s)
|
|
if not self.owner then
|
|
local deserialized = minetest.deserialize(staticdata)
|
|
if deserialized then
|
|
self.inv = deserializeContents(deserialized.inv)
|
|
if deserialized.owner then
|
|
self.owner = deserialized.owner
|
|
end
|
|
if deserialized.expiretime then
|
|
self.time = deserialized.expiretime
|
|
if self.time < os.time() then
|
|
self.object:set_properties({infotext = self.owner.."'s old bones"})
|
|
else
|
|
self.object:set_properties({infotext = self.owner.."'s fresh bones"})
|
|
minetest.after(self.time-os.time(), function(self)
|
|
self.object:set_properties({infotext = self.owner.."'s old bones"})
|
|
end, self)
|
|
end
|
|
end
|
|
local inv = minetest.create_detached_inventory("bones_"..self.owner, {})
|
|
inv:set_size("main", 8 * 6)
|
|
inv:set_list("main",self.inv)
|
|
if inv:is_empty("main") then
|
|
self.object:remove()
|
|
end
|
|
end
|
|
self.object:set_armor_groups({immortal = 1})
|
|
if deserialized.mesh and deserialized.textures and deserialized.yaw then
|
|
self.mesh = deserialized.mesh
|
|
self.textures = deserialized.textures
|
|
self.yaw = deserialized.yaw
|
|
self.object:set_properties({mesh = deserialized.mesh, textures = deserialized.textures})
|
|
self.object:set_yaw(deserialized.yaw)
|
|
self.object:set_animation({x=162,y=167}, 1)
|
|
end
|
|
end
|
|
end,
|
|
get_staticdata = function(self)
|
|
return minetest.serialize({owner = self.owner, expiretime = self.time, mesh = self.mesh, textures = self.textures, yaw = self.yaw, inv = serializeContents(self.inv)})
|
|
end,
|
|
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
|
|
local name = puncher:get_player_name()
|
|
if name ~= self.owner and self.time > os.time() and not minetest.check_player_privs(name, "protection_bypass") then return end
|
|
|
|
local player_inv = puncher:get_inventory()
|
|
local has_space = true
|
|
local inv = minetest.create_detached_inventory("bones_"..self.owner, {})
|
|
inv:set_size("main", 8 * 6)
|
|
inv:set_list("main",self.inv)
|
|
--The MIT License (MIT) (Following 12 lines)
|
|
--Copyright (C) 2012-2016 PilzAdam
|
|
--Copyright (C) 2012-2016 Various Minetest developers and contributors
|
|
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
|
|
self.object:remove()
|
|
else
|
|
self.inv = inv:get_list("main")
|
|
end
|
|
end,
|
|
on_rightclick = function(self, clicker)
|
|
local name = clicker:get_player_name()
|
|
local inventory = minetest.create_detached_inventory("bones_"..name, {
|
|
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
|
return 0
|
|
end,
|
|
allow_put = function(inv, listname, index, stack, player)
|
|
return 0
|
|
end,
|
|
allow_take = function(inv, listname, index, stack, player)
|
|
local name = player:get_player_name()
|
|
if name == self.owner or self.time < os.time() or minetest.check_player_privs(name, "protection_bypass") then
|
|
return stack:get_count()
|
|
end
|
|
return 0
|
|
end,
|
|
on_take = function(inv, listname, index, stack, player)
|
|
self.inv = inv:get_list("main")
|
|
if inv:is_empty("main") then
|
|
self.object:remove()
|
|
end
|
|
end,
|
|
})
|
|
inventory:set_size("main", 48)
|
|
local templist = table.copy(self.inv)
|
|
inventory:set_list("main", templist)
|
|
local formspec =
|
|
"size[12,9]"..
|
|
"list[detached:bones_"..name..";main;0,0;12,4;]"..
|
|
"list[current_player;main;2,5;8,4;]"
|
|
minetest.show_formspec(name, "bones_inv", formspec)
|
|
end
|
|
})
|
|
minetest.register_on_dieplayer(function(player)
|
|
local pos = player:get_pos()
|
|
local player_inv = player:get_inventory()
|
|
if player_inv:is_empty("main") and
|
|
player_inv:is_empty("craft") then
|
|
return
|
|
end
|
|
local inv = minetest.create_detached_inventory("bones_"..player:get_player_name(), {})
|
|
--The MIT License (MIT) (Following 14 lines)
|
|
--Copyright (C) 2012-2016 PilzAdam
|
|
--Copyright (C) 2012-2016 Various Minetest developers and contributors
|
|
inv:set_size("main", 8 * 6)
|
|
inv:set_list("main", player_inv:get_list("main"))
|
|
|
|
for i = 1, player_inv:get_size("craft") do
|
|
local stack = player_inv:get_stack("craft", i)
|
|
if inv:room_for_item("main", stack) then
|
|
inv:add_item("main", stack)
|
|
else
|
|
--drop if no space left
|
|
drop(pos, stack)
|
|
end
|
|
end
|
|
pos.y = pos.y + 1
|
|
local props = player:get_properties()
|
|
local yaw = player:get_look_horizontal()
|
|
local e = minetest.add_entity(pos, "bones_entity:entity", minetest.serialize({owner = player:get_player_name(), expiretime = os.time() + share_bones_time, mesh = props.mesh, textures = props.textures, yaw = yaw, inv = serializeContents(inv:get_list("main"))}))
|
|
|
|
player_inv:set_list("main", {})
|
|
player_inv:set_list("craft", {})
|
|
end) |