local S = minetest.get_translator(minetest.get_current_modname()) local F = minetest.formspec_escape local C = minetest.colorize -- Shulker boxes local boxtypes = { 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"), } 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", } local canonical_shulker_color = "violet" local normal_canonical_name = "mcl_chests:" .. canonical_shulker_color .. "_shulker_box" local small_canonical_name = normal_canonical_name .. "_small" --WARNING: after formspec v4 update, old shulker boxes will need to be placed again to get the new formspec local function formspec_shulker_box(name) if not name or name == "" then name = S("Shulker Box") end return table.concat({ "formspec_version[4]", "size[11.75,10.425]", "label[0.375,0.375;" .. F(C(mcl_formspec.label_color, name)) .. "]", mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3), "list[context;main;0.375,0.75;9,3;]", "label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]", mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3), "list[current_player;main;0.375,5.1;9,3;9]", mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1), "list[current_player;main;0.375,9.05;9,1;]", "listring[context;main]", "listring[current_player;main]", }) 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 for color, desc in pairs(boxtypes) do local mob_texture = shulker_mob_textures[color] local is_canonical = color == canonical_shulker_color local longdesc, usagehelp, create_entry, entry_name if doc then if is_canonical then longdesc = S([[ 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. ]]) usagehelp = S([[ 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. ]]) entry_name = S("Shulker Box") else create_entry = false end end local normal_name = "mcl_chests:" .. color .. "_shulker_box" local small_name = normal_name .. "_small" minetest.register_node(normal_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, tiles = { mob_texture }, use_texture_alpha = "opaque", drawtype = "mesh", mesh = "mcl_chests_shulker.b3d", groups = { handy = 1, pickaxey = 1, container = 2, deco_block = 1, dig_by_piston = 1, shulker_box = 1, old_shulker_box_node = 1 }, is_ground_content = false, sounds = mcl_sounds.node_sound_stone_defaults(), stack_max = 1, drop = "", paramtype = "light", paramtype2 = "facedir", on_construct = function(pos) 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) ninv:set_size("main", 9 * 3) 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 end, _on_dispense = function(stack, pos, droppos, dropnode, dropdir) -- Place shulker box as node if minetest.registered_nodes[dropnode.name].buildable_to then minetest.set_node(droppos, { name = small_name, param2 = minetest.dir_to_facedir(dropdir) }) local ninv = minetest.get_inventory({ type = "node", pos = droppos }) local imetadata = stack:get_metadata() local iinv_main = minetest.deserialize(imetadata) ninv:set_list("main", iinv_main) ninv:set_size("main", 9 * 3) set_shulkerbox_meta(minetest.get_meta(droppos), stack:get_meta()) stack:take_item() end return stack end, }) 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", node_box = { type = "fixed", fixed = { -0.48, -0.5, -0.48, 0.48, 0.489, 0.48 }, }, tiles = { "blank.png^[resize:16x16" }, use_texture_alpha = "clip", _chest_entity_textures = { mob_texture }, _chest_entity_sound = "mcl_chests_shulker", _chest_entity_mesh = "mcl_chests_shulker", _chest_entity_animation_type = "shulker", groups = { handy = 1, pickaxey = 1, container = 2, deco_block = 1, dig_by_piston = 1, shulker_box = 1, chest_entity = 1, not_in_creative_inventory = 1 }, is_ground_content = false, sounds = mcl_sounds.node_sound_stone_defaults(), stack_max = 1, drop = "", paramtype = "light", paramtype2 = "facedir", on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", formspec_shulker_box(nil)) local inv = meta:get_inventory() inv:set_size("main", 9 * 3) mcl_chests.create_entity(pos, small_name, { mob_texture }, minetest.get_node(pos).param2, false, "mcl_chests_shulker", "mcl_chests_shulker", "shulker") 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) ninv:set_size("main", 9 * 3) 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 end, on_rightclick = function(pos, node, clicker) mcl_chests.player_chest_open(clicker, pos, small_name, { mob_texture }, node.param2, false, "mcl_chests_shulker", "mcl_chests_shulker", true) end, on_receive_fields = function(pos, formname, fields, sender) if fields.quit then mcl_chests.player_chest_close(sender) end end, on_destruct = function(pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local items = {} for i = 1, inv:get_size("main") do local stack = inv:get_stack("main", i) items[i] = stack:to_string() end local data = minetest.serialize(items) local boxitem = ItemStack("mcl_chests:" .. color .. "_shulker_box") local boxitem_meta = boxitem:get_meta() boxitem_meta:set_string("description", meta:get_string("description")) boxitem_meta:set_string("name", meta:get_string("name")) boxitem:set_metadata(data) if minetest.is_creative_enabled("") then if not inv:is_empty("main") then minetest.add_item(pos, boxitem) end else minetest.add_item(pos, boxitem) end end, allow_metadata_inventory_move = mcl_chests.protection_check_move, allow_metadata_inventory_take = mcl_chests.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 end -- 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, on_rotate = mcl_chests.simple_rotate, _mcl_blast_resistance = 6, _mcl_hardness = 2, _mcl_hoppers_on_try_push = function(pos, hop_pos, hop_inv, hop_list) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() return inv, "main", mcl_util.select_stack(hop_inv, hop_list, inv, "main", mcl_chests.is_not_shulker_box, 1) end, }) if doc and not is_canonical then doc.add_entry_alias("nodes", normal_canonical_name, "nodes", normal_name) doc.add_entry_alias("nodes", small_canonical_name, "nodes", small_name) end minetest.register_craft({ type = "shapeless", output = normal_name, recipe = { "group:shulker_box", "mcl_dye:" .. color }, }) end minetest.register_craft({ output = "mcl_chests:violet_shulker_box", recipe = { { "mcl_mobitems:shulker_shell" }, { "mcl_chests:chest" }, { "mcl_mobitems:shulker_shell" }, }, }) -- 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) minetest.register_lbm({ label = "Update shulker box formspecs (0.72.0)", name = "mcl_chests:update_shulker_box_formspecs_0_72_0", nodenames = { "group:shulker_box" }, run_at_every_load = false, action = function(pos, node) local meta = minetest.get_meta(pos) meta:set_string("formspec", formspec_shulker_box(meta:get_string("name"))) end, })