forked from mtcontrib/connected_chests
044a91fcd5
There are multiple hopper mods and not all of them support the set_extra_container_info function, so the mod crashes now if it is used together with an incompatible hopper mod. To prevent the crash, execute the code for hopper compatibility if hopper and hopper.set_extra_container_info exist and not if a mod named hopper is installed.
718 lines
21 KiB
Lua
718 lines
21 KiB
Lua
-- for translation
|
|
local S = minetest.get_translator("connected_chests")
|
|
|
|
-- param_tab maps the x and z offset to a param2 value
|
|
local param_tab = {
|
|
["-1 0"] = 0,
|
|
["1 0"] = 2,
|
|
["0 -1"] = 3,
|
|
["0 1"] = 1,
|
|
}
|
|
|
|
-- param_tab2 maps the other way round
|
|
local param_tab2 = {}
|
|
for n,i in pairs(param_tab) do
|
|
param_tab2[i] = n:split" "
|
|
end
|
|
|
|
local function return_remove_next(allowed_name, add_open)
|
|
local function remove_next(pos, oldnode)
|
|
-- if the left node had an unexpected rotation, the right one can't be
|
|
-- found, in this case simply do nothing
|
|
if oldnode.param2 > 3 then
|
|
return
|
|
end
|
|
|
|
-- remove the right one if there is one
|
|
-- (the left one is already removed)
|
|
local x, z = unpack(param_tab2[oldnode.param2])
|
|
pos.x = pos.x-x
|
|
pos.z = pos.z-z
|
|
local right_n = minetest.get_node(pos).name
|
|
if right_n == allowed_name
|
|
or (add_open and right_n == allowed_name .. "_open") then
|
|
minetest.remove_node(pos)
|
|
end
|
|
end
|
|
return remove_next
|
|
end
|
|
|
|
|
|
-- used when constructing the left node
|
|
local function return_add_next(right_name)
|
|
local function add_next(pos, node)
|
|
node = node or minetest.get_node(pos)
|
|
local par = node.param2
|
|
|
|
-- if the left node is set with an unexpected rotation, put the chest
|
|
-- with default rotation
|
|
if par > 3 then
|
|
minetest.log("action",
|
|
node.name .. " with invalid param2 found, pos: " ..
|
|
minetest.pos_to_string(pos) .. ", param2: " .. par)
|
|
node.param2 = 0
|
|
minetest.set_node(pos, node)
|
|
return
|
|
end
|
|
|
|
-- put the right chest if possible
|
|
local x, z = unpack(param_tab2[par])
|
|
pos.x = pos.x-x
|
|
pos.z = pos.z-z
|
|
if minetest.get_node(pos).name == "air" then
|
|
minetest.set_node(pos, {name=right_name, param2=par})
|
|
end
|
|
end
|
|
return add_next
|
|
end
|
|
|
|
|
|
-- gives information about the positions and param to place the nodes
|
|
local function get_pointed_info(pt, name)
|
|
if not pt then
|
|
return
|
|
end
|
|
local pu = minetest.get_pointed_thing_position(pt)
|
|
local pa = minetest.get_pointed_thing_position(pt, true)
|
|
if not pu
|
|
or not pa
|
|
or pu.y ~= pa.y then
|
|
return
|
|
end
|
|
local nd_u = minetest.get_node(pu)
|
|
if nd_u.name ~= name then
|
|
return
|
|
end
|
|
return pu, pa, nd_u.param2
|
|
end
|
|
|
|
|
|
|
|
|
|
local pars = {[0]=2, 3, 0, 1}
|
|
|
|
local chestdata = {}
|
|
|
|
|
|
-- executed when connecting the chests
|
|
local function connect_chests(pu, pa, old_param2, data)
|
|
local metatable = minetest.get_meta(pu):to_table()
|
|
|
|
local par = param_tab[pu.x-pa.x.." "..pu.z-pa.z]
|
|
local par_inverted = pars[par]
|
|
if old_param2 == par_inverted then
|
|
pu, pa = pa, pu
|
|
par = par_inverted
|
|
end
|
|
|
|
data.on_connect(pu, pa, par, metatable)
|
|
end
|
|
|
|
|
|
local tube_to_left, tube_to_left_locked, tube_update, tube_groups
|
|
if minetest.global_exists"pipeworks" then
|
|
tube_to_left_locked = {
|
|
insert_object = function(pos, node, stack)
|
|
local x, z = unpack(param_tab2[node.param2])
|
|
return minetest.get_meta{x=pos.x+x, y=pos.y, z=pos.z+z
|
|
}:get_inventory():add_item("main", stack)
|
|
end,
|
|
can_insert = function(pos, node, stack)
|
|
local x, z = unpack(param_tab2[node.param2])
|
|
return minetest.get_meta{x=pos.x+x, y=pos.y, z=pos.z+z
|
|
}:get_inventory():room_for_item("main", stack)
|
|
end,
|
|
connect_sides = {right = 1, back = 1, front = 1, bottom = 1, top = 1}
|
|
}
|
|
|
|
tube_to_left = table.copy(tube_to_left_locked)
|
|
tube_to_left.input_inventory = "main"
|
|
|
|
tube_update = pipeworks.scan_for_tube_objects
|
|
|
|
tube_groups = {tubedevice=1, tubedevice_receiver=1}
|
|
else
|
|
function tube_update() end
|
|
end
|
|
|
|
|
|
connected_chests = {chestdata = chestdata}
|
|
--[[
|
|
connected_chests.register_chest(<original_node>, {
|
|
description = <string>, -- The name of the connected chest as shown to the
|
|
-- player, i.e. the node metadata infotext
|
|
get_formspec = function(metatable, pos)
|
|
return <formspec_of_big>
|
|
end,
|
|
lock = true, -- indicates whether a lock should be added to the texture
|
|
-- and has an impact on the tube function
|
|
front = <keyhole_texture>, -- if present, this texture is added to the chest
|
|
-- front
|
|
on_rightclick = <func>, -- sets an on_rightclick (some chests need this)
|
|
})
|
|
]]
|
|
|
|
function connected_chests.register_chest(fromname, data)
|
|
chestdata[fromname] = data
|
|
|
|
--~ local mod, name = fromname:split":"
|
|
local name_left = fromname .. "_connected_left"
|
|
local name_right = fromname .. "_connected_right"
|
|
data.left = name_left
|
|
data.right = name_right
|
|
|
|
local description = data.description
|
|
if not description then
|
|
minetest.log("deprecated",
|
|
"Missing connected chest description for " .. fromname)
|
|
description = "Big " .. minetest.registered_nodes[fromname].description
|
|
end
|
|
|
|
-- executed when connecting the chest
|
|
data.on_connect = function(pu, pa, par, metatable)
|
|
minetest.add_node(pu, {name=name_left, param2=par})
|
|
minetest.add_node(pa, {name=name_right, param2=par})
|
|
|
|
if not data.add_open_chest then
|
|
metatable.fields.formspec = data.get_formspec(metatable, pu)
|
|
end
|
|
metatable.fields.infotext = description
|
|
local meta = minetest.get_meta(pu)
|
|
meta:from_table(metatable)
|
|
local inv = meta:get_inventory()
|
|
inv:set_size("main", 65)
|
|
|
|
end
|
|
|
|
-- override the original node to support connecting
|
|
local place_chest = minetest.registered_nodes[fromname].on_place
|
|
local creative_mode = minetest.settings:get_bool"creative_mode"
|
|
minetest.override_item(fromname, {
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if not placer
|
|
or not placer:get_player_control().sneak then
|
|
return place_chest(itemstack, placer, pointed_thing)
|
|
end
|
|
local pu, pa, par2 = get_pointed_info(pointed_thing, fromname)
|
|
if not pu then
|
|
return place_chest(itemstack, placer, pointed_thing)
|
|
end
|
|
if minetest.is_protected(pa, placer:get_player_name()) then
|
|
return
|
|
end
|
|
connect_chests(pu, pa, par2, data)
|
|
if not creative_mode then
|
|
itemstack:take_item()
|
|
return itemstack
|
|
end
|
|
end
|
|
})
|
|
|
|
|
|
-- Adds the big chest nodes
|
|
|
|
-- the left one contains inventory
|
|
local chest = {}
|
|
local origdef = minetest.registered_nodes[fromname]
|
|
for i in pairs(origdef) do
|
|
chest[i] = rawget(origdef, i)
|
|
end
|
|
|
|
local top = chest.tiles[1]
|
|
local side = chest.tiles[4]
|
|
local top_texture = top .. "^([combine:16x16:5,0=" .. top ..
|
|
"^connected_chests_frame.png^[makealpha:255,126,126)"
|
|
local side_texture = side .. "^([combine:16x16:5,0=" .. side ..
|
|
"^connected_chests_frame.png^[makealpha:255,126,126)"
|
|
local inside_texture
|
|
|
|
|
|
chest.description = description
|
|
chest.groups = table.copy(chest.groups)
|
|
chest.groups.not_in_creative_inventory = 1
|
|
chest.legacy_facedir_simple = nil
|
|
chest.after_place_node = nil
|
|
chest.on_receive_fields = nil
|
|
if data.on_rightclick then
|
|
chest.on_rightclick = data.on_rightclick
|
|
end
|
|
|
|
-- disallow rotating a connected chest using a screwdriver
|
|
function chest.on_rotate()
|
|
return false
|
|
end
|
|
|
|
-- copy pipeworks tube data (if requisite)
|
|
if chest.tube then
|
|
chest.tube = table.copy(chest.tube)
|
|
chest.tube.connect_sides = {left = 1, -- no connection to the right.
|
|
back = 1, front = 1, bottom = 1, top = 1}
|
|
end
|
|
|
|
if not data.front then
|
|
data.front = "connected_chests_front.png"
|
|
if data.lock then
|
|
data.front = data.front .. "^connected_chests_lock.png"
|
|
end
|
|
end
|
|
chest.tiles = {top_texture, top_texture, "default_obsidian_glass.png",
|
|
side, side_texture.."^[transformFX", side_texture.."^" .. data.front}
|
|
chest.drop = (chest.drop or fromname) .. " 2"
|
|
chest.selection_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 1.5, 0.5, 0.5},
|
|
},
|
|
}
|
|
chest.on_construct = return_add_next(name_right)
|
|
chest.after_destruct = return_remove_next(name_right, data.add_open_chest)
|
|
|
|
if data.add_open_chest then
|
|
-- mostly copied from default
|
|
local def_opened = table.copy(chest)
|
|
|
|
def_opened.mesh = "connected_chest_open.obj"
|
|
def_opened.drawtype = "mesh"
|
|
def_opened.paramtype = "light"
|
|
for i = 1, #def_opened.tiles do
|
|
if type(def_opened.tiles[i]) == "string" then
|
|
def_opened.tiles[i] =
|
|
{name = def_opened.tiles[i], backface_culling = true}
|
|
elseif def_opened.tiles[i].backface_culling == nil then
|
|
def_opened.tiles[i].backface_culling = true
|
|
end
|
|
end
|
|
def_opened.selection_box = {
|
|
type = "fixed",
|
|
fixed = {-0.5, -0.5, -0.5, 1.5, 3/16, 0.5},
|
|
}
|
|
def_opened.diggable = false
|
|
def_opened.on_blast = function() end
|
|
inside_texture = "default_chest_inside.png^([combine:16x32:5,0=" ..
|
|
"default_chest_inside.png^connected_chests_inside_frame.png^[" ..
|
|
"makealpha:255,126,126)"
|
|
-- TODO, see right chest
|
|
-- here 3 and 4 are swapped and no mirroring is needed…
|
|
def_opened.tiles[3] = def_opened.tiles[4]
|
|
def_opened.tiles[3].name = def_opened.tiles[3].name
|
|
def_opened.tiles[5] = def_opened.tiles[6]
|
|
|
|
def_opened.tiles[6] = inside_texture
|
|
|
|
minetest.register_node(":" .. name_left.. "_open", def_opened)
|
|
end
|
|
|
|
--~ minetest.register_node("connected_chests:chest_left", chest)
|
|
minetest.register_node(":" .. name_left, chest)
|
|
|
|
|
|
-- the right one is the deco one
|
|
local tiles = {top_texture.."^[transformFX", top_texture.."^[transformFX",
|
|
side, "default_obsidian_glass.png", side_texture, side_texture
|
|
.. "^" .. data.front .. "^[transformFX"}
|
|
local right_def = {
|
|
tiles = tiles,
|
|
paramtype2 = "facedir",
|
|
drop = "",
|
|
pointable = false,
|
|
diggable = false,
|
|
on_construct = function(pos)
|
|
local node = minetest.get_node(pos)
|
|
|
|
-- if the right node has an unexpected rotation, try to set it with
|
|
-- a valid one
|
|
if node.param2 > 3 then
|
|
node.param2 = node.param2 % 4
|
|
minetest.set_node(pos, node)
|
|
return
|
|
end
|
|
|
|
-- remove it if the left node can't be found
|
|
local x, z = unpack(param_tab2[node.param2])
|
|
local node_left = minetest.get_node{x=pos.x+x, y=pos.y, z=pos.z+z}
|
|
if node_left.name ~= name_left
|
|
or node_left.param2 ~= node.param2 then
|
|
minetest.remove_node(pos)
|
|
return
|
|
end
|
|
|
|
-- connect pipework tubes if there are any
|
|
tube_update(pos)
|
|
end,
|
|
after_destruct = function(pos, oldnode)
|
|
-- simply remove the right node if it has an unexpected rotation
|
|
if oldnode.param2 > 3 then
|
|
return
|
|
end
|
|
|
|
-- add it back if the left node is still there
|
|
local x, z = unpack(param_tab2[oldnode.param2])
|
|
local node_left = minetest.get_node{x=pos.x+x, y=pos.y, z=pos.z+z}
|
|
if node_left.name == name_left
|
|
and node_left.param2 == oldnode.param2
|
|
and minetest.get_node(pos).name == "air" then
|
|
minetest.set_node(pos, oldnode)
|
|
return
|
|
end
|
|
|
|
-- disconnect pipework tubes if there are any
|
|
tube_update(pos)
|
|
end,
|
|
tube = data.lock and tube_to_left_locked or tube_to_left,
|
|
groups = tube_groups,
|
|
}
|
|
|
|
if data.add_open_chest then
|
|
local def_opened = table.copy(right_def)
|
|
|
|
def_opened.mesh = "connected_chest_open.obj"
|
|
def_opened.drawtype = "mesh"
|
|
def_opened.paramtype = "light"
|
|
for i = 1, #def_opened.tiles do
|
|
if type(def_opened.tiles[i]) == "string" then
|
|
def_opened.tiles[i] =
|
|
{name = def_opened.tiles[i], backface_culling = true}
|
|
elseif def_opened.tiles[i].backface_culling == nil then
|
|
def_opened.tiles[i].backface_culling = true
|
|
end
|
|
end
|
|
|
|
-- fix right side, somehow
|
|
def_opened.tiles[4] = def_opened.tiles[3]
|
|
def_opened.tiles[4].name = def_opened.tiles[4].name .. "^[transformFX"
|
|
|
|
-- fix front side
|
|
def_opened.tiles[5] = def_opened.tiles[6]
|
|
|
|
-- add inside
|
|
def_opened.tiles[6] = inside_texture .. "^[transformFX"
|
|
|
|
-- TODO: back side looks like right side
|
|
|
|
minetest.register_node(":" .. name_right .. "_open", def_opened)
|
|
end
|
|
|
|
minetest.register_node(":" .. name_right, right_def)
|
|
|
|
|
|
-- LBMs to fix half chests if they occur for some reason
|
|
minetest.register_lbm{
|
|
label = "Connected Chest fixer " .. name_right,
|
|
name = ":" .. name_right .. "_reconnect_lbm",
|
|
nodenames = {name_right},
|
|
run_at_every_load = true,
|
|
action = function(pos, node)
|
|
if node.param2 > 3 then
|
|
node.param2 = node.param2%4
|
|
minetest.set_node(pos, node)
|
|
return
|
|
end
|
|
local x, z = unpack(param_tab2[node.param2])
|
|
local left_node = minetest.get_node{x=pos.x+x, y=pos.y, z=pos.z+z}
|
|
if left_node.name ~= name_left
|
|
or left_node.param2 ~= node.param2 then
|
|
minetest.remove_node(pos)
|
|
end
|
|
end,
|
|
}
|
|
minetest.register_lbm{
|
|
label = "Connected Chest fixer " .. name_left,
|
|
name = ":" .. name_left .. "_reconnect_lbm",
|
|
nodenames = {name_left},
|
|
run_at_every_load = true,
|
|
action = return_add_next(name_right),
|
|
}
|
|
end
|
|
|
|
|
|
local function get_chest_formspec(pos)
|
|
local spos = pos.x .. "," .. pos.y .. "," .. pos.z
|
|
local formspec =
|
|
"size[13,9]" ..
|
|
"list[nodemeta:" .. spos .. ";main;0,0;13,5;]" ..
|
|
"list[current_player;main;2.5,5.2;8,4;]" ..
|
|
"listring[nodemeta:" .. spos .. ";main]" ..
|
|
"listring[current_player;main]"
|
|
return formspec
|
|
end
|
|
|
|
local open_chests = {} -- counter for players viewing the chest
|
|
local accessed_chests = {} -- position of the chest a player views
|
|
|
|
-- a hacky way to close open connected default chests
|
|
-- vi: vector index of the position of the left chest
|
|
local function close_chest(vi)
|
|
local pos = minetest.get_position_from_hash(vi)
|
|
local node = minetest.get_node(pos)
|
|
local is_locked = node.name == "default:chest_locked_connected_left_open"
|
|
if node.name ~= "default:chest_connected_left_open"
|
|
and not is_locked then
|
|
return
|
|
end
|
|
if is_locked then
|
|
node.name = "default:chest_locked_connected_left"
|
|
else
|
|
node.name = "default:chest_connected_left"
|
|
end
|
|
minetest.swap_node(pos, node)
|
|
|
|
-- close the right chest
|
|
-- TODO: test for valid rotation
|
|
local x, z = unpack(param_tab2[node.param2])
|
|
pos.x = pos.x-x
|
|
pos.z = pos.z-z
|
|
node = minetest.get_node(pos)
|
|
if is_locked then
|
|
if node.name == "default:chest_locked_connected_right_open" then
|
|
node.name = "default:chest_locked_connected_right"
|
|
minetest.swap_node(pos, node)
|
|
end
|
|
else
|
|
if node.name == "default:chest_connected_right_open" then
|
|
node.name = "default:chest_connected_right"
|
|
minetest.swap_node(pos, node)
|
|
end
|
|
end
|
|
pos.x = pos.x + x * 0.5
|
|
pos.z = pos.z + z * 0.5
|
|
minetest.sound_play("default_chest_close",
|
|
{gain = 0.3, pos = pos, max_hear_distance = 10, pitch = 0.7}, true)
|
|
end
|
|
|
|
-- close all remaining open chest on shutdown
|
|
minetest.register_on_shutdown(function()
|
|
for vi in pairs(open_chests) do
|
|
close_chest(vi)
|
|
end
|
|
open_chests = nil
|
|
end)
|
|
|
|
-- close open chests when the last player exits formspec
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
if formname ~= "default:chest_connected"
|
|
and formname ~= "default:chest_locked_connected" then
|
|
return
|
|
end
|
|
if not player
|
|
or not fields.quit then
|
|
return
|
|
end
|
|
local pn = player:get_player_name()
|
|
local vi = accessed_chests[pn]
|
|
if not vi then
|
|
minetest.log("warning", pn .. " opened a chest without lid?")
|
|
return
|
|
end
|
|
accessed_chests[pn] = nil
|
|
|
|
local cnt = open_chests[vi]
|
|
if cnt == 1 then
|
|
close_chest(vi)
|
|
open_chests[vi] = nil
|
|
else
|
|
open_chests[vi] = cnt-1
|
|
end
|
|
|
|
return true
|
|
end)
|
|
|
|
local chest_lid_obstructed = default.chest
|
|
and default.chest.chest_lid_obstructed
|
|
connected_chests.register_chest("default:chest", {
|
|
description = S("Big Chest"),
|
|
add_open_chest = true,
|
|
on_rightclick = function(pos, _, player)
|
|
minetest.sound_play("default_chest_open",
|
|
{gain = 0.3, pos = pos, max_hear_distance = 10, pitch = 0.7}, true)
|
|
|
|
local vi = minetest.hash_node_position(pos)
|
|
if not open_chests[vi]
|
|
and not chest_lid_obstructed(pos) then
|
|
local left_param2 = minetest.get_node(pos).param2
|
|
|
|
-- TODO: test for invalid param2 values
|
|
local x, z = unpack(param_tab2[left_param2])
|
|
local pos_right = {x=pos.x-x, y=pos.y, z=pos.z-z}
|
|
local node = minetest.get_node(pos_right)
|
|
if node.name == "default:chest_connected_right"
|
|
and not chest_lid_obstructed(pos_right) then
|
|
minetest.swap_node(pos, {
|
|
name = "default:chest_connected_left_open",
|
|
param2 = left_param2})
|
|
minetest.swap_node(pos_right, {
|
|
name = "default:chest_connected_right_open",
|
|
param2 = node.param2})
|
|
end
|
|
end
|
|
|
|
local pname = player:get_player_name()
|
|
local spec = get_chest_formspec(pos)
|
|
|
|
minetest.after(0.2, minetest.show_formspec, pname,
|
|
"default:chest_connected", spec)
|
|
|
|
if not accessed_chests[pname] then
|
|
open_chests[vi] = open_chests[vi] or 0
|
|
open_chests[vi] = open_chests[vi]+1
|
|
|
|
accessed_chests[pname] = vi
|
|
end
|
|
end
|
|
})
|
|
|
|
connected_chests.register_chest("default:chest_locked", {
|
|
description = S("Big Locked Chest"),
|
|
lock = true,
|
|
add_open_chest = true,
|
|
on_rightclick = function(pos, _, player)
|
|
if not default.can_interact_with_node(player, pos) then
|
|
minetest.sound_play("default_chest_locked", {pos = pos}, true)
|
|
return
|
|
end
|
|
|
|
minetest.sound_play("default_chest_open",
|
|
{gain = 0.32, pos = pos, max_hear_distance = 10, pitch = 0.7}, true)
|
|
|
|
local vi = minetest.hash_node_position(pos)
|
|
-- TODO: somehow avoid using the chest node names here
|
|
if not open_chests[vi]
|
|
and not chest_lid_obstructed(pos) then
|
|
local left_param2 = minetest.get_node(pos).param2
|
|
|
|
-- TODO: test for invalid param2 values
|
|
local x, z = unpack(param_tab2[left_param2])
|
|
local pos_right = {x=pos.x-x, y=pos.y, z=pos.z-z}
|
|
local node = minetest.get_node(pos_right)
|
|
if node.name == "default:chest_locked_connected_right"
|
|
and not chest_lid_obstructed(pos_right) then
|
|
minetest.swap_node(pos_right, {
|
|
name = "default:chest_locked_connected_right_open",
|
|
param2 = node.param2})
|
|
minetest.swap_node(pos, {
|
|
name = "default:chest_locked_connected_left_open",
|
|
param2 = left_param2})
|
|
end
|
|
end
|
|
|
|
local pname = player:get_player_name()
|
|
local spec = get_chest_formspec(pos)
|
|
|
|
minetest.after(0.2, minetest.show_formspec, pname,
|
|
"default:chest_locked_connected", spec)
|
|
|
|
if not accessed_chests[pname] then
|
|
open_chests[vi] = open_chests[vi] or 0
|
|
open_chests[vi] = open_chests[vi]+1
|
|
|
|
accessed_chests[pname] = vi
|
|
end
|
|
end
|
|
})
|
|
|
|
|
|
|
|
-- legacy
|
|
|
|
-- the default chest lid obstruction function wasn't exposed in minetest 0.4.16
|
|
if not chest_lid_obstructed then
|
|
-- copied from default's nodes.lua
|
|
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 and
|
|
(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
|
|
end
|
|
|
|
-- once the connected_chests mod supported only default chests and used
|
|
-- different node names
|
|
minetest.register_alias("connected_chests:chest_left",
|
|
"default:chest_connected_left")
|
|
minetest.register_alias("connected_chests:chest_right",
|
|
"default:chest_connected_right")
|
|
minetest.register_alias("connected_chests:chest_left_locked",
|
|
"default:chest_locked_connected_left")
|
|
minetest.register_alias("connected_chests:chest_right_locked",
|
|
"default:chest_locked_connected_right")
|
|
minetest.register_alias("connected_chests:chest_locked_left",
|
|
"default:chest_locked_connected_left")
|
|
minetest.register_alias("connected_chests:chest_locked_right",
|
|
"default:chest_locked_connected_right")
|
|
|
|
if minetest.global_exists("hopper") and hopper.set_extra_container_info then
|
|
local function get_inventory(chest_right_pos)
|
|
local node_right = minetest.get_node(chest_right_pos)
|
|
if node_right.param2 > 3 then
|
|
-- The right connected chest node has an invalid param2 value
|
|
-- Cannot determine the inventory
|
|
return
|
|
end
|
|
local x, z = unpack(param_tab2[node_right.param2])
|
|
local chest_left_pos = {x=chest_right_pos.x+x, y=chest_right_pos.y,
|
|
z=chest_right_pos.z+z}
|
|
local node_left = minetest.get_node(chest_left_pos)
|
|
if node_left.name ~= "default:chest_connected_left"
|
|
and node_left.name ~= "default:chest_connected_left_open" then
|
|
minetest.log("error","The left chest is not a chest: " ..
|
|
node_left.name .. " at " .. vector.to_string(chest_left_pos))
|
|
return
|
|
end
|
|
if node_left.param2 ~= node_right.param2 then
|
|
minetest.log("error", "The chests are pointing in different " ..
|
|
"directions: node_left.param2:" .. node_left.param2 ..
|
|
", node_right.param2:" .. node_right.param2)
|
|
return
|
|
end
|
|
return minetest.get_meta(chest_left_pos):get_inventory()
|
|
end
|
|
hopper:add_container({
|
|
{"top", "default:chest_connected_left", "main"},
|
|
{"bottom", "default:chest_connected_left", "main"},
|
|
{"side", "default:chest_connected_left", "main"},
|
|
{"top", "default:chest_connected_right", "main",
|
|
get_inventory = get_inventory},
|
|
{"bottom", "default:chest_connected_right", "main",
|
|
get_inventory = get_inventory},
|
|
{"side", "default:chest_connected_right", "main",
|
|
get_inventory = get_inventory},
|
|
{"top", "default:chest_connected_left_open", "main"},
|
|
{"bottom", "default:chest_connected_left_open", "main"},
|
|
{"side", "default:chest_connected_left_open", "main"},
|
|
{"top", "default:chest_connected_right_open", "main",
|
|
get_inventory = get_inventory},
|
|
{"bottom", "default:chest_connected_right_open", "main",
|
|
get_inventory = get_inventory},
|
|
{"side", "default:chest_connected_right_open", "main",
|
|
get_inventory = get_inventory},
|
|
})
|
|
local function set_hopper_param2(hopper_pos, chest_left_pos)
|
|
local param2_by_offset = {
|
|
[vector.new(-1, 0, 0):to_string()] = 0,
|
|
[vector.new( 0, 0, 1):to_string()] = 1,
|
|
[vector.new( 1, 0, 0):to_string()] = 2,
|
|
[vector.new( 0, 0,-1):to_string()] = 3,
|
|
}
|
|
local hopper_param2 = param2_by_offset[
|
|
(chest_left_pos - hopper_pos):to_string()]
|
|
if hopper_param2 then
|
|
return hopper_param2
|
|
end
|
|
local x, z = unpack(
|
|
param_tab2[minetest.get_node(chest_left_pos).param2])
|
|
local chest_right_pos = {x=chest_left_pos.x-x, y=chest_left_pos.y,
|
|
z=chest_left_pos.z-z}
|
|
return param2_by_offset[(chest_right_pos - hopper_pos):to_string()]
|
|
end
|
|
hopper:set_extra_container_info({
|
|
{"default:chest_connected_left", set_hopper_param2 = set_hopper_param2},
|
|
})
|
|
end
|