284 lines
7.9 KiB
Lua
284 lines
7.9 KiB
Lua
|
|
--[[
|
|
|
|
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
|
|
|
|
"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,
|
|
})
|