bones_entity/init.lua
2019-12-03 10:08:16 -06:00

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)