greeknodes/doors.lua

330 lines
12 KiB
Lua
Raw Permalink Normal View History

2021-04-11 17:51:01 -07:00
-- Custom door implementation because I don't want to depend on other mods for content.
-- Registers only 2 nodes per door. Relies on front and back faces being identical. Locked doors implemented via param2.
local function can_interact(pos, player)
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
-- Not locked, is owner, or has valid key
return owner == "" or player:get_player_name() == owner or meta:get_string("secret") == player:get_wielded_item():get_meta():get_string("secret")
end
local function toggle_door(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local door, flip = node.name:match("^(.+_)(%w)$")
local yaw = minetest.dir_to_yaw(minetest.facedir_to_dir(node.param2))
local rot = minetest.dir_to_facedir(minetest.yaw_to_dir(yaw + math.rad(flip == "a" and -90 or 90)))
minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "greek:door_blank", param2 = rot})
minetest.swap_node(pos, {name = door .. (flip == "a" and "b" or "a"), param2 = rot + (meta:get_string("owner") ~= "" and 128 or 0)})
local state = (meta:get_int("state") + 1) % 2
meta:set_int("state", state)
2022-03-25 20:39:00 -07:00
if minetest.get_modpath("doors") then minetest.sound_play("doors_door_" .. ({"close", "open"})[state + 1], {pos = pos}, true) end
2021-04-11 17:51:01 -07:00
end
minetest.register_node("greek:door_blank", {
drawtype = "airlike",
2021-08-27 13:51:44 -07:00
paramtype = "light",
sunlight_propagates = true,
2021-04-11 17:51:01 -07:00
paramtype2 = "facedir",
2021-08-27 13:51:44 -07:00
walkable = true,
pointable = false,
diggable = false,
buildable_to = false,
floodable = false,
drop = "",
groups = {not_in_creative_inventory = 1},
2021-04-11 17:51:01 -07:00
collision_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, -6 / 16},
},
})
local door_count = 4
for i = 1, door_count do
local def = {
description = "Blue Door " .. i,
drawtype = "mesh",
mesh = "greek_door.obj",
tiles = {{name = "greek_door_" .. i .. ".png", backface_culling = true, color = "white"}},
overlay_tiles = {"greek_door_handle.png"},
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "colorfacedir",
palette = "greek_door_palette.png",
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, -6 / 16},
},
collision_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, -6 / 16},
},
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, door = 1},
on_rightclick = function(pos, _, clicker) if can_interact(pos, clicker) then toggle_door(pos) end end,
on_key_use = function(pos, player) if can_interact(pos, player) then toggle_door(pos) end end,
on_skeleton_key_use = function(pos, player, newsecret)
local meta = minetest.get_meta(pos)
local name = player:get_player_name()
local owner = meta:get_string("owner")
if owner ~= name then
if owner ~= "" then minetest.chat_send_player(name, "You do not own this door.") end
return
end
local secret = meta:get_string("secret")
secret = secret ~= "" and secret or newsecret
meta:set_string("secret", secret)
return secret
end,
on_punch = function(pos, node, puncher, pointed)
-- Allow binding a key to multiple doors
local stack = puncher:get_wielded_item()
print(stack:get_name())
if minetest.get_item_group(stack:get_name(), "key") == 1 then
local meta = minetest.get_meta(pos)
local name = puncher:get_player_name()
if meta:get_string("owner") == name then
local current = meta:get_string("secret")
local new = stack:get_meta():get_string("secret")
if current == "" then
meta:set_string("secret", new)
elseif current ~= new then
minetest.chat_send_player(name, "This door has already been bound to a key.")
end
end
end
minetest.node_punch(pos, node, puncher, pointed)
end,
on_rotate = function() return false end,
on_dig = function(pos, node, digger)
minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z})
minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "air"})
return minetest.node_dig(pos, node, digger)
end,
on_blast = function(pos)
if minetest.get_meta(pos):get_string("owner") ~= "" then return end
local name = minetest.get_node(pos).name
2021-08-27 13:51:44 -07:00
minetest.remove_node(pos)
minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z})
return {name}
end,
2021-04-11 17:51:01 -07:00
}
do -- Register normal version
local defcopy = table.copy(def)
-- Check for obstructions and place invisible node
defcopy.on_place = function(itemstack, placer, pointed)
2021-08-27 13:51:44 -07:00
local pos
2021-04-11 17:51:01 -07:00
2021-08-27 13:51:44 -07:00
if pointed.type ~= "node" then return itemstack end
2021-04-11 17:51:01 -07:00
2021-08-27 13:51:44 -07:00
local node = minetest.get_node(pointed.under)
local pdef = minetest.registered_nodes[node.name]
2021-04-11 17:51:01 -07:00
if pdef and pdef.on_rightclick and not placer:get_player_control().sneak then
return pdef.on_rightclick(pointed.under, node, placer, itemstack, pointed)
end
2021-08-27 13:51:44 -07:00
if pdef and pdef.buildable_to then
pos = pointed.under
else
pos = pointed.above
node = minetest.get_node(pos)
pdef = minetest.registered_nodes[node.name]
if not pdef or not pdef.buildable_to then return itemstack end
end
2021-04-11 17:51:01 -07:00
2021-08-27 13:51:44 -07:00
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local top_node = minetest.get_node_or_nil(above)
local topdef = top_node and minetest.registered_nodes[top_node.name]
2021-04-11 17:51:01 -07:00
2021-08-27 13:51:44 -07:00
if not topdef or not topdef.buildable_to then return itemstack end
2021-04-11 17:51:01 -07:00
2021-08-27 13:51:44 -07:00
local pn = placer and placer:get_player_name() or ""
if minetest.is_protected(pos, pn) or minetest.is_protected(above, pn) then return itemstack end
2021-04-11 17:51:01 -07:00
2021-08-27 13:51:44 -07:00
return minetest.item_place_node(itemstack, placer, pointed)
end
2021-04-11 17:51:01 -07:00
-- Set metadata and rotate door
defcopy.after_place_node = function(pos, placer)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
-- Check if door is locked
if math.floor(node.param2 / 32) >= 4 then
local name = placer:get_player_name()
meta:set_string("owner", name)
meta:set_string("infotext", "Blue Door\nOwned by " .. name)
end
meta:set_int("state", 0)
local dir = node.param2 % 32
local ref = {
{x = -1, y = 0, z = 0},
{x = 0, y = 0, z = 1},
{x = 1, y = 0, z = 0},
{x = 0, y = 0, z = -1},
}
local aside = {
x = pos.x + ref[dir + 1].x,
y = pos.y + ref[dir + 1].y,
z = pos.z + ref[dir + 1].z,
}
if minetest.get_item_group(minetest.get_node(aside).name, "door") == 1 then
minetest.swap_node(pos, {name = node.name:match("^(.+_)%w$") .. "b", param2 = node.param2})
end
minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "greek:door_blank", param2 = node.param2})
end
defcopy.color = "#242424"
-- Use overlay for door because it wont be colored
defcopy.inventory_overlay = "greek_door_" .. i .. "_inv.png"
defcopy.inventory_image = "greek_door_inv_handle.png"
defcopy.wield_overlay = "greek_door_" .. i .. "_inv.png"
defcopy.wield_image = "greek_door_inv_handle.png"
minetest.register_node("greek:door_" .. i .. "_a", defcopy)
end
do -- Register mirrored version (should not be obtainable normally)
local defcopy = table.copy(def)
-- Fancy flipping
local front = "([combine\\:16x32\\:0,0=%s\\^[transformFX)"
local back = "([combine\\:16x32\\:-16,0=%s\\^[transformFX)"
local sides = "([combine\\:4x32\\:-32,0=%s\\^[transformFX)"
local tops = "([combine\\:2x32\\:-36,0=%s\\^[transformFX)"
defcopy.tiles[1].name = (("[combine:38x32:0,0=%s:16,0=%s:32,0=%s:36,0=%s"):format(front, back, sides, tops):gsub("%%s", def.tiles[1].name))
defcopy.overlay_tiles = {(("[combine:38x32:0,0=([combine\\:16x32\\:0,0=%s\\^[transformFX):16,0=([combine\\:16x32\\:-16,0=%s\\^[transformFX)"):gsub("%%s", def.overlay_tiles[1]))}
defcopy.groups.not_in_creative_inventory = 1
defcopy.drop = "greek:door_" .. i .. "_a"
defcopy.preserve_metadata = function(_, node, oldmeta, drops)
-- Preserve locked state
if oldmeta.owner then
local meta = drops[1]:get_meta()
meta:set_int("palette_index", 128)
meta:set_string("description", "Locked " .. minetest.registered_items[node.name].description)
meta:set_string("color", "#dcdcdc")
end
end
minetest.register_node("greek:door_" .. i .. "_b", defcopy)
end
end
greek.register_craftring("greek:door_%s_a", door_count)
for _, item in pairs(greek.settings_list("blue_wood")) do
-- Only bother registering our own if it is used
if item == "greek:blue_wood" then
greek.register_node_and_stairs("greek:blue_wood", {
description = "Blue Wood",
tiles = {"greek_blue_wood.png"},
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 2},
sounds = greek.default_sounds("node_sound_wood_defaults"),
})
minetest.register_craft({
output = "greek:blue_wood",
recipe = {"group:wood", "dye:blue"},
type = "shapeless",
})
end
greek.add_group(item, "blue_wood")
end
minetest.register_craft({
output = "greek:door_1_a 2",
recipe = {
{"group:greek:blue_wood", "group:greek:blue_wood"},
{"group:greek:blue_wood", "group:greek:blue_wood"},
{"group:greek:blue_wood", "group:greek:blue_wood"},
},
})
for _, item in pairs(greek.settings_list("door_lock")) do
greek.add_group(item, "door_lock")
end
minetest.register_craft({
output = ItemStack({
name = "greek:door_1_a",
meta = {
description = "Locked " .. minetest.registered_items["greek:door_1_a"].description,
color = "#dcdcdc",
palette_index = 128,
},
}):to_string(),
recipe = {"greek:door_1_a", "group:greek:door_lock"},
type = "shapeless",
})
local shutter_count = 3
for i = 1, shutter_count do
local def = {
description = "Blue Shutters " .. i,
drawtype = "mesh",
mesh = "greek_shutters.obj",
tiles = {{name = "greek_shutters_" .. i .. ".png", backface_culling = true}, "blank.png"},
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, 6 / 16, 0.5, 0.5, 0.5},
},
collision_box = {
type = "fixed",
fixed = {-0.5, -0.5, 6 / 16, 0.5, 0.5, 0.5},
},
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
on_rightclick = function(pos, node)
minetest.swap_node(pos, {name = "greek:shutters_" .. i .. "_open", param2 = node.param2})
2022-03-25 20:39:00 -07:00
if minetest.get_modpath("doors") then minetest.sound_play("doors_door_open", {pos = pos}, true) end
2021-04-11 17:51:01 -07:00
end,
}
minetest.register_node("greek:shutters_" .. i, def)
def = table.copy(def)
def.tiles = {"blank.png", def.tiles[1]}
def.groups.not_in_creative_inventory = 1
def.drop = "greek:shutters_" .. i
def.on_rightclick = function(pos, node)
minetest.swap_node(pos, {name = "greek:shutters_" .. i, param2 = node.param2})
2022-03-25 20:39:00 -07:00
if minetest.get_modpath("doors") then minetest.sound_play("doors_door_close", {pos = pos}, true) end
2021-04-11 17:51:01 -07:00
end
minetest.register_node("greek:shutters_" .. i .. "_open", def)
end
greek.register_craftring("greek:shutters_%s", shutter_count)
minetest.register_craft({
output = "greek:shutters_1 2",
recipe = {
{"group:greek:blue_wood", "", "group:greek:blue_wood"},
{"group:greek:blue_wood", "", "group:greek:blue_wood"},
},
})