--[[ Copyright (C) 2015 - Auke Kok "frame" is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the license, or (at your option) any later version. --]] local S = minetest.get_translator("frame") frame = {} -- handle node removal from frame local function frame_on_punch(pos, node, puncher, pointed_thing) local name = puncher:get_player_name() if puncher and not minetest.check_player_privs(puncher, "protection_bypass") then if minetest.is_protected(pos, name) then minetest.record_protection_violation(pos, name) return false end end local def = minetest.registered_nodes[node.name] -- lock/unlock local meta = minetest.get_meta(pos) if puncher:get_player_control().sneak and boxes.players_editing_boxes[name] then local idef = minetest.registered_nodes[def.frame_contents] if idef and not(idef.groups.hand or idef.groups.axe or idef.groups.shovel or idef.groups.pickaxe or idef.groups.torch) then meta:set_int("locked", 1) minetest.chat_send_player(name, S("The frame contains an item the player can not obtain, therefore remains locked.")) return false elseif meta:get_int("locked") == 1 then meta:set_int("locked", 0) minetest.chat_send_player(name, S("Frame is now unlocked.")) return false else meta:set_int("locked", 1) minetest.chat_send_player(name, S("Frame is now locked.")) return false end end if meta:get_int("locked") == 1 then if not boxes.players_editing_boxes[name] then return false end end -- preserve itemstack metadata and wear local wear = meta:get_int("wear") local item = ItemStack(def.frame_contents) if wear then item:set_wear(wear) end local metadata = meta:get_string("metadata") if metadata ~= "" then item:set_metadata(metadata) end --minetest.handle_node_drops(pos, {item}, puncher) local inv = puncher:get_inventory() if inv:room_for_item("main", item) then inv:add_item("main", item) --minetest.sound_play(def.sounds.dug, {pos = pos}) minetest.swap_node(pos, {name = "frame:empty", param2 = node.param2}) end end local frame_admin = { ["tools:player"] = true, ["tools:bulk"] = true, ["tools:grow"] = true, } -- handle node insertion into empty frame local function frame_on_rightclick(pos, node, clicker, itemstack, pointed_thing) if clicker and not minetest.check_player_privs(clicker, "protection_bypass") then local name = clicker:get_player_name() if minetest.is_protected(pos, name) then minetest.record_protection_violation(pos, name) return false end end local nodename = itemstack:get_name() if not nodename then return false end if frame_admin[nodename] and not minetest.check_player_privs(clicker, "server") then return false end local name = "frame:" .. nodename:gsub(":", "_") local def = minetest.registered_nodes[name] if not def then minetest.chat_send_player(clicker:get_player_name(), S("This item can not be inserted in a frame.")) return itemstack end local meta = minetest.get_meta(pos) local idef = minetest.registered_nodes[nodename] if idef and not(idef.groups.hand or idef.groups.axe or idef.groups.shovel or idef.groups.pickaxe or idef.groups.torch) then meta:set_int("locked", 1) minetest.chat_send_player(clicker:get_player_name(), S("Item inserted into frame is not obtainable, frame locked.")) end local wear = itemstack:get_wear() if wear then meta:set_int("wear", wear) end local metadata = itemstack:get_metadata() if metadata ~= "" then meta:set_string("metadata", metadata) end --minetest.sound_play(def.sounds.place, {pos = pos}) minetest.swap_node(pos, {name = name, param2 = node.param2}) if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end return itemstack end function frame.register(name) assert(name, "no content passed") local tiles local def = minetest.registered_nodes[name] if not def then -- item? def = minetest.registered_items[name] assert(def, "not a thing: ".. name) assert(def.inventory_image, "no inventory image for " .. name) tiles = { {name = "frame_frame.png"}, {name = def.inventory_image}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, } else -- node if def.inventory_image ~= "" then -- custom inventory override image first. tiles = { {name = "frame_frame.png"}, {name = def.inventory_image or "itb_blank.png"}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, } elseif def.drawtype ~= "normal" then -- use tiles[1] only, but on frame tiles = { {name = "frame_frame.png"}, {name = def.tiles[1] and def.tiles[1].name or def.tiles[1] or "itb_blank.png"}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, } else -- type(def.tiles[1]) == "table" then -- multiple tiles tiles = { {name = "frame_frame.png"}, {name = "itb_blank.png"}, {name = def.tiles[1] and def.tiles[1].name or def.tiles[1] or "itb_blank.png"}, {name = def.tiles[2] and def.tiles[2].name or def.tiles[1] or def.tiles[1] and def.tiles[1].name or def.tiles[1] or "itb_blank.png"}, {name = def.tiles[3] and def.tiles[3].name or def.tiles[3] or def.tiles[2] and def.tiles[2].name or def.tiles[2] or def.tiles[1] and def.tiles[1].name or def.tiles[1] or "itb_blank.png"}, } end end assert(def, name .. " is not a known node or item") local desc = def.description local nodename = def.name:gsub(":", "_") minetest.register_node(":frame:" .. nodename, { description = S("Frame with @1", desc), drawtype = "mesh", mesh = "frame.obj", tiles = tiles, paramtype = "light", paramtype2 = "facedir", sunlight_propagates = true, collision_box = { type = "fixed", fixed = {-1/2, -1/2, 3/8, 1/2, 1/2, 1/2}, }, selection_box = { type = "fixed", fixed = {-1/2, -1/2, 3/8, 1/2, 1/2, 1/2}, }, groups = {oddly_breakable_by_hand = 1, snappy = 3, not_in_creative_inventory = 1, frame_with_content = 1}, frame_contents = name, on_punch = frame_on_punch, on_reveal = function(n, pos) local meta = minetest.get_meta(pos) local locked = "no" if meta:get_int("locked") == 1 then locked = "yes" end minetest.chat_send_player(n, minetest.colorize( "#88ff44", "> locked = " .. locked )) end, sounds = sounds.wood, }) end -- empty frame minetest.register_node("frame:empty", { description = S("Frame"), drawtype = "mesh", mesh = "frame.obj", tiles = { {name = "frame_frame.png"}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, {name = "itb_blank.png"}, }, paramtype = "light", paramtype2 = "facedir", sunlight_propagates = true, collision_box = { type = "fixed", fixed = {-1/2, -1/2, 3/8, 1/2, 1/2, 1/2}, }, selection_box = { type = "fixed", fixed = {-1/2, -1/2, 3/8, 1/2, 1/2, 1/2}, }, groups = {oddly_breakable_by_hand = 3, cracky = 1}, on_rightclick = frame_on_rightclick, sounds = sounds.wood, }) -- inception! frame.register("frame:empty") minetest.register_abm({ label = "frame:content_obtainable", nodenames = {"group:frame_with_content"}, interval = 0.1, chance = 50, catch_up = false, action = function(pos, node) local meta = minetest.get_meta(pos) if meta:get_int("locked") == 1 then return end minetest.add_particle({ pos = vector.add(pos, math.random(50)/100 - 0.25), minpos = {x = math.floor(pos.x) - 0.4, y = math.floor(pos.y) - 0.4, z = math.floor(pos.z) - 0.4}, maxpos = {x = math.floor(pos.x) + 0.4, y = math.floor(pos.y) + 0.4, z = math.floor(pos.z) + 0.4}, velocity = {x = 0, y = 0, z = 0}, expirationtime = 0.78, size = math.random(10)/5 + 1, texture = "frame_effect_animated.png", glow = 13, animation = { type = "sheet_2d", frames_w = 8, frames_h = 1, frame_length = 0.1, }, }) end, })