-
-
Save GreenXenith/6e6f075aec63b2b024cea07f7b0af744 to your computer and use it in GitHub Desktop.
Chests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function get_chest_formspec(pos) | |
local spos = pos.x .. "," .. pos.y .. "," .. pos.z | |
local formspec = | |
"size[8.7,10.4;]" .. | |
"background[-0.27,-0.25;9.41,11.48;chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[current_name;main;-0.064,0.5;9,4;]".. | |
"list[current_player;main;-0.064,5.52;9,4;9]".. | |
"list[current_player;main;-0.064,9.745;9,1;]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]" | |
return formspec | |
end | |
local chest_formspec = | |
"size[8.7,10.4;]" .. | |
"background[-0.27,-0.25;9.41,11.48;chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[current_name;main;-0.064,0.5;9,4;]".. | |
"list[current_player;main;-0.064,5.52;9,4;9]".. | |
"list[current_player;main;-0.064,9.745;9,1;]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]" | |
local large_chest_formspec = | |
"size[8.7,12;]" .. | |
"background[-0.27, -0.75;9.41,13.48;large_chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[current_name;main;-0.064,0;9,6;]".. | |
"list[current_player;main;-0.064,7.02;9,4;9]".. | |
"list[current_player;main;-0.064,11.245;9,1;]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]" | |
local function get_chest_neighborpos(pos, param2, side) | |
if side == "right" then | |
if param2 == 0 then | |
return {x=pos.x-1, y=pos.y, z=pos.z} | |
elseif param2 == 1 then | |
return {x=pos.x, y=pos.y, z=pos.z+1} | |
elseif param2 == 2 then | |
return {x=pos.x+1, y=pos.y, z=pos.z} | |
elseif param2 == 3 then | |
return {x=pos.x, y=pos.y, z=pos.z-1} | |
end | |
else | |
if param2 == 0 then | |
return {x=pos.x+1, y=pos.y, z=pos.z} | |
elseif param2 == 1 then | |
return {x=pos.x, y=pos.y, z=pos.z-1} | |
elseif param2 == 2 then | |
return {x=pos.x-1, y=pos.y, z=pos.z} | |
elseif param2 == 3 then | |
return {x=pos.x, y=pos.y, z=pos.z+1} | |
end | |
end | |
end | |
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 | |
local open_chests = {} | |
minetest.register_on_player_receive_fields(function(player, formname, fields) | |
if formname ~= "default:chest" then | |
return | |
end | |
if not player or not fields.quit then | |
return | |
end | |
local pn = player:get_player_name() | |
if not open_chests[pn] then | |
return | |
end | |
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("main", 9*6) | |
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("main") 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 | |
if def.on_construct == nil then | |
def.on_construct = function(pos) | |
local meta = minetest.get_meta(pos) | |
meta:set_string("infotext", "Chest") | |
local inv = meta:get_inventory() | |
inv:set_size("main", 9*6) | |
end | |
else | |
def.on_construct = d.on_construct | |
end | |
if def.can_dig == nil then | |
def.can_dig = function(pos,player) | |
local meta = minetest.get_meta(pos); | |
local inv = meta:get_inventory() | |
return inv:is_empty("main") | |
end | |
else | |
def.can_dig = d._can_dig | |
end | |
if def.on_rightclick == nil then | |
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 | |
else | |
def.on_rightclick = d.on_rightclick | |
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 | |
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 | |
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 | |
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 | |
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 = nil | |
def_closed.drawtype = nil | |
def_closed.tiles[6] = def.tiles[5] -- swap textures around for "normal" | |
def_closed.tiles[5] = def.tiles[3] -- drawtype to make them match the mesh | |
def_closed.tiles[3] = def.tiles[3].."^[transformFX" | |
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 .. "_v2", | |
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("default:chest") | |
if list then | |
inv:set_size("main", 9*6) | |
inv:set_list("main", list) | |
inv:set_list("default:chest", nil) | |
end | |
end | |
}) | |
end | |
default.register_chest("chest", { | |
description = "Chest", | |
tiles = { | |
"default_chest_top.png", | |
"default_chest_top.png", | |
"default_chest_side.png", | |
"default_chest_side.png", | |
"default_chest_front.png", | |
"default_chest_inside.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}, | |
on_construct = function(pos) | |
local param2 = minetest.get_node(pos).param2 | |
local meta = minetest.get_meta(pos) | |
if minetest.get_node(get_chest_neighborpos(pos, param2, "right")).name == "default:chest" then | |
minetest.set_node(pos, {name="default:chest_right",param2=param2}) | |
local p = get_chest_neighborpos(pos, param2, "right") | |
meta:set_string("formspec", | |
"size[8.7,12;]" .. | |
"background[-0.27, -0.75;9.41,13.48;large_chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[nodemeta:"..p.x..","..p.y..","..p.z..";main;-0.064,0;9,6;]".. | |
"list[current_name;main;-0.064,0;9,6;]".. | |
"list[current_player;main;-0.064,7.02;9,4;9]".. | |
"list[current_player;main;-0.064,11.245;9,1;]".. | |
"listring[nodemeta:"..p.x..","..p.y..","..p.z..";main]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]" | |
) | |
minetest.swap_node(p, { name = "default:chest_left", param2 = param2 }) | |
local m = minetest.get_meta(p) | |
m:set_string("formspec", | |
"size[8.7,12;]" .. | |
"background[-0.27, -0.75;9.41,13.48;large_chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[current_name;main;-0.064,0;9,6;]".. | |
"list[nodemeta:"..p.x..","..p.y..","..p.z..";main;-0.064,0;9,6;]".. | |
"list[current_player;main;-0.064,7.02;9,4;9]".. | |
"list[current_player;main;-0.064,11.245;9,1;]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]".. | |
"listring[nodemeta:"..p.x..","..p.y..","..p.z..";main]" | |
) | |
elseif minetest.get_node(get_chest_neighborpos(pos, param2, "left")).name == "default:chest" then | |
minetest.set_node(pos, {name="default:chest_left",param2=param2}) | |
local p = get_chest_neighborpos(pos, param2, "left") | |
meta:set_string("formspec", | |
"size[8.7,12;]" .. | |
"background[-0.27, -0.75;9.41,13.48;large_chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[current_name;main;-0.064,0;9,6;]".. | |
"list[nodemeta:"..p.x..","..p.y..","..p.z..";main;-0.064,0;9,6;]".. | |
"list[current_player;main;-0.064,7.02;9,4;9]".. | |
"list[current_player;main;-0.064,11.245;9,1;]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]".. | |
"listring[nodemeta:"..p.x..","..p.y..","..p.z..";main]" | |
) | |
minetest.swap_node(p, { name = "default:chest_right", param2 = param2 }) | |
local m = minetest.get_meta(p) | |
m:set_string("formspec", | |
"size[8.7,12;]" .. | |
"background[-0.27, -0.75;9.41,13.48;large_chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[nodemeta:"..p.x..","..p.y..","..p.z..";main;-0.064,0;9,6;]".. | |
"list[current_name;main;-0.064,0;9,6;]".. | |
"list[current_player;main;-0.064,7.02;9,4;9]".. | |
"list[current_player;main;-0.064,11.245;9,1;]".. | |
"listring[nodemeta:"..p.x..","..p.y..","..p.z..";main]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]" | |
) | |
else | |
meta:set_string("formspec", | |
"size[8.7,10.4;]" .. | |
"background[-0.27,-0.25;9.41,11.48;chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[current_name;main;-0.064,0.5;9,4;]".. | |
"list[current_player;main;-0.064,5.52;9,4;9]".. | |
"list[current_player;main;-0.064,9.745;9,1;]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]" | |
) | |
end | |
local inv = meta:get_inventory() | |
inv:set_size("main", 9*6) | |
end, | |
after_dig_node = function(pos, oldnode, oldmetadata, digger) | |
local meta = minetest.get_meta(pos) | |
local meta2 = meta | |
meta:from_table(oldmetadata) | |
local inv = meta:get_inventory() | |
for i=1,inv:get_size("main") do | |
local stack = inv:get_stack("main", i) | |
if not stack:is_empty() then | |
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5} | |
minetest.add_item(p, stack) | |
end | |
end | |
meta:from_table(meta2:to_table()) | |
end, | |
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) | |
minetest.log("action", player:get_player_name().. | |
" moves stuff to 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 stuff from chest at "..minetest.pos_to_string(pos)) | |
end, | |
}) | |
default.register_chest("chest_locked", { | |
description = "Locked Chest", | |
tiles = { | |
"default_chest_top.png", | |
"default_chest_top.png", | |
"default_chest_side.png", | |
"default_chest_side.png", | |
"default_chest_lock.png", | |
"default_chest_inside.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, | |
}) | |
default.register_chest("chest_left", { | |
description = "Chest", | |
tiles = { | |
"default_chest_top_big.png", | |
"default_chest_top_big.png", | |
"default_chest_side_big.png^[transformFX", | |
"default_chest_side.png", | |
"default_chest_front_big.png", | |
"default_chest_inside.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}, | |
drop = "default:chest", | |
on_destruct = function(pos) | |
local n = minetest.get_node(pos) | |
if n.name == "default:chest" then | |
return | |
end | |
local param2 = n.param2 | |
local p = get_chest_neighborpos(pos, param2, "left") | |
if not p or minetest.get_node(p).name ~= "default:chest_right" then | |
return | |
end | |
local meta = minetest.get_meta(p) | |
meta:set_string("formspec", | |
"size[8.7,10.4;]" .. | |
"background[-0.27,-0.25;9.41,11.48;chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[current_name;main;-0.064,0.5;9,4;]".. | |
"list[current_player;main;-0.064,5.52;9,4;9]".. | |
"list[current_player;main;-0.064,9.745;9,1;]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]" | |
) | |
minetest.swap_node(p, { name = "default:chest", param2 = param2 }) | |
end, | |
after_dig_node = function(pos, oldnode, oldmetadata, digger) | |
local meta = minetest.get_meta(pos) | |
local meta2 = meta | |
meta:from_table(oldmetadata) | |
local inv = meta:get_inventory() | |
for i=1,inv:get_size("main") do | |
local stack = inv:get_stack("main", i) | |
if not stack:is_empty() then | |
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5} | |
minetest.add_item(p, stack) | |
end | |
end | |
meta:from_table(meta2:to_table()) | |
end, | |
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) | |
minetest.log("action", player:get_player_name().. | |
" moves stuff to 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 stuff from chest at "..minetest.pos_to_string(pos)) | |
end, | |
}) | |
default.register_chest("chest_right", { | |
description = "Chest", | |
tiles = { | |
"default_chest_top_big.png^[transformFX", | |
"default_chest_top_big.png^[transformFX", | |
"default_chest_side.png", | |
"default_chest_side_big.png^[transformFX", | |
"default_chest_front_big.png^[transformFX", | |
"default_chest_inside.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}, | |
drop = "default:chest", | |
on_destruct = function(pos) | |
local n = minetest.get_node(pos) | |
if n.name == "default:chest" then | |
return | |
end | |
local param2 = n.param2 | |
local p = get_chest_neighborpos(pos, param2, "right") | |
if not p or minetest.get_node(p).name ~= "default:chest_left" then | |
return | |
end | |
local meta = minetest.get_meta(p) | |
meta:set_string("formspec", | |
"size[8.7,10.4;]" .. | |
"background[-0.27,-0.25;9.41,11.48;chest_formspec.png]".. | |
"listcolors[#00000000;#FFF7;#00000000]".. | |
"list[current_name;main;-0.064,0.5;9,4;]".. | |
"list[current_player;main;-0.064,5.52;9,4;9]".. | |
"list[current_player;main;-0.064,9.745;9,1;]".. | |
"listring[current_name;main]".. | |
"listring[current_player;main]" | |
) | |
minetest.swap_node(p, { name = "default:chest", param2 = param2 }) | |
end, | |
after_dig_node = function(pos, oldnode, oldmetadata, digger) | |
local meta = minetest.get_meta(pos) | |
local meta2 = meta | |
meta:from_table(oldmetadata) | |
local inv = meta:get_inventory() | |
for i=1,inv:get_size("main") do | |
local stack = inv:get_stack("main", i) | |
if not stack:is_empty() then | |
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5} | |
minetest.add_item(p, stack) | |
end | |
end | |
meta:from_table(meta2:to_table()) | |
end, | |
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) | |
minetest.log("action", player:get_player_name().. | |
" moves stuff to 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 stuff from chest at "..minetest.pos_to_string(pos)) | |
end, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment