forked from minetest/minetest_game
Improve Chest appearance - opening chests.
Adds a mesh model that appears when a chest is opened. The chest stays visibly open as long as the player keeps it open. When the player closes the formspec, the chest returns back to the closed shape. While opening and closing, a sound plays. A second person inspecting the chest will trigger a second sound open. However, only after the last player closes the chest, does the chest actually visually close and is the sound close played. This keeps mesh updates to a minimum. While it's possible that a server shutting down may cause chests to remain open, this does not affect the chests' working matter, and opening or closing them should fix them. Old chests are converted to the new style by LBM. I previously had them converted on open but this was unreliable, and LBMs don't have that problem. Open chests cannot be dug up. This prevents people from keeping a chest open and digging it out as well, since closing a chest would place a chest back (swap) at the spot. We could protect against this, but it still messes up the client and causes a lot of "missing node inventory" error messages otherwise. It's unlikely but possible that a player lagging out causes a chest to stay "open" and thus unremovable by digging, but there are other ways of dealing with that - a server restart fixes that issue. If the lid of the chest is obstructed, the sounds continue to play, but the lid isn't opened. Obstructed means that a node is present above the chest lid, however, we ignore several node types like signs, torches (not 3d) and wallmounted nodeboxes (typically signs) since they don't pose any major obstruction in almost any case, and are typically found above chests. Additionally, the selection box of the opened chest does not include the lid, and so one can still interact with e.g. a sign behind an open lid. Due to the fact that chests now have 7+ textures, we can no longer use materials (limit: 6) to texture the chest, and so there is now a single UV mapped image that applies both to open and closed chests. While this does mean texture pack makers need to create it, this is extremely simple and consists of a simple cut'n'paste over the template and should be really easy to do. Only one texture file is now then used for both open and closed chests.
This commit is contained in:
parent
4ec0fd974b
commit
011ad78b42
@ -154,6 +154,9 @@ sofar (CC BY-SA 3.0):
|
||||
default_aspen_tree
|
||||
default_aspen_tree_top, derived from default_pine_tree_top (by paramat)
|
||||
default_aspen_wood, derived from default_pine_wood (by paramat)
|
||||
default_chest_wood, default_chest_wood_locked derived from default_chest_* textures by BlockMen
|
||||
|
||||
sofar (WTFPL):
|
||||
default_gravel.png -- Derived from Gambit's PixelBOX texture pack light gravel
|
||||
|
||||
Neuromancer (CC BY-SA 2.0):
|
||||
@ -285,3 +288,13 @@ https://www.freesound.org/people/AGFX/packs/1253/
|
||||
blukotek (CC0 1.0)
|
||||
https://www.freesound.org/people/blukotek/sounds/251660/
|
||||
default_dig_snappy.ogg
|
||||
|
||||
Chests sounds added by sofar, derived of several files mixed together:
|
||||
default_chest_open.ogg
|
||||
default_chest_close.ogg
|
||||
- http://www.freesound.org/people/Sevin7/sounds/269722/ CC0
|
||||
- http://www.freesound.org/people/Percy%20Duke/sounds/23448/ CC-BY-3.0
|
||||
- http://www.freesound.org/people/kingsamas/sounds/135576/ CC-BY-3.0
|
||||
- http://www.freesound.org/people/bulbastre/sounds/126887/ CC-BY-3.0
|
||||
- http://www.freesound.org/people/Yoyodaman234/sounds/183541/ CC0
|
||||
|
||||
|
82
mods/default/models/chest_open.obj
Normal file
82
mods/default/models/chest_open.obj
Normal file
@ -0,0 +1,82 @@
|
||||
# Blender v2.76 (sub 0) OBJ File: 'chest_open.blend'
|
||||
# www.blender.org
|
||||
mtllib chest_open.mtl
|
||||
o Bottom_Cube.001
|
||||
v -0.500000 -0.500000 0.500000
|
||||
v -0.500000 0.187500 0.500000
|
||||
v -0.500000 -0.500000 -0.500000
|
||||
v -0.500000 0.187500 -0.500000
|
||||
v 0.500000 -0.500000 0.500000
|
||||
v 0.500000 0.187500 0.500000
|
||||
v 0.500000 -0.500000 -0.500000
|
||||
v 0.500000 0.187500 -0.500000
|
||||
vt 0.750000 0.343750
|
||||
vt 0.500000 0.343750
|
||||
vt 0.500000 0.000000
|
||||
vt 0.750000 0.000000
|
||||
vt 0.250000 0.343750
|
||||
vt 0.250000 0.000000
|
||||
vt 0.000000 0.343750
|
||||
vt 0.000000 0.000000
|
||||
vt 0.750000 0.875000
|
||||
vt 0.500000 0.875000
|
||||
vt 0.500000 0.500000
|
||||
vt 0.750000 0.500000
|
||||
vt 0.250000 0.500000
|
||||
vt 0.250000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.500000
|
||||
vt 1.000000 0.500000
|
||||
vt 1.000000 0.000000
|
||||
vn -1.000000 0.000000 0.000000
|
||||
vn 0.000000 0.000000 -1.000000
|
||||
vn 1.000000 0.000000 0.000000
|
||||
vn 0.000000 0.000000 1.000000
|
||||
vn 0.000000 -1.000000 0.000000
|
||||
vn 0.000000 1.000000 0.000000
|
||||
usemtl None
|
||||
s off
|
||||
f 2/1/1 4/2/1 3/3/1 1/4/1
|
||||
f 4/2/2 8/5/2 7/6/2 3/3/2
|
||||
f 8/5/3 6/7/3 5/8/3 7/6/3
|
||||
f 6/9/4 2/10/4 1/11/4 5/12/4
|
||||
f 1/13/5 3/14/5 7/15/5 5/16/5
|
||||
f 6/4/6 8/12/6 4/17/6 2/18/6
|
||||
o Top_Cube.002
|
||||
v -0.499900 0.187501 0.499900
|
||||
v -0.499900 0.408471 0.720970
|
||||
v -0.499900 0.894607 -0.207108
|
||||
v -0.499900 1.115578 0.013863
|
||||
v 0.499900 0.187501 0.499900
|
||||
v 0.499900 0.408471 0.720970
|
||||
v 0.499900 0.894607 -0.207108
|
||||
v 0.499900 1.115578 0.013863
|
||||
vt 0.750000 0.500000
|
||||
vt 0.500000 0.500000
|
||||
vt 0.500000 0.343750
|
||||
vt 0.750000 0.343750
|
||||
vt 0.250000 0.500000
|
||||
vt 0.250000 0.343750
|
||||
vt 0.000000 0.500000
|
||||
vt 0.000000 0.343750
|
||||
vt 0.750000 1.000000
|
||||
vt 0.500000 1.000000
|
||||
vt 0.500000 0.843750
|
||||
vt 0.750000 0.843750
|
||||
vt 1.000000 0.500000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.250000 1.000000
|
||||
vn -1.000000 0.000000 0.000000
|
||||
vn 0.000000 0.707100 -0.707100
|
||||
vn 1.000000 0.000000 0.000000
|
||||
vn 0.000000 -0.707100 0.707100
|
||||
vn 0.000000 -0.707100 -0.707100
|
||||
vn 0.000000 0.707100 0.707100
|
||||
usemtl None
|
||||
s off
|
||||
f 10/19/7 12/20/7 11/21/7 9/22/7
|
||||
f 12/20/8 16/23/8 15/24/8 11/21/8
|
||||
f 16/23/9 14/25/9 13/26/9 15/24/9
|
||||
f 14/27/10 10/28/10 9/29/10 13/30/10
|
||||
f 9/31/11 11/32/11 15/27/11 13/19/11
|
||||
f 14/33/12 16/23/12 12/20/12 10/28/12
|
38
mods/default/models/cube.obj
Normal file
38
mods/default/models/cube.obj
Normal file
@ -0,0 +1,38 @@
|
||||
# Blender v2.76 (sub 0) OBJ File: 'chest_close.blend'
|
||||
# www.blender.org
|
||||
mtllib chest_close.mtl
|
||||
o Cube_Cube.001
|
||||
v -0.500000 -0.500000 0.500000
|
||||
v -0.500000 0.500000 0.500000
|
||||
v -0.500000 -0.500000 -0.500000
|
||||
v -0.500000 0.500000 -0.500000
|
||||
v 0.500000 -0.500000 0.500000
|
||||
v 0.500000 0.500000 0.500000
|
||||
v 0.500000 -0.500000 -0.500000
|
||||
v 0.500000 0.500000 -0.500000
|
||||
vt 0.750000 0.500000
|
||||
vt 0.500000 0.500000
|
||||
vt 0.500000 -0.000000
|
||||
vt 0.750000 0.000000
|
||||
vt 0.250000 0.500000
|
||||
vt 0.250000 0.000000
|
||||
vt 0.000000 0.500000
|
||||
vt -0.000000 0.000000
|
||||
vt 0.750000 1.000000
|
||||
vt 0.500000 1.000000
|
||||
vt 0.250000 1.000000
|
||||
vt -0.000000 1.000000
|
||||
vn -1.000000 0.000000 0.000000
|
||||
vn 0.000000 0.000000 -1.000000
|
||||
vn 1.000000 0.000000 0.000000
|
||||
vn 0.000000 0.000000 1.000000
|
||||
vn 0.000000 -1.000000 0.000000
|
||||
vn 0.000000 1.000000 0.000000
|
||||
usemtl None
|
||||
s off
|
||||
f 2/1/1 4/2/1 3/3/1 1/4/1
|
||||
f 4/2/2 8/5/2 7/6/2 3/3/2
|
||||
f 8/5/3 6/7/3 5/8/3 7/6/3
|
||||
f 6/9/4 2/10/4 1/2/4 5/1/4
|
||||
f 1/5/5 3/11/5 7/12/5 5/7/5
|
||||
f 6/11/6 8/5/6 4/2/6 2/10/6
|
@ -1766,188 +1766,276 @@ minetest.register_node("default:lava_flowing", {
|
||||
-- Tools / "Advanced" crafting / Non-"natural"
|
||||
--
|
||||
|
||||
local chest_formspec =
|
||||
"size[8,9]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"list[current_name;main;0,0.3;8,4;]" ..
|
||||
"list[current_player;main;0,4.85;8,1;]" ..
|
||||
"list[current_player;main;0,6.08;8,3;8]" ..
|
||||
"listring[current_name;main]" ..
|
||||
"listring[current_player;main]" ..
|
||||
default.get_hotbar_bg(0,4.85)
|
||||
|
||||
local function get_locked_chest_formspec(pos)
|
||||
local function get_chest_formspec(pos)
|
||||
local spos = pos.x .. "," .. pos.y .. "," .. pos.z
|
||||
local formspec =
|
||||
"size[8,9]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"list[nodemeta:" .. spos .. ";main;0,0.3;8,4;]" ..
|
||||
"list[nodemeta:" .. spos .. ";default:chest;0,0.3;8,4;]" ..
|
||||
"list[current_player;main;0,4.85;8,1;]" ..
|
||||
"list[current_player;main;0,6.08;8,3;8]" ..
|
||||
"listring[nodemeta:" .. spos .. ";main]" ..
|
||||
"listring[nodemeta:" .. spos .. ";default:chest]" ..
|
||||
"listring[current_player;main]" ..
|
||||
default.get_hotbar_bg(0,4.85)
|
||||
return formspec
|
||||
return formspec
|
||||
end
|
||||
|
||||
minetest.register_node("default:chest", {
|
||||
description = "Chest",
|
||||
tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
|
||||
"default_chest_side.png", "default_chest_side.png", "default_chest_front.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2},
|
||||
legacy_facedir_simple = true,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
local function chest_lid_obstructed(pos)
|
||||
local above = { x = pos.x, y = pos.y + 1, z = pos.z }
|
||||
local def = minetest.registered_nodes[minetest.get_node(above).name]
|
||||
-- allow ladders, signs, wallmounted things and torches to not obstruct
|
||||
if def.drawtype == "airlike" or
|
||||
def.drawtype == "signlike" or
|
||||
def.drawtype == "torchlike" or
|
||||
(def.drawtype == "nodebox" and def.paramtype2 == "wallmounted") then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", chest_formspec)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 8*4)
|
||||
end,
|
||||
can_dig = function(pos,player)
|
||||
local meta = minetest.get_meta(pos);
|
||||
local inv = meta:get_inventory()
|
||||
return inv:is_empty("main")
|
||||
end,
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index,
|
||||
local open_chests = {}
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= "default:chest" then
|
||||
return
|
||||
end
|
||||
if not fields.quit then
|
||||
return
|
||||
end
|
||||
local pn = player:get_player_name()
|
||||
|
||||
local pos = open_chests[pn].pos
|
||||
local sound = open_chests[pn].sound
|
||||
local swap = open_chests[pn].swap
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
open_chests[pn] = nil
|
||||
for k, v in pairs(open_chests) do
|
||||
if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then
|
||||
return true
|
||||
end
|
||||
end
|
||||
minetest.after(0.2, minetest.swap_node, pos, { name = "default:" .. swap,
|
||||
param2 = node.param2 })
|
||||
minetest.sound_play(sound, {gain = 0.3, pos = pos, max_hear_distance = 10})
|
||||
return true
|
||||
end)
|
||||
|
||||
function default.register_chest(name, d)
|
||||
local def = table.copy(d)
|
||||
def.drawtype = "mesh"
|
||||
def.visual = "mesh"
|
||||
def.paramtype = "light"
|
||||
def.paramtype2 = "facedir"
|
||||
def.legacy_facedir_simple = true
|
||||
def.is_ground_content = false
|
||||
|
||||
if def.protected then
|
||||
def.on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Locked Chest")
|
||||
meta:set_string("owner", "")
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("default:chest", 8*4)
|
||||
end
|
||||
def.after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", placer:get_player_name() or "")
|
||||
meta:set_string("infotext", "Locked Chest (owned by " ..
|
||||
meta:get_string("owner") .. ")")
|
||||
end
|
||||
def.can_dig = function(pos,player)
|
||||
local meta = minetest.get_meta(pos);
|
||||
local inv = meta:get_inventory()
|
||||
return inv:is_empty("default:chest") and
|
||||
default.can_interact_with_node(player, pos)
|
||||
end
|
||||
def.allow_metadata_inventory_move = function(pos, from_list, from_index,
|
||||
to_list, to_index, count, player)
|
||||
if not default.can_interact_with_node(player, pos) then
|
||||
return 0
|
||||
end
|
||||
return count
|
||||
end
|
||||
def.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
if not default.can_interact_with_node(player, pos) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
def.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
if not default.can_interact_with_node(player, pos) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||
if not default.can_interact_with_node(clicker, pos) then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
minetest.sound_play(def.sound_open, {gain = 0.3,
|
||||
pos = pos, max_hear_distance = 10})
|
||||
if not chest_lid_obstructed(pos) then
|
||||
minetest.swap_node(pos,
|
||||
{ name = "default:" .. name .. "_open",
|
||||
param2 = node.param2 })
|
||||
end
|
||||
minetest.after(0.2, minetest.show_formspec,
|
||||
clicker:get_player_name(),
|
||||
"default:chest", get_chest_formspec(pos))
|
||||
open_chests[clicker:get_player_name()] = { pos = pos,
|
||||
sound = def.sound_close, swap = name }
|
||||
end
|
||||
def.on_blast = function() end
|
||||
def.on_key_use = function(pos, player)
|
||||
local secret = minetest.get_meta(pos):get_string("key_lock_secret")
|
||||
local itemstack = player:get_wielded_item()
|
||||
local key_meta = itemstack:get_meta()
|
||||
|
||||
if key_meta:get_string("secret") == "" then
|
||||
key_meta:set_string("secret", minetest.parse_json(itemstack:get_metadata()).secret)
|
||||
itemstack:set_metadata("")
|
||||
end
|
||||
|
||||
if secret ~= key_meta:get_string("secret") then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.show_formspec(
|
||||
player:get_player_name(),
|
||||
"default:chest_locked",
|
||||
get_chest_formspec(pos)
|
||||
)
|
||||
end
|
||||
def.on_skeleton_key_use = function(pos, player, newsecret)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner = meta:get_string("owner")
|
||||
local pn = player:get_player_name()
|
||||
|
||||
-- verify placer is owner of lockable chest
|
||||
if owner ~= pn then
|
||||
minetest.record_protection_violation(pos, pn)
|
||||
minetest.chat_send_player(pn, "You do not own this chest.")
|
||||
return nil
|
||||
end
|
||||
|
||||
local secret = meta:get_string("key_lock_secret")
|
||||
if secret == "" then
|
||||
secret = newsecret
|
||||
meta:set_string("key_lock_secret", secret)
|
||||
end
|
||||
|
||||
return secret, "a locked chest", owner
|
||||
end
|
||||
else
|
||||
def.on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Chest")
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("default:chest", 8*4)
|
||||
end
|
||||
def.can_dig = function(pos,player)
|
||||
local meta = minetest.get_meta(pos);
|
||||
local inv = meta:get_inventory()
|
||||
return inv:is_empty("default:chest")
|
||||
end
|
||||
def.on_rightclick = function(pos, node, clicker)
|
||||
minetest.sound_play(def.sound_open, {gain = 0.3, pos = pos,
|
||||
max_hear_distance = 10})
|
||||
if not chest_lid_obstructed(pos) then
|
||||
minetest.swap_node(pos, {
|
||||
name = "default:" .. name .. "_open",
|
||||
param2 = node.param2 })
|
||||
end
|
||||
minetest.after(0.2, minetest.show_formspec,
|
||||
clicker:get_player_name(),
|
||||
"default:chest", get_chest_formspec(pos))
|
||||
open_chests[clicker:get_player_name()] = { pos = pos,
|
||||
sound = def.sound_close, swap = name }
|
||||
end
|
||||
end
|
||||
|
||||
def.on_metadata_inventory_move = function(pos, from_list, from_index,
|
||||
to_list, to_index, count, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff in chest at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
end
|
||||
def.on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves " .. stack:get_name() ..
|
||||
" to chest at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
end
|
||||
def.on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" takes " .. stack:get_name() ..
|
||||
" from chest at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_blast = function(pos)
|
||||
end
|
||||
def.on_blast = function(pos)
|
||||
local drops = {}
|
||||
default.get_inventory_drops(pos, "main", drops)
|
||||
drops[#drops+1] = "default:chest"
|
||||
minetest.remove_node(pos)
|
||||
return drops
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_node("default:chest_locked", {
|
||||
description = "Locked Chest",
|
||||
tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
|
||||
"default_chest_side.png", "default_chest_side.png", "default_chest_lock.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2},
|
||||
legacy_facedir_simple = true,
|
||||
is_ground_content = false,
|
||||
local def_opened = table.copy(def)
|
||||
local def_closed = table.copy(def)
|
||||
|
||||
def_opened.mesh = "chest_open.obj"
|
||||
def_opened.drop = "default:" .. name
|
||||
def_opened.groups.not_in_creative_inventory = 1
|
||||
def_opened.selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/2, -1/2, -1/2, 1/2, 3/16, 1/2 },
|
||||
}
|
||||
def_opened.can_dig = function()
|
||||
return false
|
||||
end
|
||||
|
||||
def_closed.mesh = "cube.obj"
|
||||
|
||||
minetest.register_node("default:" .. name, def_closed)
|
||||
minetest.register_node("default:" .. name .. "_open", def_opened)
|
||||
|
||||
-- convert old chests to this new variant
|
||||
minetest.register_lbm({
|
||||
label = "update chests to opening chests",
|
||||
name = "default:upgrade_" .. name,
|
||||
nodenames = {"default:" .. name},
|
||||
action = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", nil)
|
||||
local inv = meta:get_inventory()
|
||||
local list = inv:get_list("main")
|
||||
inv:set_list("main", nil)
|
||||
inv:set_size("default:chest", 8*4)
|
||||
inv:set_list("default:chest", list)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
default.register_chest("chest", {
|
||||
description = "Chest",
|
||||
tiles = { "default_chest_wood.png" },
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", placer:get_player_name() or "")
|
||||
meta:set_string("infotext", "Locked Chest (owned by " ..
|
||||
meta:get_string("owner") .. ")")
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", "")
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 8 * 4)
|
||||
end,
|
||||
can_dig = function(pos,player)
|
||||
local meta = minetest.get_meta(pos);
|
||||
local inv = meta:get_inventory()
|
||||
return inv:is_empty("main") and default.can_interact_with_node(player, pos)
|
||||
end,
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index,
|
||||
to_list, to_index, count, player)
|
||||
if not default.can_interact_with_node(player, pos) then
|
||||
return 0
|
||||
end
|
||||
return count
|
||||
end,
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
if not default.can_interact_with_node(player, pos) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
if not default.can_interact_with_node(player, pos) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves " .. stack:get_name() ..
|
||||
" to locked chest at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" takes " .. stack:get_name() ..
|
||||
" from locked chest at " .. minetest.pos_to_string(pos))
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||
if default.can_interact_with_node(clicker, pos) then
|
||||
minetest.show_formspec(
|
||||
clicker:get_player_name(),
|
||||
"default:chest_locked",
|
||||
get_locked_chest_formspec(pos)
|
||||
)
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
on_blast = function() end,
|
||||
on_key_use = function(pos, player)
|
||||
local secret = minetest.get_meta(pos):get_string("key_lock_secret")
|
||||
local itemstack = player:get_wielded_item()
|
||||
local key_meta = itemstack:get_meta()
|
||||
|
||||
if key_meta:get_string("secret") == "" then
|
||||
key_meta:set_string("secret", minetest.parse_json(itemstack:get_metadata()).secret)
|
||||
itemstack:set_metadata("")
|
||||
end
|
||||
|
||||
if secret ~= key_meta:get_string("secret") then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.show_formspec(
|
||||
player:get_player_name(),
|
||||
"default:chest_locked",
|
||||
get_locked_chest_formspec(pos)
|
||||
)
|
||||
end,
|
||||
on_skeleton_key_use = function(pos, player, newsecret)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner = meta:get_string("owner")
|
||||
local name = player:get_player_name()
|
||||
|
||||
-- verify placer is owner of lockable chest
|
||||
if owner ~= name then
|
||||
minetest.record_protection_violation(pos, name)
|
||||
minetest.chat_send_player(name, "You do not own this chest.")
|
||||
return nil
|
||||
end
|
||||
|
||||
local secret = meta:get_string("key_lock_secret")
|
||||
if secret == "" then
|
||||
secret = newsecret
|
||||
meta:set_string("key_lock_secret", secret)
|
||||
end
|
||||
|
||||
return secret, "a locked chest", owner
|
||||
end,
|
||||
sound_open = "default_chest_open",
|
||||
sound_close = "default_chest_close",
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2},
|
||||
})
|
||||
|
||||
default.register_chest("chest_locked", {
|
||||
description = "Locked Chest",
|
||||
tiles = { "default_chest_wood_locked.png" },
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
sound_open = "default_chest_open",
|
||||
sound_close = "default_chest_close",
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2},
|
||||
protected = true,
|
||||
})
|
||||
|
||||
local bookshelf_formspec =
|
||||
"size[8,7;]" ..
|
||||
|
BIN
mods/default/sounds/default_chest_close.ogg
Normal file
BIN
mods/default/sounds/default_chest_close.ogg
Normal file
Binary file not shown.
BIN
mods/default/sounds/default_chest_open.ogg
Normal file
BIN
mods/default/sounds/default_chest_open.ogg
Normal file
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 423 B |
Binary file not shown.
Before Width: | Height: | Size: 469 B |
Binary file not shown.
Before Width: | Height: | Size: 375 B |
Binary file not shown.
Before Width: | Height: | Size: 422 B |
BIN
mods/default/textures/default_chest_wood.png
Normal file
BIN
mods/default/textures/default_chest_wood.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
mods/default/textures/default_chest_wood_locked.png
Normal file
BIN
mods/default/textures/default_chest_wood_locked.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
Loading…
Reference in New Issue
Block a user