2021-05-29 14:12:33 +00:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
2021-09-17 21:58:58 +00:00
local F = minetest.formspec_escape
local C = minetest.colorize
2021-09-17 22:36:33 +00:00
local string = string
local table = table
local math = math
local sf = string.format
2019-03-24 08:30:15 +00:00
local mod_doc = minetest.get_modpath ( " doc " )
2019-03-07 22:40:43 +00:00
2021-12-11 16:16:10 +00:00
-- Christmas chest setup
local it_is_christmas = false
local date = os.date ( " *t " )
if (
2022-09-09 18:42:28 +00:00
date.month == 12 and (
date.day == 24 or
date.day == 25 or
date.day == 26
)
) then
2021-12-11 16:16:10 +00:00
it_is_christmas = true
end
2022-09-09 18:42:28 +00:00
local tiles_chest_normal_small = { " mcl_chests_normal.png " }
local tiles_chest_normal_double = { " mcl_chests_normal_double.png " }
2021-12-11 16:16:10 +00:00
if it_is_christmas then
2022-09-09 18:42:28 +00:00
tiles_chest_normal_small = { " mcl_chests_normal_present.png^mcl_chests_noise.png " }
tiles_chest_normal_double = { " mcl_chests_normal_double_present.png^mcl_chests_noise_double.png " }
2021-12-11 16:16:10 +00:00
end
2022-09-09 18:42:28 +00:00
local tiles_chest_trapped_small = { " mcl_chests_trapped.png " }
local tiles_chest_trapped_double = { " mcl_chests_trapped_double.png " }
2021-12-11 16:16:10 +00:00
if it_is_christmas then
2022-09-09 18:42:28 +00:00
tiles_chest_trapped_small = { " mcl_chests_trapped_present.png^mcl_chests_noise.png " }
tiles_chest_trapped_double = { " mcl_chests_trapped_double_present.png^mcl_chests_noise_double.png " }
2021-12-11 16:16:10 +00:00
end
2022-09-09 18:42:28 +00:00
local tiles_chest_ender_small = { " mcl_chests_ender.png " }
2021-12-11 16:16:10 +00:00
2022-09-09 18:42:28 +00:00
local ender_chest_texture = { " mcl_chests_ender.png " }
2021-12-11 16:16:10 +00:00
if it_is_christmas then
2022-09-09 18:42:28 +00:00
tiles_chest_ender_small = { " mcl_chests_ender_present.png^mcl_chests_noise.png " }
ender_chest_texture = { " mcl_chests_ender_present.png " }
2021-12-11 16:16:10 +00:00
end
2021-01-03 13:21:35 +00:00
-- Chest Entity
2021-01-27 18:21:28 +00:00
local animate_chests = ( minetest.settings : get_bool ( " animated_chests " ) ~= false )
2021-01-27 14:45:23 +00:00
local entity_animations = {
2021-01-28 19:53:57 +00:00
shulker = {
speed = 50 ,
2022-09-09 18:42:28 +00:00
open = { x = 45 , y = 95 } ,
close = { x = 95 , y = 145 } ,
2021-01-28 19:53:57 +00:00
} ,
chest = {
speed = 25 ,
2022-09-09 18:42:28 +00:00
open = { x = 0 , y = 7 } ,
close = { x = 13 , y = 20 } ,
2021-09-17 22:36:33 +00:00
} ,
2021-01-27 14:45:23 +00:00
}
2021-01-03 13:21:35 +00:00
minetest.register_entity ( " mcl_chests:chest " , {
initial_properties = {
visual = " mesh " ,
2022-09-09 18:42:28 +00:00
visual_size = { x = 3 , y = 3 } ,
2021-01-03 13:21:35 +00:00
pointable = false ,
physical = false ,
2021-01-04 16:14:51 +00:00
static_save = false ,
2021-01-03 13:21:35 +00:00
} ,
2021-01-03 17:16:12 +00:00
2021-01-03 13:21:35 +00:00
set_animation = function ( self , animname )
2021-01-28 19:53:57 +00:00
local anim_table = entity_animations [ self.animation_type ]
local anim = anim_table [ animname ]
2021-01-27 14:45:23 +00:00
if not anim then return end
2021-01-28 19:53:57 +00:00
self.object : set_animation ( anim , anim_table.speed , 0 , false )
2021-01-03 13:21:35 +00:00
end ,
2021-01-03 17:16:12 +00:00
2021-03-17 03:10:34 +00:00
open = function ( self , playername )
2021-01-03 13:21:35 +00:00
self.players [ playername ] = true
if not self.is_open then
2021-03-17 03:10:34 +00:00
self : set_animation ( " open " )
2022-09-09 18:42:28 +00:00
minetest.sound_play ( self.sound_prefix .. " _open " , { pos = self.node_pos , gain = 0.5 , max_hear_distance = 16 } ,
true )
2021-01-27 15:42:49 +00:00
self.is_open = true
2021-01-03 13:21:35 +00:00
end
end ,
2021-01-03 17:16:12 +00:00
2021-01-03 13:21:35 +00:00
close = function ( self , playername )
local playerlist = self.players
playerlist [ playername ] = nil
if self.is_open then
2021-05-27 07:41:20 +00:00
if next ( playerlist ) then
2021-01-03 13:21:35 +00:00
return
end
2021-03-17 03:10:34 +00:00
self : set_animation ( " close " )
2022-09-10 16:32:37 +00:00
minetest.sound_play ( self.sound_prefix .. " _close " ,
{ pos = self.node_pos , gain = 0.3 , max_hear_distance = 16 } ,
2022-09-09 18:42:28 +00:00
true )
2021-01-27 14:45:23 +00:00
self.is_open = false
2021-01-03 13:21:35 +00:00
end
end ,
2021-01-28 19:53:57 +00:00
initialize = function ( self , node_pos , node_name , textures , dir , double , sound_prefix , mesh_prefix , animation_type )
2021-01-03 13:21:35 +00:00
self.node_pos = node_pos
self.node_name = node_name
2021-01-04 10:26:07 +00:00
self.sound_prefix = sound_prefix
2021-01-28 19:53:57 +00:00
self.animation_type = animation_type
2021-01-03 13:21:35 +00:00
local obj = self.object
2021-01-03 17:52:24 +00:00
obj : set_properties ( {
textures = textures ,
2021-01-04 10:26:07 +00:00
mesh = mesh_prefix .. ( double and " _double " or " " ) .. " .b3d " ,
2021-01-03 17:52:24 +00:00
} )
2021-01-03 17:16:12 +00:00
self : set_yaw ( dir )
end ,
reinitialize = function ( self , node_name )
self.node_name = node_name
end ,
set_yaw = function ( self , dir )
self.object : set_yaw ( minetest.dir_to_yaw ( dir ) )
2021-01-03 13:21:35 +00:00
end ,
2021-01-03 17:16:12 +00:00
2021-01-03 13:21:35 +00:00
check = function ( self )
local node_pos , node_name = self.node_pos , self.node_name
if not node_pos or not node_name then
return false
end
local node = minetest.get_node ( node_pos )
if node.name ~= node_name then
return false
end
return true
end ,
on_activate = function ( self )
2022-09-09 18:42:28 +00:00
self.object : set_armor_groups ( { immortal = 1 } )
2021-01-03 13:21:35 +00:00
self.players = { }
end ,
2021-01-03 17:16:12 +00:00
2021-01-03 13:21:35 +00:00
on_step = function ( self , dtime )
if not self : check ( ) then
self.object : remove ( )
end
end
} )
local function get_entity_pos ( pos , dir , double )
2022-09-10 16:32:37 +00:00
pos = vector.copy ( pos )
pos.y = pos.y - 0.49
2021-01-03 13:21:35 +00:00
if double then
local add , mul , vec , cross = vector.add , vector.multiply , vector.new , vector.cross
pos = add ( pos , mul ( cross ( dir , vec ( 0 , 1 , 0 ) ) , - 0.5 ) )
end
return pos
end
local function find_entity ( pos )
2021-03-16 16:43:32 +00:00
for _ , obj in pairs ( minetest.get_objects_inside_radius ( pos , 0 ) ) do
2021-01-03 13:21:35 +00:00
local luaentity = obj : get_luaentity ( )
if luaentity and luaentity.name == " mcl_chests:chest " then
return luaentity
end
end
end
2021-01-28 19:53:57 +00:00
local function get_entity_info ( pos , param2 , double , dir , entity_pos )
2021-01-03 13:21:35 +00:00
dir = dir or minetest.facedir_to_dir ( param2 )
2021-01-28 19:53:57 +00:00
return dir , get_entity_pos ( pos , dir , double )
end
2022-09-09 18:42:28 +00:00
local function create_entity ( pos , node_name , textures , param2 , double , sound_prefix , mesh_prefix , animation_type , dir ,
entity_pos )
2021-01-28 19:53:57 +00:00
dir , entity_pos = get_entity_info ( pos , param2 , double , dir , entity_pos )
2021-01-03 13:21:35 +00:00
local obj = minetest.add_entity ( entity_pos , " mcl_chests:chest " )
local luaentity = obj : get_luaentity ( )
2021-01-28 19:53:57 +00:00
luaentity : initialize ( pos , node_name , textures , dir , double , sound_prefix , mesh_prefix , animation_type )
2021-01-03 13:21:35 +00:00
return luaentity
end
2022-09-09 18:42:28 +00:00
local function find_or_create_entity ( pos , node_name , textures , param2 , double , sound_prefix , mesh_prefix , animation_type
, dir , entity_pos )
2021-01-28 19:53:57 +00:00
dir , entity_pos = get_entity_info ( pos , param2 , double , dir , entity_pos )
2022-09-09 18:42:28 +00:00
return find_entity ( entity_pos ) or
create_entity ( pos , node_name , textures , param2 , double , sound_prefix , mesh_prefix , animation_type , dir ,
entity_pos )
2021-01-03 13:21:35 +00:00
end
2017-12-08 16:33:45 +00:00
local no_rotate , simple_rotate
if minetest.get_modpath ( " screwdriver " ) then
no_rotate = screwdriver.disallow
2021-01-03 17:16:12 +00:00
simple_rotate = function ( pos , node , user , mode , new_param2 )
if screwdriver.rotate_simple ( pos , node , user , mode , new_param2 ) ~= false then
local nodename = node.name
local nodedef = minetest.registered_nodes [ nodename ]
2021-01-28 19:53:57 +00:00
local dir = minetest.facedir_to_dir ( new_param2 )
2022-09-09 18:42:28 +00:00
find_or_create_entity ( pos , nodename , nodedef._chest_entity_textures , new_param2 , false ,
nodedef._chest_entity_sound ,
nodedef._chest_entity_mesh , nodedef._chest_entity_animation_type , dir ) : set_yaw ( dir )
2021-01-03 17:16:12 +00:00
else
return false
end
end
2017-12-08 16:33:45 +00:00
end
2018-01-26 23:34:37 +00:00
--[[ List of open chests.
Key : Player name
Value :
2021-05-29 14:12:33 +00:00
If player is using a chest : { pos = < chest node position > }
Otherwise : nil ] ]
2018-01-26 23:34:37 +00:00
local open_chests = { }
2021-01-27 15:42:49 +00:00
2021-05-22 22:31:22 +00:00
--[[local function back_is_blocked(pos, dir)
2021-01-27 15:42:49 +00:00
pos = vector.add ( pos , dir )
local def = minetest.registered_nodes [ minetest.get_node ( pos ) . name ]
pos.y = pos.y + 1
local def2 = minetest.registered_nodes [ minetest.get_node ( pos ) . name ]
return not def or def.groups . opaque == 1 or not def2 or def2.groups . opaque == 1
2021-05-22 22:31:22 +00:00
end ] ]
2018-01-26 23:34:37 +00:00
-- To be called if a player opened a chest
2021-05-29 14:12:33 +00:00
local function player_chest_open ( player , pos , node_name , textures , param2 , double , sound , mesh , shulker )
2021-01-03 13:21:35 +00:00
local name = player : get_player_name ( )
2022-09-09 18:42:28 +00:00
open_chests [ name ] = {
pos = pos ,
node_name = node_name ,
textures = textures ,
param2 = param2 ,
double = double ,
sound = sound ,
mesh = mesh ,
shulker = shulker
}
2021-01-27 18:21:28 +00:00
if animate_chests then
local dir = minetest.facedir_to_dir ( param2 )
2022-09-09 18:42:28 +00:00
find_or_create_entity ( pos , node_name , textures , param2 , double , sound , mesh , shulker and " shulker " or " chest " ,
dir ) :
open ( name )
2021-01-27 18:21:28 +00:00
end
2018-01-26 23:34:37 +00:00
end
2018-01-26 23:50:04 +00:00
2019-02-08 20:59:01 +00:00
-- Simple protection checking functions
2021-05-29 14:12:33 +00:00
local function protection_check_move ( pos , from_list , from_index , to_list , to_index , count , player )
2019-02-08 20:59:01 +00:00
local name = player : get_player_name ( )
if minetest.is_protected ( pos , name ) then
minetest.record_protection_violation ( pos , name )
return 0
else
return count
end
end
2022-09-09 18:42:28 +00:00
2021-05-29 14:12:33 +00:00
local function protection_check_put_take ( pos , listname , index , stack , player )
2019-02-08 20:59:01 +00:00
local name = player : get_player_name ( )
if minetest.is_protected ( pos , name ) then
minetest.record_protection_violation ( pos , name )
return 0
else
return stack : get_count ( )
end
end
2018-01-26 23:50:04 +00:00
local trapped_chest_mesecons_rules = mesecon.rules . pplate
2019-03-09 06:59:07 +00:00
-- To be called when a chest is closed (only relevant for trapped chest atm)
2021-05-29 14:12:33 +00:00
local function chest_update_after_close ( pos )
2018-01-26 23:34:37 +00:00
local node = minetest.get_node ( pos )
2021-01-03 17:52:24 +00:00
if node.name == " mcl_chests:trapped_chest_on_small " then
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_small " , param2 = node.param2 } )
find_or_create_entity ( pos , " mcl_chests:trapped_chest_small " , { " mcl_chests_trapped.png " } , node.param2 , false ,
" default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_small " )
2018-01-26 23:34:37 +00:00
mesecon.receptor_off ( pos , trapped_chest_mesecons_rules )
elseif node.name == " mcl_chests:trapped_chest_on_left " then
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_left " , param2 = node.param2 } )
find_or_create_entity ( pos , " mcl_chests:trapped_chest_left " , tiles_chest_trapped_double , node.param2 , true ,
" default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_left " )
2018-01-26 23:34:37 +00:00
mesecon.receptor_off ( pos , trapped_chest_mesecons_rules )
local pos_other = mcl_util.get_double_container_neighbor_pos ( pos , node.param2 , " left " )
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos_other , { name = " mcl_chests:trapped_chest_right " , param2 = node.param2 } )
2018-01-26 23:34:37 +00:00
mesecon.receptor_off ( pos_other , trapped_chest_mesecons_rules )
elseif node.name == " mcl_chests:trapped_chest_on_right " then
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_right " , param2 = node.param2 } )
2018-01-26 23:34:37 +00:00
mesecon.receptor_off ( pos , trapped_chest_mesecons_rules )
local pos_other = mcl_util.get_double_container_neighbor_pos ( pos , node.param2 , " right " )
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos_other , { name = " mcl_chests:trapped_chest_left " , param2 = node.param2 } )
find_or_create_entity ( pos_other , " mcl_chests:trapped_chest_left " , tiles_chest_trapped_double , node.param2 , true ,
" default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_left " )
2018-01-26 23:34:37 +00:00
mesecon.receptor_off ( pos_other , trapped_chest_mesecons_rules )
end
2019-03-09 06:59:07 +00:00
end
-- To be called if a player closed a chest
2021-05-29 14:12:33 +00:00
local function player_chest_close ( player )
2019-03-09 06:59:07 +00:00
local name = player : get_player_name ( )
2021-01-03 13:21:35 +00:00
local open_chest = open_chests [ name ]
if open_chest == nil then
2019-03-09 06:59:07 +00:00
return
end
2021-01-27 18:21:28 +00:00
if animate_chests then
2022-09-09 18:42:28 +00:00
find_or_create_entity ( open_chest.pos , open_chest.node_name , open_chest.textures , open_chest.param2 ,
open_chest.double ,
open_chest.sound , open_chest.mesh , open_chest.shulker and " shulker " or " chest " ) : close ( name )
2021-01-27 18:21:28 +00:00
end
2021-01-03 13:21:35 +00:00
chest_update_after_close ( open_chest.pos )
2018-01-26 23:34:37 +00:00
open_chests [ name ] = nil
end
2017-03-16 03:23:21 +00:00
-- This is a helper function to register both chests and trapped chests. Trapped chests will make use of the additional parameters
2022-09-09 18:42:28 +00:00
local function register_chest ( basename , desc , longdesc , usagehelp , tt_help , tiles_table , hidden , mesecons ,
on_rightclick_addendum , on_rightclick_addendum_left , on_rightclick_addendum_right , drop ,
canonical_basename )
2021-05-29 14:12:33 +00:00
-- START OF register_chest FUNCTION BODY
if not drop then
2022-09-09 18:42:28 +00:00
drop = " mcl_chests: " .. basename
2021-05-29 14:12:33 +00:00
else
2022-09-09 18:42:28 +00:00
drop = " mcl_chests: " .. drop
2021-05-29 14:12:33 +00:00
end
-- The basename of the "canonical" version of the node, if set (e.g.: trapped_chest_on → trapped_chest).
-- Used to get a shared formspec ID and to swap the node back to the canonical version in on_construct.
if not canonical_basename then
canonical_basename = basename
2020-03-24 19:19:49 +00:00
end
2021-05-29 14:12:33 +00:00
local function double_chest_add_item ( top_inv , bottom_inv , listname , stack )
if not stack or stack : is_empty ( ) then
return
end
2020-03-24 19:19:49 +00:00
2021-05-29 14:12:33 +00:00
local name = stack : get_name ( )
local function top_off ( inv , stack )
for c , chest_stack in ipairs ( inv : get_list ( listname ) ) do
if stack : is_empty ( ) then
break
end
2020-03-24 19:19:49 +00:00
2021-05-29 14:12:33 +00:00
if chest_stack : get_name ( ) == name and chest_stack : get_free_space ( ) > 0 then
stack = chest_stack : add_item ( stack )
inv : set_stack ( listname , c , chest_stack )
end
2020-03-24 19:19:49 +00:00
end
2021-05-29 14:12:33 +00:00
return stack
end
2020-03-24 19:19:49 +00:00
2021-05-29 14:12:33 +00:00
stack = top_off ( top_inv , stack )
stack = top_off ( bottom_inv , stack )
2020-03-24 19:19:49 +00:00
if not stack : is_empty ( ) then
2021-05-29 14:12:33 +00:00
stack = top_inv : add_item ( listname , stack )
if not stack : is_empty ( ) then
bottom_inv : add_item ( listname , stack )
end
2020-03-24 19:19:49 +00:00
end
end
2022-02-07 07:47:41 +00:00
local drop_items_chest = mcl_util.drop_items_from_meta_container ( " main " )
2020-06-06 14:57:19 +00:00
2021-05-29 14:12:33 +00:00
local function on_chest_blast ( pos )
local node = minetest.get_node ( pos )
drop_items_chest ( pos , node )
minetest.remove_node ( pos )
end
2020-06-06 14:57:19 +00:00
2021-05-29 14:12:33 +00:00
local function limit_put_list ( stack , list )
for _ , other in ipairs ( list ) do
stack = other : add_item ( stack )
if stack : is_empty ( ) then
break
end
2021-01-05 13:13:33 +00:00
end
2021-05-29 14:12:33 +00:00
return stack
2021-01-05 13:13:33 +00:00
end
2021-05-29 14:12:33 +00:00
local function limit_put ( stack , inv1 , inv2 )
local leftover = ItemStack ( stack )
leftover = limit_put_list ( leftover , inv1 : get_list ( " main " ) )
leftover = limit_put_list ( leftover , inv2 : get_list ( " main " ) )
return stack : get_count ( ) - leftover : get_count ( )
end
2021-01-05 13:13:33 +00:00
2022-09-09 18:42:28 +00:00
local small_name = " mcl_chests: " .. basename .. " _small "
2021-05-29 14:12:33 +00:00
local small_textures = tiles_table.small
2022-09-09 18:42:28 +00:00
local left_name = " mcl_chests: " .. basename .. " _left "
2021-05-29 14:12:33 +00:00
local left_textures = tiles_table.double
2021-01-03 17:16:12 +00:00
2022-09-09 18:42:28 +00:00
minetest.register_node ( " mcl_chests: " .. basename , {
2021-05-29 14:12:33 +00:00
description = desc ,
_tt_help = tt_help ,
_doc_items_longdesc = longdesc ,
_doc_items_usagehelp = usagehelp ,
_doc_items_hidden = hidden ,
drawtype = " mesh " ,
2022-10-18 15:25:25 +00:00
mesh = " mcl_chests_chest.b3d " ,
2021-05-29 14:12:33 +00:00
tiles = small_textures ,
2022-09-10 16:32:37 +00:00
use_texture_alpha = " opaque " ,
2021-05-29 14:12:33 +00:00
paramtype = " light " ,
paramtype2 = " facedir " ,
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
2022-09-09 18:42:28 +00:00
groups = { deco_block = 1 } ,
2021-05-29 14:12:33 +00:00
on_construct = function ( pos , node )
local node = minetest.get_node ( pos )
node.name = small_name
minetest.set_node ( pos , node )
end ,
after_place_node = function ( pos , placer , itemstack , pointed_thing )
minetest.get_meta ( pos ) : set_string ( " name " , itemstack : get_meta ( ) : get_string ( " name " ) )
end ,
} )
2021-01-22 17:42:37 +00:00
2021-05-29 14:12:33 +00:00
local function close_forms ( canonical_basename , pos )
local players = minetest.get_connected_players ( )
2022-09-09 18:42:28 +00:00
for p = 1 , # players do
2021-05-29 14:12:33 +00:00
if vector.distance ( players [ p ] : get_pos ( ) , pos ) <= 30 then
2022-09-09 18:42:28 +00:00
minetest.close_formspec ( players [ p ] : get_player_name ( ) ,
" mcl_chests: " .. canonical_basename .. " _ " .. pos.x .. " _ " .. pos.y .. " _ " .. pos.z )
2021-05-29 14:12:33 +00:00
end
2017-06-12 18:36:50 +00:00
end
2021-05-29 14:12:33 +00:00
end
2017-03-16 01:13:35 +00:00
2021-05-29 14:12:33 +00:00
minetest.register_node ( small_name , {
description = desc ,
_tt_help = tt_help ,
_doc_items_longdesc = longdesc ,
_doc_items_usagehelp = usagehelp ,
_doc_items_hidden = hidden ,
drawtype = " nodebox " ,
node_box = {
type = " fixed " ,
2022-09-09 18:42:28 +00:00
fixed = { - 0.4375 , - 0.5 , - 0.4375 , 0.4375 , 0.375 , 0.4375 } ,
2021-05-29 14:12:33 +00:00
} ,
2022-09-09 18:42:28 +00:00
tiles = { " blank.png^[resize:16x16 " } ,
2022-09-10 16:32:37 +00:00
use_texture_alpha = " clip " ,
2021-05-29 14:12:33 +00:00
_chest_entity_textures = small_textures ,
_chest_entity_sound = " default_chest " ,
_chest_entity_mesh = " mcl_chests_chest " ,
_chest_entity_animation_type = " chest " ,
paramtype = " light " ,
paramtype2 = " facedir " ,
drop = drop ,
2022-09-09 18:42:28 +00:00
groups = {
handy = 1 ,
axey = 1 ,
container = 2 ,
deco_block = 1 ,
material_wood = 1 ,
flammable = - 1 ,
chest_entity = 1 ,
not_in_creative_inventory = 1
} ,
2021-05-29 14:12:33 +00:00
is_ground_content = false ,
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
on_construct = function ( pos )
local param2 = minetest.get_node ( pos ) . param2
local meta = minetest.get_meta ( pos )
--[[ This is a workaround for Minetest issue 5894
< https : // github.com / minetest / minetest / issues / 5894 > .
Apparently if we don ' t do this, large chests initially don ' t work when
placed at chunk borders , and some chests randomly don ' t work after
placing . ] ]
-- FIXME: Remove this workaround when the bug has been fixed.
-- BEGIN OF WORKAROUND --
meta : set_string ( " workaround " , " ignore_me " )
meta : set_string ( " workaround " , nil ) -- Done to keep metadata clean
-- END OF WORKAROUND --
local inv = meta : get_inventory ( )
2022-09-09 18:42:28 +00:00
inv : set_size ( " main " , 9 * 3 )
2021-05-29 14:12:33 +00:00
--[[ The "input" list is *another* workaround (hahahaha!) around the fact that Minetest
does not support listrings to put items into an alternative list if the first one
happens to be full . See < https : // github.com / minetest / minetest / issues / 5343 > .
This list is a hidden input - only list and immediately puts items into the appropriate chest .
It is only used for listrings and hoppers . This workaround is not that bad because it only
requires a simple “ inventory allows ” check for large chests . ] ]
-- FIXME: Refactor the listrings as soon Minetest supports alternative listrings
-- BEGIN OF LISTRING WORKAROUND
inv : set_size ( " input " , 1 )
-- END OF LISTRING WORKAROUND
2022-09-09 18:42:28 +00:00
if minetest.get_node ( mcl_util.get_double_container_neighbor_pos ( pos , param2 , " right " ) ) . name ==
" mcl_chests: " .. canonical_basename .. " _small " then
minetest.swap_node ( pos , { name = " mcl_chests: " .. canonical_basename .. " _right " , param2 = param2 } )
2021-05-29 14:12:33 +00:00
local p = mcl_util.get_double_container_neighbor_pos ( pos , param2 , " right " )
2022-09-09 18:42:28 +00:00
minetest.swap_node ( p , { name = " mcl_chests: " .. canonical_basename .. " _left " , param2 = param2 } )
create_entity ( p , " mcl_chests: " .. canonical_basename .. " _left " , left_textures , param2 , true ,
" default_chest " ,
" mcl_chests_chest " , " chest " )
elseif minetest.get_node ( mcl_util.get_double_container_neighbor_pos ( pos , param2 , " left " ) ) . name ==
" mcl_chests: " .. canonical_basename .. " _small " then
minetest.swap_node ( pos , { name = " mcl_chests: " .. canonical_basename .. " _left " , param2 = param2 } )
create_entity ( pos , " mcl_chests: " .. canonical_basename .. " _left " , left_textures , param2 , true ,
" default_chest " ,
" mcl_chests_chest " , " chest " )
2021-05-29 14:12:33 +00:00
local p = mcl_util.get_double_container_neighbor_pos ( pos , param2 , " left " )
2022-09-09 18:42:28 +00:00
minetest.swap_node ( p , { name = " mcl_chests: " .. canonical_basename .. " _right " , param2 = param2 } )
2021-05-29 14:12:33 +00:00
else
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos , { name = " mcl_chests: " .. canonical_basename .. " _small " , param2 = param2 } )
create_entity ( pos , small_name , small_textures , param2 , false , " default_chest " , " mcl_chests_chest " ,
" chest " )
2021-05-29 14:12:33 +00:00
end
end ,
after_place_node = function ( pos , placer , itemstack , pointed_thing )
minetest.get_meta ( pos ) : set_string ( " name " , itemstack : get_meta ( ) : get_string ( " name " ) )
end ,
after_dig_node = drop_items_chest ,
on_blast = on_chest_blast ,
allow_metadata_inventory_move = protection_check_move ,
allow_metadata_inventory_take = protection_check_put_take ,
allow_metadata_inventory_put = protection_check_put_take ,
on_metadata_inventory_move = function ( pos , from_list , from_index , to_list , to_index , count , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" moves stuff in chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
end ,
on_metadata_inventory_put = function ( pos , listname , index , stack , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" moves stuff to chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
-- BEGIN OF LISTRING WORKAROUND
if listname == " input " then
2022-09-09 18:42:28 +00:00
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
2021-05-29 14:12:33 +00:00
inv : add_item ( " main " , stack )
end
-- END OF LISTRING WORKAROUND
end ,
on_metadata_inventory_take = function ( pos , listname , index , stack , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" takes stuff from chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
end ,
_mcl_blast_resistance = 2.5 ,
_mcl_hardness = 2.5 ,
2020-07-27 17:26:01 +00:00
2021-05-29 14:12:33 +00:00
on_rightclick = function ( pos , node , clicker )
2022-09-09 18:42:28 +00:00
if minetest.registered_nodes [ minetest.get_node ( { x = pos.x , y = pos.y + 1 , z = pos.z } ) . name ] . groups.opaque == 1 then
2021-05-29 14:12:33 +00:00
-- won't open if there is no space from the top
return false
end
local name = minetest.get_meta ( pos ) : get_string ( " name " )
if name == " " then
name = S ( " Chest " )
end
2021-01-03 17:16:12 +00:00
2021-05-29 14:12:33 +00:00
minetest.show_formspec ( clicker : get_player_name ( ) ,
2021-09-17 22:36:33 +00:00
sf ( " mcl_chests:%s_%s_%s_%s " , canonical_basename , pos.x , pos.y , pos.z ) ,
table.concat ( {
" formspec_version[4] " ,
2021-09-18 07:53:45 +00:00
" size[11.75,10.425] " ,
2021-09-17 22:36:33 +00:00
2022-09-09 18:42:28 +00:00
" label[0.375,0.375; " .. F ( C ( mcl_formspec.label_color , name ) ) .. " ] " ,
2021-09-17 22:36:33 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 0.75 , 9 , 3 ) ,
sf ( " list[nodemeta:%s,%s,%s;main;0.375,0.75;9,3;] " , pos.x , pos.y , pos.z ) ,
2022-09-09 18:42:28 +00:00
" label[0.375,4.7; " .. F ( C ( mcl_formspec.label_color , S ( " Inventory " ) ) ) .. " ] " ,
2021-09-17 22:36:33 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 5.1 , 9 , 3 ) ,
" list[current_player;main;0.375,5.1;9,3;9] " ,
2021-09-18 07:53:45 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 9.05 , 9 , 1 ) ,
" list[current_player;main;0.375,9.05;9,1;] " ,
2021-09-17 22:36:33 +00:00
sf ( " listring[nodemeta:%s,%s,%s;main] " , pos.x , pos.y , pos.z ) ,
" listring[current_player;main] " ,
} )
)
2021-05-29 14:12:33 +00:00
if on_rightclick_addendum then
on_rightclick_addendum ( pos , node , clicker )
end
2017-09-19 17:40:54 +00:00
2022-09-09 18:42:28 +00:00
player_chest_open ( clicker , pos , small_name , small_textures , node.param2 , false , " default_chest " ,
" mcl_chests_chest " )
2021-05-29 14:12:33 +00:00
end ,
2017-01-27 11:42:05 +00:00
2021-05-29 14:12:33 +00:00
on_destruct = function ( pos )
close_forms ( canonical_basename , pos )
end ,
mesecons = mesecons ,
on_rotate = simple_rotate ,
} )
2017-09-19 17:40:54 +00:00
2021-05-29 14:12:33 +00:00
minetest.register_node ( left_name , {
drawtype = " nodebox " ,
node_box = {
type = " fixed " ,
2022-09-09 18:42:28 +00:00
fixed = { - 0.4375 , - 0.5 , - 0.4375 , 0.5 , 0.375 , 0.4375 } ,
2021-05-29 14:12:33 +00:00
} ,
2022-09-09 18:42:28 +00:00
tiles = { " blank.png^[resize:16x16 " } ,
2022-09-10 16:32:37 +00:00
use_texture_alpha = " clip " ,
2021-05-29 14:12:33 +00:00
_chest_entity_textures = left_textures ,
_chest_entity_sound = " default_chest " ,
_chest_entity_mesh = " mcl_chests_chest " ,
_chest_entity_animation_type = " chest " ,
paramtype = " light " ,
paramtype2 = " facedir " ,
2022-09-09 18:42:28 +00:00
groups = {
handy = 1 ,
axey = 1 ,
container = 5 ,
not_in_creative_inventory = 1 ,
material_wood = 1 ,
flammable = - 1 ,
chest_entity = 1 ,
double_chest = 1
} ,
2021-05-29 14:12:33 +00:00
drop = drop ,
is_ground_content = false ,
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
on_construct = function ( pos )
local n = minetest.get_node ( pos )
local param2 = n.param2
local p = mcl_util.get_double_container_neighbor_pos ( pos , param2 , " left " )
2022-09-09 18:42:28 +00:00
if not p or minetest.get_node ( p ) . name ~= " mcl_chests: " .. canonical_basename .. " _right " then
n.name = " mcl_chests: " .. canonical_basename .. " _small "
2021-05-29 14:12:33 +00:00
minetest.swap_node ( pos , n )
end
create_entity ( pos , left_name , left_textures , param2 , true , " default_chest " , " mcl_chests_chest " , " chest " )
end ,
after_place_node = function ( pos , placer , itemstack , pointed_thing )
minetest.get_meta ( pos ) : set_string ( " name " , itemstack : get_meta ( ) : get_string ( " name " ) )
end ,
on_destruct = function ( pos )
local n = minetest.get_node ( pos )
if n.name == small_name then
return
end
2017-09-19 17:40:54 +00:00
2021-05-29 14:12:33 +00:00
close_forms ( canonical_basename , pos )
2021-01-22 17:42:37 +00:00
2021-05-29 14:12:33 +00:00
local param2 = n.param2
local p = mcl_util.get_double_container_neighbor_pos ( pos , param2 , " left " )
2022-09-09 18:42:28 +00:00
if not p or minetest.get_node ( p ) . name ~= " mcl_chests: " .. basename .. " _right " then
2021-05-29 14:12:33 +00:00
return
end
close_forms ( canonical_basename , p )
2021-01-05 13:13:33 +00:00
2021-05-29 14:12:33 +00:00
minetest.swap_node ( p , { name = small_name , param2 = param2 } )
create_entity ( p , small_name , small_textures , param2 , false , " default_chest " , " mcl_chests_chest " , " chest " )
end ,
after_dig_node = drop_items_chest ,
on_blast = on_chest_blast ,
allow_metadata_inventory_move = protection_check_move ,
allow_metadata_inventory_take = protection_check_put_take ,
allow_metadata_inventory_put = function ( pos , listname , index , stack , player )
local name = player : get_player_name ( )
if minetest.is_protected ( pos , name ) then
minetest.record_protection_violation ( pos , name )
return 0
2022-09-09 18:42:28 +00:00
-- BEGIN OF LISTRING WORKAROUND
2021-05-29 14:12:33 +00:00
elseif listname == " input " then
2022-09-09 18:42:28 +00:00
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
2021-05-29 14:12:33 +00:00
local other_pos = mcl_util.get_double_container_neighbor_pos ( pos , minetest.get_node ( pos ) . param2 , " left " )
2022-09-09 18:42:28 +00:00
local other_inv = minetest.get_inventory ( { type = " node " , pos = other_pos } )
2021-05-29 14:12:33 +00:00
return limit_put ( stack , inv , other_inv )
--[[if inv:room_for_item("main", stack) then
2017-06-12 18:36:50 +00:00
return - 1
else
2017-03-16 01:13:35 +00:00
2021-05-29 14:12:33 +00:00
if other_inv : room_for_item ( " main " , stack ) then
return - 1
else
return 0
end
2022-09-09 18:42:28 +00:00
end ] ]
--
-- END OF LISTRING WORKAROUND
2021-05-29 14:12:33 +00:00
else
return stack : get_count ( )
end
end ,
on_metadata_inventory_move = function ( pos , from_list , from_index , to_list , to_index , count , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" moves stuff in chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
end ,
on_metadata_inventory_put = function ( pos , listname , index , stack , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" moves stuff to chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
-- BEGIN OF LISTRING WORKAROUND
if listname == " input " then
2022-09-09 18:42:28 +00:00
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
2021-05-29 14:12:33 +00:00
local other_pos = mcl_util.get_double_container_neighbor_pos ( pos , minetest.get_node ( pos ) . param2 , " left " )
2022-09-09 18:42:28 +00:00
local other_inv = minetest.get_inventory ( { type = " node " , pos = other_pos } )
2021-05-29 14:12:33 +00:00
inv : set_stack ( " input " , 1 , nil )
double_chest_add_item ( inv , other_inv , " main " , stack )
end
-- END OF LISTRING WORKAROUND
end ,
on_metadata_inventory_take = function ( pos , listname , index , stack , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" takes stuff from chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
end ,
_mcl_blast_resistance = 2.5 ,
_mcl_hardness = 2.5 ,
2020-09-30 12:42:52 +00:00
2021-05-29 14:12:33 +00:00
on_rightclick = function ( pos , node , clicker )
local pos_other = mcl_util.get_double_container_neighbor_pos ( pos , node.param2 , " left " )
2022-09-09 18:42:28 +00:00
local above_def = minetest.registered_nodes [ minetest.get_node ( { x = pos.x , y = pos.y + 1 , z = pos.z } ) . name ]
local above_def_other = minetest.registered_nodes [
minetest.get_node ( { x = pos_other.x , y = pos_other.y + 1 , z = pos_other.z } ) . name ]
2021-11-17 17:25:12 +00:00
if not above_def or above_def.groups . opaque == 1 or not above_def_other or above_def_other.groups . opaque == 1 then
-- won't open if there is no space from the top
return false
2021-05-29 14:12:33 +00:00
end
2017-03-16 01:13:35 +00:00
2021-05-29 14:12:33 +00:00
local name = minetest.get_meta ( pos ) : get_string ( " name " )
if name == " " then
name = minetest.get_meta ( pos_other ) : get_string ( " name " )
end
if name == " " then
name = S ( " Large Chest " )
end
2021-01-03 17:16:12 +00:00
2021-05-29 14:12:33 +00:00
minetest.show_formspec ( clicker : get_player_name ( ) ,
2021-09-18 07:53:45 +00:00
sf ( " mcl_chests:%s_%s_%s_%s " , canonical_basename , pos.x , pos.y , pos.z ) ,
table.concat ( {
" formspec_version[4] " ,
" size[11.75,14.15] " ,
2022-09-09 18:42:28 +00:00
" label[0.375,0.375; " .. F ( C ( mcl_formspec.label_color , name ) ) .. " ] " ,
2021-09-18 07:53:45 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 0.75 , 9 , 3 ) ,
sf ( " list[nodemeta:%s,%s,%s;main;0.375,0.75;9,3;] " , pos.x , pos.y , pos.z ) ,
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 4.5 , 9 , 3 ) ,
sf ( " list[nodemeta:%s,%s,%s;main;0.375,4.5;9,3;] " , pos_other.x , pos_other.y , pos_other.z ) ,
2022-09-09 18:42:28 +00:00
" label[0.375,8.45; " .. F ( C ( mcl_formspec.label_color , S ( " Inventory " ) ) ) .. " ] " ,
2021-09-18 07:53:45 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 8.825 , 9 , 3 ) ,
" list[current_player;main;0.375,8.825;9,3;9] " ,
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 12.775 , 9 , 1 ) ,
" list[current_player;main;0.375,12.775;9,1;] " ,
--BEGIN OF LISTRING WORKAROUND
" listring[current_player;main] " ,
sf ( " listring[nodemeta:%s,%s,%s;input] " , pos.x , pos.y , pos.z ) ,
--END OF LISTRING WORKAROUND
2022-09-09 18:42:28 +00:00
" listring[current_player;main] " ..
2021-09-18 07:53:45 +00:00
sf ( " listring[nodemeta:%s,%s,%s;main] " , pos.x , pos.y , pos.z ) ,
" listring[current_player;main] " ,
sf ( " listring[nodemeta:%s,%s,%s;main] " , pos_other.x , pos_other.y , pos_other.z ) ,
} )
)
2021-05-29 14:12:33 +00:00
if on_rightclick_addendum_left then
on_rightclick_addendum_left ( pos , node , clicker )
end
2017-01-27 11:42:05 +00:00
2022-09-09 18:42:28 +00:00
player_chest_open ( clicker , pos , left_name , left_textures , node.param2 , true , " default_chest " ,
" mcl_chests_chest " )
2021-05-29 14:12:33 +00:00
end ,
mesecons = mesecons ,
on_rotate = no_rotate ,
} )
2022-09-09 18:42:28 +00:00
minetest.register_node ( " mcl_chests: " .. basename .. " _right " , {
2021-05-29 14:12:33 +00:00
drawtype = " nodebox " ,
paramtype = " light " ,
paramtype2 = " facedir " ,
node_box = {
type = " fixed " ,
2022-09-09 18:42:28 +00:00
fixed = { - 0.5 , - 0.5 , - 0.4375 , 0.4375 , 0.375 , 0.4375 } ,
2021-05-29 14:12:33 +00:00
} ,
2022-09-09 18:42:28 +00:00
tiles = { " blank.png^[resize:16x16 " } ,
2022-09-10 16:32:37 +00:00
use_texture_alpha = " clip " ,
2022-09-09 18:42:28 +00:00
groups = {
handy = 1 ,
axey = 1 ,
container = 6 ,
not_in_creative_inventory = 1 ,
material_wood = 1 ,
flammable = - 1 ,
double_chest = 2
} ,
2021-05-29 14:12:33 +00:00
drop = drop ,
is_ground_content = false ,
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
on_construct = function ( pos )
local n = minetest.get_node ( pos )
local param2 = n.param2
local p = mcl_util.get_double_container_neighbor_pos ( pos , param2 , " right " )
2022-09-09 18:42:28 +00:00
if not p or minetest.get_node ( p ) . name ~= " mcl_chests: " .. canonical_basename .. " _left " then
n.name = " mcl_chests: " .. canonical_basename .. " _small "
2021-05-29 14:12:33 +00:00
minetest.swap_node ( pos , n )
end
end ,
after_place_node = function ( pos , placer , itemstack , pointed_thing )
minetest.get_meta ( pos ) : set_string ( " name " , itemstack : get_meta ( ) : get_string ( " name " ) )
end ,
on_destruct = function ( pos )
local n = minetest.get_node ( pos )
if n.name == small_name then
return
end
2017-09-19 17:40:54 +00:00
2021-05-29 14:12:33 +00:00
close_forms ( canonical_basename , pos )
2017-09-19 17:40:54 +00:00
2021-05-29 14:12:33 +00:00
local param2 = n.param2
local p = mcl_util.get_double_container_neighbor_pos ( pos , param2 , " right " )
2022-09-09 18:42:28 +00:00
if not p or minetest.get_node ( p ) . name ~= " mcl_chests: " .. basename .. " _left " then
2021-05-29 14:12:33 +00:00
return
end
close_forms ( canonical_basename , p )
2021-01-22 17:42:37 +00:00
2021-05-29 14:12:33 +00:00
minetest.swap_node ( p , { name = small_name , param2 = param2 } )
create_entity ( p , small_name , small_textures , param2 , false , " default_chest " , " mcl_chests_chest " , " chest " )
end ,
after_dig_node = drop_items_chest ,
on_blast = on_chest_blast ,
allow_metadata_inventory_move = protection_check_move ,
allow_metadata_inventory_take = protection_check_put_take ,
allow_metadata_inventory_put = function ( pos , listname , index , stack , player )
local name = player : get_player_name ( )
if minetest.is_protected ( pos , name ) then
minetest.record_protection_violation ( pos , name )
return 0
2022-09-09 18:42:28 +00:00
-- BEGIN OF LISTRING WORKAROUND
2021-05-29 14:12:33 +00:00
elseif listname == " input " then
local other_pos = mcl_util.get_double_container_neighbor_pos ( pos , minetest.get_node ( pos ) . param2 , " right " )
2022-09-09 18:42:28 +00:00
local other_inv = minetest.get_inventory ( { type = " node " , pos = other_pos } )
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
2021-05-29 14:12:33 +00:00
--[[if other_inv:room_for_item("main", stack) then
2017-06-12 18:36:50 +00:00
return - 1
else
2021-05-29 14:12:33 +00:00
if inv : room_for_item ( " main " , stack ) then
return - 1
else
return 0
end
end --]]
return limit_put ( stack , other_inv , inv )
2022-09-09 18:42:28 +00:00
-- END OF LISTRING WORKAROUND
2021-05-29 14:12:33 +00:00
else
return stack : get_count ( )
end
end ,
on_metadata_inventory_move = function ( pos , from_list , from_index , to_list , to_index , count , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" moves stuff in chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
end ,
on_metadata_inventory_put = function ( pos , listname , index , stack , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" moves stuff to chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
-- BEGIN OF LISTRING WORKAROUND
if listname == " input " then
local other_pos = mcl_util.get_double_container_neighbor_pos ( pos , minetest.get_node ( pos ) . param2 , " right " )
2022-09-09 18:42:28 +00:00
local other_inv = minetest.get_inventory ( { type = " node " , pos = other_pos } )
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
2021-05-29 14:12:33 +00:00
inv : set_stack ( " input " , 1 , nil )
double_chest_add_item ( other_inv , inv , " main " , stack )
end
-- END OF LISTRING WORKAROUND
end ,
on_metadata_inventory_take = function ( pos , listname , index , stack , player )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , player : get_player_name ( ) ..
" takes stuff from chest at " .. minetest.pos_to_string ( pos ) )
2021-05-29 14:12:33 +00:00
end ,
_mcl_blast_resistance = 2.5 ,
_mcl_hardness = 2.5 ,
2017-03-16 01:13:35 +00:00
2021-05-29 14:12:33 +00:00
on_rightclick = function ( pos , node , clicker )
local pos_other = mcl_util.get_double_container_neighbor_pos ( pos , node.param2 , " right " )
2022-09-09 18:42:28 +00:00
if minetest.registered_nodes [ minetest.get_node ( { x = pos.x , y = pos.y + 1 , z = pos.z } ) . name ] . groups.opaque == 1
or
minetest.registered_nodes [ minetest.get_node ( { x = pos_other.x , y = pos_other.y + 1 , z = pos_other.z } ) . name ] . groups.opaque
== 1 then
-- won't open if there is no space from the top
return false
2021-05-29 14:12:33 +00:00
end
2020-09-30 12:42:52 +00:00
2021-05-29 14:12:33 +00:00
local name = minetest.get_meta ( pos_other ) : get_string ( " name " )
if name == " " then
name = minetest.get_meta ( pos ) : get_string ( " name " )
end
if name == " " then
name = S ( " Large Chest " )
end
2017-03-16 03:16:37 +00:00
2021-05-29 14:12:33 +00:00
minetest.show_formspec ( clicker : get_player_name ( ) ,
2021-09-18 07:53:45 +00:00
sf ( " mcl_chests:%s_%s_%s_%s " , canonical_basename , pos.x , pos.y , pos.z ) ,
table.concat ( {
" formspec_version[4] " ,
" size[11.75,14.15] " ,
2022-09-09 18:42:28 +00:00
" label[0.375,0.375; " .. F ( C ( mcl_formspec.label_color , name ) ) .. " ] " ,
2021-09-18 07:53:45 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 0.75 , 9 , 3 ) ,
sf ( " list[nodemeta:%s,%s,%s;main;0.375,0.75;9,3;] " , pos_other.x , pos_other.y , pos_other.z ) ,
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 4.5 , 9 , 3 ) ,
sf ( " list[nodemeta:%s,%s,%s;main;0.375,4.5;9,3;] " , pos.x , pos.y , pos.z ) ,
2022-09-09 18:42:28 +00:00
" label[0.375,8.45; " .. F ( C ( mcl_formspec.label_color , S ( " Inventory " ) ) ) .. " ] " ,
2021-09-18 07:53:45 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 8.825 , 9 , 3 ) ,
" list[current_player;main;0.375,8.825;9,3;9] " ,
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 12.775 , 9 , 1 ) ,
" list[current_player;main;0.375,12.775;9,1;] " ,
--BEGIN OF LISTRING WORKAROUND
" listring[current_player;main] " ,
sf ( " listring[nodemeta:%s,%s,%s;input] " , pos.x , pos.y , pos.z ) ,
--END OF LISTRING WORKAROUND
2022-09-09 18:42:28 +00:00
" listring[current_player;main] " ..
2021-09-18 07:53:45 +00:00
sf ( " listring[nodemeta:%s,%s,%s;main] " , pos_other.x , pos_other.y , pos_other.z ) ,
" listring[current_player;main] " ,
sf ( " listring[nodemeta:%s,%s,%s;main] " , pos.x , pos.y , pos.z ) ,
} )
)
2021-05-29 14:12:33 +00:00
if on_rightclick_addendum_right then
on_rightclick_addendum_right ( pos , node , clicker )
end
2021-01-03 17:16:12 +00:00
2022-09-09 18:42:28 +00:00
player_chest_open ( clicker , pos_other , left_name , left_textures , node.param2 , true , " default_chest " ,
" mcl_chests_chest " )
2021-05-29 14:12:33 +00:00
end ,
mesecons = mesecons ,
on_rotate = no_rotate ,
} )
2017-03-20 17:12:05 +00:00
2021-05-29 14:12:33 +00:00
if mod_doc then
2022-09-09 18:42:28 +00:00
doc.add_entry_alias ( " nodes " , small_name , " nodes " , " mcl_chests: " .. basename .. " _left " )
doc.add_entry_alias ( " nodes " , small_name , " nodes " , " mcl_chests: " .. basename .. " _right " )
2021-05-29 14:12:33 +00:00
end
2017-03-20 17:12:05 +00:00
2021-05-29 14:12:33 +00:00
-- END OF register_chest FUNCTION BODY
2017-03-16 00:48:52 +00:00
end
2019-03-14 05:20:05 +00:00
local chestusage = S ( " To access its inventory, rightclick it. When broken, the items will drop out. " )
2017-03-16 00:48:52 +00:00
register_chest ( " chest " ,
2019-03-07 22:40:43 +00:00
S ( " Chest " ) ,
2022-09-09 18:42:28 +00:00
S (
2022-09-10 16:32:37 +00:00
" Chests are containers which provide 27 inventory slots. Chests can be turned into large chests with double the capacity by placing two chests next to each other. " )
2022-09-09 18:42:28 +00:00
,
2019-03-14 05:20:05 +00:00
chestusage ,
2020-03-12 00:35:11 +00:00
S ( " 27 inventory slots " ) .. " \n " .. S ( " Can be combined to a large chest " ) ,
2018-01-26 22:13:44 +00:00
{
2021-12-11 16:16:10 +00:00
small = tiles_chest_normal_small ,
double = tiles_chest_normal_double ,
2022-09-09 18:42:28 +00:00
inv = { " default_chest_top.png " , " mcl_chests_chest_bottom.png " ,
" mcl_chests_chest_right.png " , " mcl_chests_chest_left.png " ,
" mcl_chests_chest_back.png " , " default_chest_front.png " } ,
--[[left = {"default_chest_top_big.png", "default_chest_top_big.png",
" mcl_chests_chest_right.png " , " mcl_chests_chest_left.png " ,
" default_chest_side_big.png^[transformFX " , " default_chest_front_big.png " } ,
right = { " default_chest_top_big.png^[transformFX " , " default_chest_top_big.png^[transformFX " ,
" mcl_chests_chest_right.png " , " mcl_chests_chest_left.png " ,
" default_chest_side_big.png " , " default_chest_front_big.png^[transformFX " } , ] ] --
2018-01-26 22:13:44 +00:00
} ,
2017-03-20 15:38:16 +00:00
false
2017-03-16 00:48:52 +00:00
)
2018-01-26 22:13:44 +00:00
local traptiles = {
2021-12-11 16:16:10 +00:00
small = tiles_chest_trapped_small ,
double = tiles_chest_trapped_double ,
2018-01-26 22:13:44 +00:00
}
2017-03-16 00:48:52 +00:00
register_chest ( " trapped_chest " ,
2019-03-07 22:40:43 +00:00
S ( " Trapped Chest " ) ,
2022-09-09 18:42:28 +00:00
S (
2022-09-10 16:32:37 +00:00
" A trapped chest is a container which provides 27 inventory slots. When it is opened, it sends a redstone signal to its adjacent blocks as long it stays open. Trapped chests can be turned into large trapped chests with double the capacity by placing two trapped chests next to each other. " )
2022-09-09 18:42:28 +00:00
,
2019-03-14 05:20:05 +00:00
chestusage ,
2022-09-09 18:42:28 +00:00
S ( " 27 inventory slots " ) ..
" \n " .. S ( " Can be combined to a large chest " ) .. " \n " .. S ( " Emits a redstone signal when opened " ) ,
2018-01-26 22:13:44 +00:00
traptiles ,
2017-03-20 15:38:16 +00:00
nil ,
2021-09-17 22:36:33 +00:00
{
receptor = {
state = mesecon.state . off ,
rules = trapped_chest_mesecons_rules ,
} ,
} ,
2017-03-16 03:16:37 +00:00
function ( pos , node , clicker )
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_on_small " , param2 = node.param2 } )
find_or_create_entity ( pos , " mcl_chests:trapped_chest_on_small " , { " mcl_chests_trapped.png " } , node.param2 , false ,
" default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_on_small " )
2017-07-30 22:12:21 +00:00
mesecon.receptor_on ( pos , trapped_chest_mesecons_rules )
2017-03-16 03:16:37 +00:00
end ,
function ( pos , node , clicker )
local meta = minetest.get_meta ( pos )
meta : set_int ( " players " , 1 )
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_on_left " , param2 = node.param2 } )
find_or_create_entity ( pos , " mcl_chests:trapped_chest_on_left " , tiles_chest_trapped_double , node.param2 , true ,
" default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_on_left " )
2017-07-30 22:12:21 +00:00
mesecon.receptor_on ( pos , trapped_chest_mesecons_rules )
2017-03-16 03:16:37 +00:00
2017-08-03 21:27:22 +00:00
local pos_other = mcl_util.get_double_container_neighbor_pos ( pos , node.param2 , " left " )
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos_other , { name = " mcl_chests:trapped_chest_on_right " , param2 = node.param2 } )
2017-07-30 22:12:21 +00:00
mesecon.receptor_on ( pos_other , trapped_chest_mesecons_rules )
2017-03-16 03:16:37 +00:00
end ,
function ( pos , node , clicker )
2017-08-03 21:27:22 +00:00
local pos_other = mcl_util.get_double_container_neighbor_pos ( pos , node.param2 , " right " )
2017-03-16 03:16:37 +00:00
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_on_right " , param2 = node.param2 } )
2017-07-30 22:12:21 +00:00
mesecon.receptor_on ( pos , trapped_chest_mesecons_rules )
2017-03-16 03:16:37 +00:00
2022-09-09 18:42:28 +00:00
minetest.swap_node ( pos_other , { name = " mcl_chests:trapped_chest_on_left " , param2 = node.param2 } )
find_or_create_entity ( pos_other , " mcl_chests:trapped_chest_on_left " , tiles_chest_trapped_double , node.param2 ,
true ,
" default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_on_left " )
2017-07-30 22:12:21 +00:00
mesecon.receptor_on ( pos_other , trapped_chest_mesecons_rules )
2017-03-16 03:16:37 +00:00
end
2017-03-16 01:13:35 +00:00
)
register_chest ( " trapped_chest_on " ,
2020-03-08 07:50:21 +00:00
nil , nil , nil , nil , traptiles , true ,
2021-09-17 22:36:33 +00:00
{
receptor = {
state = mesecon.state . on ,
rules = trapped_chest_mesecons_rules ,
} ,
} ,
2021-01-03 13:21:35 +00:00
nil , nil , nil ,
2018-01-26 22:43:33 +00:00
" trapped_chest " ,
2017-03-16 03:16:37 +00:00
" trapped_chest "
2017-03-16 00:48:52 +00:00
)
2017-01-27 11:42:05 +00:00
2021-05-22 22:31:22 +00:00
--[[local function close_if_trapped_chest(pos, player)
2018-01-26 23:34:37 +00:00
local node = minetest.get_node ( pos )
2021-01-03 17:52:24 +00:00
if node.name == " mcl_chests:trapped_chest_on_small " then
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_small " , param2 = node.param2 } )
2021-01-28 19:53:57 +00:00
find_or_create_entity ( pos , " mcl_chests:trapped_chest_small " , { " mcl_chests_trapped.png " } , node.param2 , false , " default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_small " )
2018-01-26 23:34:37 +00:00
mesecon.receptor_off ( pos , trapped_chest_mesecons_rules )
player_chest_close ( player )
elseif node.name == " mcl_chests:trapped_chest_on_left " then
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_left " , param2 = node.param2 } )
2021-12-11 16:16:10 +00:00
find_or_create_entity ( pos , " mcl_chests:trapped_chest_left " , tiles_chest_trapped_double , node.param2 , true , " default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_left " )
2018-01-26 23:34:37 +00:00
mesecon.receptor_off ( pos , trapped_chest_mesecons_rules )
local pos_other = mcl_util.get_double_container_neighbor_pos ( pos , node.param2 , " left " )
minetest.swap_node ( pos_other , { name = " mcl_chests:trapped_chest_right " , param2 = node.param2 } )
mesecon.receptor_off ( pos_other , trapped_chest_mesecons_rules )
player_chest_close ( player )
elseif node.name == " mcl_chests:trapped_chest_on_right " then
minetest.swap_node ( pos , { name = " mcl_chests:trapped_chest_right " , param2 = node.param2 } )
mesecon.receptor_off ( pos , trapped_chest_mesecons_rules )
local pos_other = mcl_util.get_double_container_neighbor_pos ( pos , node.param2 , " right " )
minetest.swap_node ( pos_other , { name = " mcl_chests:trapped_chest_left " , param2 = node.param2 } )
2021-12-11 16:16:10 +00:00
find_or_create_entity ( pos_other , " mcl_chests:trapped_chest_left " , tiles_chest_trapped_double , node.param2 , true , " default_chest " , " mcl_chests_chest " , " chest " ) : reinitialize ( " mcl_chests:trapped_chest_left " )
2018-01-26 23:34:37 +00:00
mesecon.receptor_off ( pos_other , trapped_chest_mesecons_rules )
player_chest_close ( player )
end
2021-05-22 22:31:22 +00:00
end ] ]
2018-01-26 23:34:37 +00:00
2021-01-03 13:21:35 +00:00
-- Disable chest when it has been closed
2017-03-16 03:16:37 +00:00
minetest.register_on_player_receive_fields ( function ( player , formname , fields )
2021-01-03 13:21:35 +00:00
if formname : find ( " mcl_chests: " ) == 1 then
2017-03-16 03:16:37 +00:00
if fields.quit then
2018-01-26 23:34:37 +00:00
player_chest_close ( player )
2017-03-16 03:16:37 +00:00
end
end
end )
2018-01-26 23:34:37 +00:00
minetest.register_on_leaveplayer ( function ( player )
player_chest_close ( player )
end )
2017-01-27 11:42:05 +00:00
minetest.register_craft ( {
2021-05-29 14:12:33 +00:00
output = " mcl_chests:chest " ,
2017-01-27 11:42:05 +00:00
recipe = {
2022-09-09 18:42:28 +00:00
{ " group:wood " , " group:wood " , " group:wood " } ,
{ " group:wood " , " " , " group:wood " } ,
{ " group:wood " , " group:wood " , " group:wood " } ,
2021-09-17 22:36:33 +00:00
} ,
2017-01-31 22:32:56 +00:00
} )
2017-02-06 20:33:38 +00:00
2017-02-13 13:33:16 +00:00
minetest.register_craft ( {
2021-05-29 14:12:33 +00:00
type = " fuel " ,
recipe = " mcl_chests:chest " ,
2021-09-17 22:36:33 +00:00
burntime = 15 ,
2017-02-13 13:33:16 +00:00
} )
2017-03-16 00:48:52 +00:00
minetest.register_craft ( {
2021-05-29 14:12:33 +00:00
type = " fuel " ,
recipe = " mcl_chests:trapped_chest " ,
2021-09-17 22:36:33 +00:00
burntime = 15 ,
2017-03-16 00:48:52 +00:00
} )
2021-01-04 10:26:07 +00:00
minetest.register_node ( " mcl_chests:ender_chest " , {
description = S ( " Ender Chest " ) ,
2022-09-09 18:42:28 +00:00
_tt_help = S ( " 27 interdimensional inventory slots " ) ..
2022-09-10 16:32:37 +00:00
" \n " .. S ( " Put items inside, retrieve them from any ender chest " ) ,
2022-09-09 18:42:28 +00:00
_doc_items_longdesc = S (
2022-09-10 16:32:37 +00:00
" Ender chests grant you access to a single personal interdimensional inventory with 27 slots. This inventory is the same no matter from which ender chest you access it from. If you put one item into one ender chest, you will find it in all other ender chests. Each player will only see their own items, but not the items of other players. " ) ,
2021-01-04 10:26:07 +00:00
_doc_items_usagehelp = S ( " Rightclick the ender chest to access your personal interdimensional inventory. " ) ,
drawtype = " mesh " ,
2022-10-18 15:25:25 +00:00
mesh = " mcl_chests_chest.b3d " ,
2021-12-11 16:16:10 +00:00
tiles = tiles_chest_ender_small ,
2022-09-10 16:32:37 +00:00
use_texture_alpha = " opaque " ,
2021-01-04 10:26:07 +00:00
paramtype = " light " ,
paramtype2 = " facedir " ,
2022-09-09 18:42:28 +00:00
groups = { deco_block = 1 } ,
2021-01-04 10:26:07 +00:00
sounds = mcl_sounds.node_sound_stone_defaults ( ) ,
2022-09-10 16:32:37 +00:00
on_construct = function ( pos )
2021-01-04 10:26:07 +00:00
local node = minetest.get_node ( pos )
node.name = " mcl_chests:ender_chest_small "
minetest.set_node ( pos , node )
end ,
} )
2021-09-17 21:58:58 +00:00
local formspec_ender_chest = table.concat ( {
" formspec_version[4] " ,
2021-09-18 07:53:45 +00:00
" size[11.75,10.425] " ,
2021-09-17 21:58:58 +00:00
2022-09-09 18:42:28 +00:00
" label[0.375,0.375; " .. F ( C ( mcl_formspec.label_color , S ( " Ender Chest " ) ) ) .. " ] " ,
2021-09-17 21:58:58 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 0.75 , 9 , 3 ) ,
" list[current_player;enderchest;0.375,0.75;9,3;] " ,
2022-09-09 18:42:28 +00:00
" label[0.375,4.7; " .. F ( C ( mcl_formspec.label_color , S ( " Inventory " ) ) ) .. " ] " ,
2021-09-17 21:58:58 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 5.1 , 9 , 3 ) ,
" list[current_player;main;0.375,5.1;9,3;9] " ,
2021-09-18 07:53:45 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 9.05 , 9 , 1 ) ,
" list[current_player;main;0.375,9.05;9,1;] " ,
2021-09-17 21:58:58 +00:00
" listring[current_player;enderchest] " ,
" listring[current_player;main] " ,
} )
2020-03-29 12:35:01 +00:00
2021-01-04 10:26:07 +00:00
minetest.register_node ( " mcl_chests:ender_chest_small " , {
2019-03-07 22:40:43 +00:00
description = S ( " Ender Chest " ) ,
2022-09-09 18:42:28 +00:00
_tt_help = S ( " 27 interdimensional inventory slots " ) ..
2022-09-10 16:32:37 +00:00
" \n " .. S ( " Put items inside, retrieve them from any ender chest " ) ,
2022-09-09 18:42:28 +00:00
_doc_items_longdesc = S (
2022-09-10 16:32:37 +00:00
" Ender chests grant you access to a single personal interdimensional inventory with 27 slots. This inventory is the same no matter from which ender chest you access it from. If you put one item into one ender chest, you will find it in all other ender chests. Each player will only see their own items, but not the items of other players. " ) ,
2019-03-07 22:40:43 +00:00
_doc_items_usagehelp = S ( " Rightclick the ender chest to access your personal interdimensional inventory. " ) ,
2021-01-04 10:26:07 +00:00
drawtype = " nodebox " ,
node_box = {
type = " fixed " ,
2022-09-09 18:42:28 +00:00
fixed = { - 0.4375 , - 0.5 , - 0.4375 , 0.4375 , 0.375 , 0.4375 } ,
2021-01-04 10:26:07 +00:00
} ,
2022-12-24 14:44:06 +00:00
_chest_entity_textures = ender_chest_texture ,
2021-01-04 10:26:07 +00:00
_chest_entity_sound = " mcl_chests_enderchest " ,
_chest_entity_mesh = " mcl_chests_chest " ,
2021-01-28 19:53:57 +00:00
_chest_entity_animation_type = " chest " ,
2022-09-09 18:42:28 +00:00
tiles = { " blank.png^[resize:16x16 " } ,
2022-09-10 16:32:37 +00:00
use_texture_alpha = " clip " ,
2017-02-13 18:06:12 +00:00
-- Note: The “container” group is missing here because the ender chest does not
-- have an inventory on its own
2022-09-09 18:42:28 +00:00
groups = { pickaxey = 1 , deco_block = 1 , material_stone = 1 , chest_entity = 1 , not_in_creative_inventory = 1 } ,
2017-02-06 20:33:38 +00:00
is_ground_content = false ,
2017-02-06 21:10:20 +00:00
paramtype = " light " ,
2017-02-06 20:33:38 +00:00
light_source = 7 ,
paramtype2 = " facedir " ,
2017-02-11 17:46:23 +00:00
sounds = mcl_sounds.node_sound_stone_defaults ( ) ,
2017-02-06 20:33:38 +00:00
drop = " mcl_core:obsidian 8 " ,
on_construct = function ( pos )
2022-09-09 18:42:28 +00:00
create_entity ( pos , " mcl_chests:ender_chest_small " , ender_chest_texture , minetest.get_node ( pos ) . param2 , false ,
" mcl_chests_enderchest " , " mcl_chests_chest " , " chest " )
2021-01-04 10:26:07 +00:00
end ,
on_rightclick = function ( pos , node , clicker )
2022-09-10 16:32:37 +00:00
if minetest.registered_nodes [ minetest.get_node ( vector.offset ( pos , 0 , 1 , 0 ) ) . name ] . groups.opaque == 1 then
2022-09-09 18:42:28 +00:00
-- won't open if there is no space from the top
return false
2021-04-06 14:17:02 +00:00
end
2022-09-09 18:42:28 +00:00
minetest.show_formspec ( clicker : get_player_name ( ) , " mcl_chests:ender_chest_ " .. clicker : get_player_name ( ) ,
formspec_ender_chest )
player_chest_open ( clicker , pos , " mcl_chests:ender_chest_small " , ender_chest_texture , node.param2 , false ,
" mcl_chests_enderchest " , " mcl_chests_chest " )
2021-01-04 10:26:07 +00:00
end ,
on_receive_fields = function ( pos , formname , fields , sender )
if fields.quit then
player_chest_close ( sender )
end
2017-02-06 20:33:38 +00:00
end ,
2017-02-22 15:03:59 +00:00
_mcl_blast_resistance = 3000 ,
2017-02-27 00:13:03 +00:00
_mcl_hardness = 22.5 ,
2022-09-09 18:42:28 +00:00
_mcl_silk_touch_drop = { " mcl_chests:ender_chest " } ,
2017-12-05 13:09:39 +00:00
on_rotate = simple_rotate ,
2017-02-06 20:33:38 +00:00
} )
minetest.register_on_joinplayer ( function ( player )
local inv = player : get_inventory ( )
2022-09-09 18:42:28 +00:00
inv : set_size ( " enderchest " , 9 * 3 )
2017-02-06 20:33:38 +00:00
end )
2021-12-02 15:19:59 +00:00
minetest.register_allow_player_inventory_action ( function ( player , action , inv , info )
if inv : get_location ( ) . type == " player " and (
2022-09-09 18:42:28 +00:00
action == " move " and ( info.from_list == " enderchest " or info.to_list == " enderchest " )
or action == " put " and info.listname == " enderchest "
or action == " take " and info.listname == " enderchest "
) then
2021-12-02 15:19:59 +00:00
local def = player : get_wielded_item ( ) : get_definition ( )
2023-02-01 15:56:12 +00:00
local range = ( def and def.range or player : get_inventory ( ) : get_stack ( " hand " , 1 ) : get_definition ( ) . range ) + 1
if not minetest.find_node_near ( player : get_pos ( ) , range , " mcl_chests:ender_chest_small " , true ) then
2021-12-02 15:19:59 +00:00
return 0
end
end
end )
2017-02-06 20:33:38 +00:00
minetest.register_craft ( {
2021-05-29 14:12:33 +00:00
output = " mcl_chests:ender_chest " ,
2017-02-06 20:33:38 +00:00
recipe = {
2022-09-09 18:42:28 +00:00
{ " mcl_core:obsidian " , " mcl_core:obsidian " , " mcl_core:obsidian " } ,
{ " mcl_core:obsidian " , " mcl_end:ender_eye " , " mcl_core:obsidian " } ,
{ " mcl_core:obsidian " , " mcl_core:obsidian " , " mcl_core:obsidian " } ,
2021-09-17 22:36:33 +00:00
} ,
2017-02-06 20:33:38 +00:00
} )
2017-02-07 00:17:00 +00:00
-- Shulker boxes
local boxtypes = {
2019-03-07 22:40:43 +00:00
white = S ( " White Shulker Box " ) ,
grey = S ( " Light Grey Shulker Box " ) ,
orange = S ( " Orange Shulker Box " ) ,
cyan = S ( " Cyan Shulker Box " ) ,
magenta = S ( " Magenta Shulker Box " ) ,
violet = S ( " Purple Shulker Box " ) ,
lightblue = S ( " Light Blue Shulker Box " ) ,
blue = S ( " Blue Shulker Box " ) ,
yellow = S ( " Yellow Shulker Box " ) ,
brown = S ( " Brown Shulker Box " ) ,
green = S ( " Lime Shulker Box " ) ,
dark_green = S ( " Green Shulker Box " ) ,
pink = S ( " Pink Shulker Box " ) ,
red = S ( " Red Shulker Box " ) ,
dark_grey = S ( " Grey Shulker Box " ) ,
black = S ( " Black Shulker Box " ) ,
2017-02-07 00:17:00 +00:00
}
2017-07-19 16:09:50 +00:00
local shulker_mob_textures = {
white = " mobs_mc_shulker_white.png " ,
grey = " mobs_mc_shulker_silver.png " ,
orange = " mobs_mc_shulker_orange.png " ,
cyan = " mobs_mc_shulker_cyan.png " ,
magenta = " mobs_mc_shulker_magenta.png " ,
violet = " mobs_mc_shulker_purple.png " ,
lightblue = " mobs_mc_shulker_light_blue.png " ,
blue = " mobs_mc_shulker_blue.png " ,
yellow = " mobs_mc_shulker_yellow.png " ,
brown = " mobs_mc_shulker_brown.png " ,
green = " mobs_mc_shulker_lime.png " ,
dark_green = " mobs_mc_shulker_green.png " ,
pink = " mobs_mc_shulker_pink.png " ,
red = " mobs_mc_shulker_red.png " ,
dark_grey = " mobs_mc_shulker_gray.png " ,
black = " mobs_mc_shulker_black.png " ,
}
2019-03-24 08:30:15 +00:00
local canonical_shulker_color = " violet "
2017-07-19 16:09:50 +00:00
2021-09-17 22:36:33 +00:00
--WARNING: after formspec v4 update, old shulker boxes will need to be placed again to get the new formspec
2020-07-27 17:26:01 +00:00
local function formspec_shulker_box ( name )
2021-09-17 22:36:33 +00:00
if not name or name == " " then
2020-07-27 17:26:01 +00:00
name = S ( " Shulker Box " )
end
2021-09-17 22:36:33 +00:00
return table.concat ( {
" formspec_version[4] " ,
2021-09-18 07:53:45 +00:00
" size[11.75,10.425] " ,
2021-09-17 22:36:33 +00:00
2022-09-09 18:42:28 +00:00
" label[0.375,0.375; " .. F ( C ( mcl_formspec.label_color , name ) ) .. " ] " ,
2021-09-17 22:36:33 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 0.75 , 9 , 3 ) ,
" list[context;main;0.375,0.75;9,3;] " ,
2022-09-09 18:42:28 +00:00
" label[0.375,4.7; " .. F ( C ( mcl_formspec.label_color , S ( " Inventory " ) ) ) .. " ] " ,
2021-09-17 22:36:33 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 5.1 , 9 , 3 ) ,
" list[current_player;main;0.375,5.1;9,3;9] " ,
2021-09-18 07:53:45 +00:00
mcl_formspec.get_itemslot_bg_v4 ( 0.375 , 9.05 , 9 , 1 ) ,
" list[current_player;main;0.375,9.05;9,1;] " ,
2021-09-17 22:36:33 +00:00
" listring[context;main] " ,
" listring[current_player;main] " ,
} )
2020-07-27 17:26:01 +00:00
end
local function set_shulkerbox_meta ( nmeta , imeta )
local name = imeta : get_string ( " name " )
nmeta : set_string ( " description " , imeta : get_string ( " description " ) )
nmeta : set_string ( " name " , name )
nmeta : set_string ( " formspec " , formspec_shulker_box ( name ) )
end
2020-03-29 12:35:01 +00:00
2017-02-07 00:17:00 +00:00
for color , desc in pairs ( boxtypes ) do
2017-07-19 16:09:50 +00:00
local mob_texture = shulker_mob_textures [ color ]
2019-03-24 08:30:15 +00:00
local is_canonical = color == canonical_shulker_color
local longdesc , usagehelp , create_entry , entry_name
if mod_doc then
if is_canonical then
2022-09-09 18:42:28 +00:00
longdesc = S (
2022-09-10 16:32:37 +00:00
" A shulker box is a portable container which provides 27 inventory slots for any item except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes as well as their contents can be taken as a single item. Shulker boxes come in many different colors. " )
2022-09-09 18:42:28 +00:00
usagehelp = S (
2022-09-10 16:32:37 +00:00
" To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out. Place the shulker box again to be able to retrieve its contents. " )
2019-03-24 08:30:15 +00:00
entry_name = S ( " Shulker Box " )
else
create_entry = false
end
end
2022-09-09 18:42:28 +00:00
local small_name = " mcl_chests: " .. color .. " _shulker_box_small "
2021-01-28 19:53:57 +00:00
2022-09-09 18:42:28 +00:00
minetest.register_node ( " mcl_chests: " .. color .. " _shulker_box " , {
2017-02-07 00:17:00 +00:00
description = desc ,
2020-03-08 07:50:21 +00:00
_tt_help = S ( " 27 inventory slots " ) .. " \n " .. S ( " Can be carried around with its contents " ) ,
2019-03-24 08:30:15 +00:00
_doc_items_create_entry = create_entry ,
_doc_items_entry_name = entry_name ,
_doc_items_longdesc = longdesc ,
_doc_items_usagehelp = usagehelp ,
2022-09-09 18:42:28 +00:00
tiles = { mob_texture } ,
2022-09-10 16:32:37 +00:00
use_texture_alpha = " opaque " ,
2021-01-28 19:53:57 +00:00
drawtype = " mesh " ,
2022-10-18 15:25:25 +00:00
mesh = " mcl_chests_shulker.b3d " ,
2022-09-09 18:42:28 +00:00
groups = {
handy = 1 ,
pickaxey = 1 ,
container = 3 ,
deco_block = 1 ,
dig_by_piston = 1 ,
shulker_box = 1 ,
old_shulker_box_node = 1
} ,
2017-02-07 00:17:00 +00:00
is_ground_content = false ,
2017-02-11 17:46:23 +00:00
sounds = mcl_sounds.node_sound_stone_defaults ( ) ,
2017-02-07 00:17:00 +00:00
stack_max = 1 ,
drop = " " ,
2017-06-13 12:46:21 +00:00
paramtype = " light " ,
2017-06-12 20:36:31 +00:00
paramtype2 = " facedir " ,
2017-02-07 00:17:00 +00:00
on_construct = function ( pos )
2021-01-28 19:53:57 +00:00
local node = minetest.get_node ( pos )
node.name = small_name
minetest.set_node ( pos , node )
end ,
after_place_node = function ( pos , placer , itemstack , pointed_thing )
local nmeta = minetest.get_meta ( pos )
local imetadata = itemstack : get_metadata ( )
local iinv_main = minetest.deserialize ( imetadata )
local ninv = nmeta : get_inventory ( )
ninv : set_list ( " main " , iinv_main )
2022-09-09 18:42:28 +00:00
ninv : set_size ( " main " , 9 * 3 )
2021-01-28 19:53:57 +00:00
set_shulkerbox_meta ( nmeta , itemstack : get_meta ( ) )
if minetest.is_creative_enabled ( placer : get_player_name ( ) ) then
if not ninv : is_empty ( " main " ) then
return nil
else
return itemstack
end
else
return nil
end
2017-02-07 00:17:00 +00:00
end ,
2018-02-01 21:45:19 +00:00
_on_dispense = function ( stack , pos , droppos , dropnode , dropdir )
-- Place shulker box as node
if minetest.registered_nodes [ dropnode.name ] . buildable_to then
2022-09-09 18:42:28 +00:00
minetest.set_node ( droppos , { name = small_name , param2 = minetest.dir_to_facedir ( dropdir ) } )
local ninv = minetest.get_inventory ( { type = " node " , pos = droppos } )
2020-07-23 19:34:13 +00:00
local imetadata = stack : get_metadata ( )
local iinv_main = minetest.deserialize ( imetadata )
2018-02-01 21:45:19 +00:00
ninv : set_list ( " main " , iinv_main )
2022-09-09 18:42:28 +00:00
ninv : set_size ( " main " , 9 * 3 )
2020-07-27 17:26:01 +00:00
set_shulkerbox_meta ( minetest.get_meta ( droppos ) , stack : get_meta ( ) )
2018-02-01 21:45:19 +00:00
stack : take_item ( )
end
return stack
end ,
2021-01-28 19:53:57 +00:00
} )
minetest.register_node ( small_name , {
description = desc ,
_tt_help = S ( " 27 inventory slots " ) .. " \n " .. S ( " Can be carried around with its contents " ) ,
_doc_items_create_entry = create_entry ,
_doc_items_entry_name = entry_name ,
_doc_items_longdesc = longdesc ,
_doc_items_usagehelp = usagehelp ,
drawtype = " nodebox " ,
2022-11-13 21:30:16 +00:00
node_box = {
type = " fixed " ,
2022-09-09 18:42:28 +00:00
fixed = { - 0.48 , - 0.5 , - 0.48 , 0.48 , 0.489 , 0.48 } ,
2022-11-13 21:30:16 +00:00
} ,
2022-09-09 18:42:28 +00:00
tiles = { " blank.png^[resize:16x16 " } ,
2022-09-10 16:32:37 +00:00
use_texture_alpha = " clip " ,
2022-09-09 18:42:28 +00:00
_chest_entity_textures = { mob_texture } ,
2021-01-28 19:53:57 +00:00
_chest_entity_sound = " mcl_chests_shulker " ,
_chest_entity_mesh = " mcl_chests_shulker " ,
_chest_entity_animation_type = " shulker " ,
2022-09-09 18:42:28 +00:00
groups = {
handy = 1 ,
pickaxey = 1 ,
container = 3 ,
deco_block = 1 ,
dig_by_piston = 1 ,
shulker_box = 1 ,
chest_entity = 1 ,
not_in_creative_inventory = 1
} ,
2021-01-28 19:53:57 +00:00
is_ground_content = false ,
sounds = mcl_sounds.node_sound_stone_defaults ( ) ,
stack_max = 1 ,
drop = " " ,
paramtype = " light " ,
paramtype2 = " facedir " ,
2021-09-17 22:36:33 +00:00
-- TODO: Make shulker boxes rotatable
-- This doesn't work, it just destroys the inventory:
-- on_place = minetest.rotate_node,
2021-01-28 19:53:57 +00:00
on_construct = function ( pos )
local meta = minetest.get_meta ( pos )
meta : set_string ( " formspec " , formspec_shulker_box ( nil ) )
local inv = meta : get_inventory ( )
2022-09-09 18:42:28 +00:00
inv : set_size ( " main " , 9 * 3 )
create_entity ( pos , small_name , { mob_texture } , minetest.get_node ( pos ) . param2 , false , " mcl_chests_shulker " ,
" mcl_chests_shulker " , " shulker " )
2021-01-28 19:53:57 +00:00
end ,
2017-02-07 00:17:00 +00:00
after_place_node = function ( pos , placer , itemstack , pointed_thing )
local nmeta = minetest.get_meta ( pos )
2020-07-23 19:34:13 +00:00
local imetadata = itemstack : get_metadata ( )
local iinv_main = minetest.deserialize ( imetadata )
2017-02-07 00:17:00 +00:00
local ninv = nmeta : get_inventory ( )
ninv : set_list ( " main " , iinv_main )
2022-09-09 18:42:28 +00:00
ninv : set_size ( " main " , 9 * 3 )
2020-07-27 17:26:01 +00:00
set_shulkerbox_meta ( nmeta , itemstack : get_meta ( ) )
2020-07-23 19:34:13 +00:00
2020-07-10 14:08:40 +00:00
if minetest.is_creative_enabled ( placer : get_player_name ( ) ) then
2017-02-08 20:16:18 +00:00
if not ninv : is_empty ( " main " ) then
return nil
else
return itemstack
end
else
return nil
end
2017-02-07 00:17:00 +00:00
end ,
2021-01-28 19:53:57 +00:00
on_rightclick = function ( pos , node , clicker )
2022-09-09 18:42:28 +00:00
player_chest_open ( clicker , pos , small_name , { mob_texture } , node.param2 , false , " mcl_chests_shulker " ,
" mcl_chests_shulker " , true )
2021-01-28 19:53:57 +00:00
end ,
on_receive_fields = function ( pos , formname , fields , sender )
if fields.quit then
player_chest_close ( sender )
end
end ,
2017-03-30 00:32:46 +00:00
on_destruct = function ( pos )
2017-02-07 00:17:00 +00:00
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
local items = { }
2022-09-09 18:42:28 +00:00
for i = 1 , inv : get_size ( " main " ) do
2017-02-08 20:16:18 +00:00
local stack = inv : get_stack ( " main " , i )
items [ i ] = stack : to_string ( )
2017-02-07 00:17:00 +00:00
end
local data = minetest.serialize ( items )
2022-09-09 18:42:28 +00:00
local boxitem = ItemStack ( " mcl_chests: " .. color .. " _shulker_box " )
2020-07-23 19:34:13 +00:00
local boxitem_meta = boxitem : get_meta ( )
boxitem_meta : set_string ( " description " , meta : get_string ( " description " ) )
boxitem_meta : set_string ( " name " , meta : get_string ( " name " ) )
2017-02-07 00:17:00 +00:00
boxitem : set_metadata ( data )
2017-02-08 20:16:18 +00:00
2020-07-10 14:08:40 +00:00
if minetest.is_creative_enabled ( " " ) then
2017-02-08 20:16:18 +00:00
if not inv : is_empty ( " main " ) then
minetest.add_item ( pos , boxitem )
end
else
minetest.add_item ( pos , boxitem )
end
2017-02-07 00:17:00 +00:00
end ,
2019-02-08 20:59:01 +00:00
allow_metadata_inventory_move = protection_check_move ,
allow_metadata_inventory_take = protection_check_put_take ,
2017-02-07 00:17:00 +00:00
allow_metadata_inventory_put = function ( pos , listname , index , stack , player )
2019-02-08 20:59:01 +00:00
local name = player : get_player_name ( )
if minetest.is_protected ( pos , name ) then
minetest.record_protection_violation ( pos , name )
return 0
end
2017-02-07 00:17:00 +00:00
-- Do not allow to place shulker boxes into shulker boxes
local group = minetest.get_item_group ( stack : get_name ( ) , " shulker_box " )
if group == 0 or group == nil then
return stack : get_count ( )
else
return 0
end
end ,
2020-06-06 14:57:19 +00:00
_mcl_blast_resistance = 6 ,
_mcl_hardness = 2 ,
2017-02-07 00:17:00 +00:00
} )
2019-03-24 08:30:15 +00:00
if mod_doc and not is_canonical then
2022-09-09 18:42:28 +00:00
doc.add_entry_alias ( " nodes " , " mcl_chests: " .. canonical_shulker_color .. " _shulker_box " , " nodes " ,
" mcl_chests: " .. color .. " _shulker_box " )
doc.add_entry_alias ( " nodes " , " mcl_chests: " .. canonical_shulker_color .. " _shulker_box_small " , " nodes " ,
" mcl_chests: " .. color .. " _shulker_box_small " )
2019-03-24 08:30:15 +00:00
end
2017-02-07 00:17:00 +00:00
minetest.register_craft ( {
type = " shapeless " ,
2022-09-09 18:42:28 +00:00
output = " mcl_chests: " .. color .. " _shulker_box " ,
recipe = { " group:shulker_box " , " mcl_dye: " .. color } ,
2017-02-07 00:17:00 +00:00
} )
end
minetest.register_craft ( {
2021-05-29 14:12:33 +00:00
output = " mcl_chests:violet_shulker_box " ,
2017-02-07 00:17:00 +00:00
recipe = {
2022-09-09 18:42:28 +00:00
{ " mcl_mobitems:shulker_shell " } ,
{ " mcl_chests:chest " } ,
{ " mcl_mobitems:shulker_shell " } ,
2021-09-17 22:36:33 +00:00
} ,
2017-02-07 00:17:00 +00:00
} )
2017-02-06 20:33:38 +00:00
2020-01-18 03:46:41 +00:00
-- Save metadata of shulker box when used in crafting
minetest.register_on_craft ( function ( itemstack , player , old_craft_grid , craft_inv )
if minetest.get_item_group ( itemstack : get_name ( ) , " shulker_box " ) ~= 1 then
return
end
local original
for i = 1 , # old_craft_grid do
local item = old_craft_grid [ i ] : get_name ( )
if minetest.get_item_group ( item , " shulker_box " ) == 1 then
original = old_craft_grid [ i ]
break
end
end
if original then
local ometa = original : get_meta ( ) : to_table ( )
local nmeta = itemstack : get_meta ( )
nmeta : from_table ( ometa )
return itemstack
end
end )
2021-01-03 17:16:12 +00:00
local function select_and_spawn_entity ( pos , node )
local node_name = node.name
local node_def = minetest.registered_nodes [ node_name ]
local double_chest = minetest.get_item_group ( node_name , " double_chest " ) > 0
2022-09-09 18:42:28 +00:00
find_or_create_entity ( pos , node_name , node_def._chest_entity_textures , node.param2 , double_chest ,
node_def._chest_entity_sound , node_def._chest_entity_mesh , node_def._chest_entity_animation_type )
2021-01-03 17:16:12 +00:00
end
2021-01-03 13:21:35 +00:00
minetest.register_lbm ( {
label = " Spawn Chest entities " ,
name = " mcl_chests:spawn_chest_entities " ,
2022-09-09 18:42:28 +00:00
nodenames = { " group:chest_entity " } ,
2021-01-03 13:21:35 +00:00
run_at_every_load = true ,
2021-01-03 17:16:12 +00:00
action = select_and_spawn_entity ,
} )
minetest.register_lbm ( {
label = " Replace old chest nodes " ,
name = " mcl_chests:replace_old " ,
2022-09-09 18:42:28 +00:00
nodenames = { " mcl_chests:chest " , " mcl_chests:trapped_chest " , " mcl_chests:trapped_chest_on " ,
" mcl_chests:ender_chest " ,
" group:old_shulker_box_node " } ,
2021-01-04 16:10:07 +00:00
run_at_every_load = true ,
2021-01-03 13:21:35 +00:00
action = function ( pos , node )
2021-01-03 17:52:24 +00:00
local node_name = node.name
node.name = node_name .. " _small "
2021-01-03 18:05:07 +00:00
minetest.swap_node ( pos , node )
2021-01-03 17:16:12 +00:00
select_and_spawn_entity ( pos , node )
2021-01-03 17:52:24 +00:00
if node_name == " mcl_chests:trapped_chest_on " then
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , " [mcl_chests] Disabled active trapped chest on load: " .. minetest.pos_to_string ( pos ) )
2021-01-03 17:52:24 +00:00
chest_update_after_close ( pos )
2021-01-04 10:26:07 +00:00
elseif node_name == " mcl_chests:ender_chest " then
local meta = minetest.get_meta ( pos )
meta : set_string ( " formspec " , formspec_ender_chest )
2021-01-03 17:52:24 +00:00
end
2021-01-03 13:21:35 +00:00
end
} )
2020-01-18 03:46:41 +00:00
2019-03-09 06:59:07 +00:00
minetest.register_lbm ( {
-- Disable active/open trapped chests when loaded because nobody could
-- have them open at loading time.
-- Fixes redstone weirdness.
label = " Disable active trapped chests " ,
name = " mcl_chests:reset_trapped_chests " ,
2022-09-09 18:42:28 +00:00
nodenames = { " mcl_chests:trapped_chest_on_small " , " mcl_chests:trapped_chest_on_left " ,
" mcl_chests:trapped_chest_on_right " } ,
2019-03-09 06:59:07 +00:00
run_at_every_load = true ,
action = function ( pos , node )
2022-09-09 18:42:28 +00:00
minetest.log ( " action " , " [mcl_chests] Disabled active trapped chest on load: " .. minetest.pos_to_string ( pos ) )
2019-03-09 06:59:07 +00:00
chest_update_after_close ( pos )
end ,
} )
2020-03-29 12:35:01 +00:00
minetest.register_lbm ( {
2021-09-17 22:36:33 +00:00
label = " Update shulker box formspecs (0.72.0) " ,
name = " mcl_chests:update_shulker_box_formspecs_0_72_0 " ,
2020-03-29 12:35:01 +00:00
nodenames = { " group:shulker_box " } ,
run_at_every_load = false ,
action = function ( pos , node )
local meta = minetest.get_meta ( pos )
2021-09-17 22:36:33 +00:00
meta : set_string ( " formspec " , formspec_shulker_box ( meta : get_string ( " name " ) ) )
2020-03-29 12:35:01 +00:00
end ,
} )
2021-04-18 09:50:02 +00:00
minetest.register_lbm ( {
label = " Upgrade old ender chest formspec " ,
2021-05-29 14:12:33 +00:00
name = " mcl_chests:replace_old_ender_form " ,
2022-09-09 18:42:28 +00:00
nodenames = { " mcl_chests:ender_chest_small " } ,
2021-05-29 14:12:33 +00:00
run_at_every_load = false ,
action = function ( pos , node )
2021-04-18 09:50:02 +00:00
minetest.get_meta ( pos ) : set_string ( " formspec " , " " )
2021-05-29 14:12:33 +00:00
end ,
2021-04-18 09:50:02 +00:00
} )