1
0
mirror of https://github.com/D00Med/scifi_nodes.git synced 2025-02-08 22:00:20 +01:00
scifi_nodes/access_card.lua
Buckaroo Banzai 6fb3ded8ad
Add access cards (#88)
* add access cards

* colored cards

* rename / recipes

* impl

* crafting fix

* indent fixes

* door groups fix (should not be diggable by hand)

---------

Co-authored-by: BuckarooBanzay <BuckarooBanzay@users.noreply.github.com>
2025-02-07 15:47:20 +01:00

254 lines
7.5 KiB
Lua

local FORMSPEC_NAME = "scifi_nodes:access_card_configure"
local function create_id()
local template = "xxxxxx"
return string.gsub(template, '[x]', function ()
return string.format('%x', math.random(0, 0xf))
end)
end
local function get_door_access_table(meta)
local str = meta:get_string("access")
if str == "" then
-- no config
return {}
else
return minetest.deserialize(str) or {}
end
end
local function set_door_access_table(meta, at)
if next(at) then
meta:set_string("access", minetest.serialize(at))
else
meta:set_string("access", "")
end
end
function scifi_nodes.door_check_access_card(node_pos, itemstack, player)
local node_meta = minetest.get_meta(node_pos)
local access_table = get_door_access_table(node_meta)
if not next(access_table) then
-- access not restricted
return true
end
local playername = player:get_player_name()
if itemstack:get_name() ~= "scifi_nodes:access_card" then
minetest.chat_send_player(playername, minetest.colorize("#ff0000", "Access denied: no access card detected!"))
minetest.sound_play("scifi_nodes_scanner_refused", { pos = node_pos, max_hear_distance = 10 })
return false
end
local item_meta = itemstack:get_meta()
local id = item_meta:get_string("id")
if id == "" then
minetest.chat_send_player(playername, minetest.colorize("#ff0000", "Access denied: unconfigured access card"))
minetest.sound_play("scifi_nodes_scanner_refused", { pos = node_pos, max_hear_distance = 10 })
return false
end
if not access_table[id] then
minetest.chat_send_player(playername, minetest.colorize("#ff0000", "Access denied: invalid access card"))
minetest.sound_play("scifi_nodes_scanner_refused", { pos = node_pos, max_hear_distance = 10 })
return false
end
minetest.sound_play("scifi_nodes_scanner_granted", { pos = node_pos, max_hear_distance = 10 })
return true
end
-- using a card against a door toggles the access to it
local function on_use(itemstack, player, pointed_thing)
local playername = player:get_player_name()
local pos = pointed_thing.under
if not pos then
-- nothing selected
return
end
if minetest.is_protected(pos, playername) then
-- protected
return
end
local node = minetest.get_node(pos)
local node_def = minetest.registered_nodes[node.name]
if not node_def.groups or not node_def.groups.scifi_nodes_door then
-- incompatible node
return
end
local item_meta = itemstack:get_meta()
local card_id = item_meta:get_string("id")
if card_id == "" then
minetest.chat_send_player(playername, "Access card is unconfigured")
return
end
local card_name = item_meta:get_string("name")
local node_meta = minetest.get_meta(pos)
local access_table = get_door_access_table(node_meta)
if access_table[card_id] then
-- remove access
access_table[card_id] = nil
minetest.chat_send_player(playername, "Revoked access to card-id '" .. card_id .. "'")
minetest.sound_play("scifi_nodes_scanner_refused", { pos = pos, max_hear_distance = 10 })
else
-- grant access
access_table[card_id] = card_name
minetest.chat_send_player(playername, "Granted access to card-id '" .. card_id .. "'")
minetest.sound_play("scifi_nodes_scanner_granted", { pos = pos, max_hear_distance = 10 })
end
local msg = ""
if next(access_table) then
msg = msg .. "Current registered cards: "
for id, name in pairs(access_table) do
msg = msg .. "Name: '" .. name .. "' ID: '" .. id .. "' / "
end
else
-- access table is empty
msg = "No access-card left in access-table, door is free to use"
end
minetest.chat_send_player(playername, msg)
-- set new access table
set_door_access_table(node_meta, access_table)
end
local function configure_access_card(meta, name)
local id = meta:get_string("id")
if id == "" then
-- set new id
id = create_id()
meta:set_string("id", id)
end
meta:set_string("name", name)
meta:set_string("description", "Access card '" .. name .. "' (id: '" .. id .. "')")
end
-- right-click with a card for rename/configuration
local function on_secondary_use(itemstack, player, pointed_thing)
local meta = itemstack:get_meta()
if meta:get_string("id") == "" then
-- initial configuration
configure_access_card(meta, "")
end
local name = meta:get_string("name")
minetest.show_formspec(player:get_player_name(), FORMSPEC_NAME, [[
size[10,1.4]
real_coordinates[true]
field[0.1,0.4;7,0.8;name;Name;]] .. minetest.formspec_escape(name) .. [[]
button_exit[7.3,0.4;2.5,0.8;save;Save]
]])
return itemstack
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= FORMSPEC_NAME then
-- wrong formspec
return false
end
if not fields.save and not fields.key_enter_field then
-- quit
return true
end
local itemstack = player:get_wielded_item()
if itemstack:get_name() ~= "scifi_nodes:access_card" then
-- invalid item
return true
end
local meta = itemstack:get_meta()
configure_access_card(meta, fields.name or "")
player:set_wielded_item(itemstack)
end)
minetest.register_craftitem("scifi_nodes:access_card", {
description = "Access card (unconfigured)",
inventory_image = "scifi_nodes_access_card.png",
palette = "unifieddyes_palette_extended.png",
stack_max = 1,
paramtype2 = "color",
on_use = on_use,
on_secondary_use = on_secondary_use,
groups = {
ud_param2_colorable = 1
}
})
-- initial recipe
minetest.register_craft({
output = "scifi_nodes:access_card",
recipe = {
{"scifi_nodes:white2", "", ""},
{"scifi_nodes:white_pad", "", ""},
{"scifi_nodes:white2", "", ""}
}
})
-- copy recipe
minetest.register_craft({
output = "scifi_nodes:access_card",
recipe = {
{"scifi_nodes:access_card", "scifi_nodes:white_pad", ""},
{"", "", ""},
{"", "", ""}
}
})
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
if itemstack:get_name() ~= "scifi_nodes:access_card" then
return
end
local original
local index
for i = 1, #old_craft_grid do
if old_craft_grid[i]:get_name() == "scifi_nodes:access_card" then
original = old_craft_grid[i]
index = i
break
end
end
if not original then
return
end
-- copy metadata
local src_meta = original:get_meta()
local dst_meta = itemstack:get_meta()
local copy_fields = {"id", "name", "description"}
for _, fieldname in ipairs(copy_fields) do
dst_meta:set_string(fieldname, src_meta:get_string(fieldname))
end
if old_craft_grid[2]:get_name() == "scifi_nodes:white_pad" then
-- keep original item if the copy-recipe is used
craft_inv:set_stack("craft", index, original)
end
end)
if minetest.get_modpath("unifieddyes") then
-- add colored crafts
unifieddyes.register_color_craft({
output = "scifi_nodes:access_card",
palette = "extended",
neutral_node = "scifi_nodes:access_card",
recipe = {
"NEUTRAL_NODE",
"MAIN_DYE"
},
type = "shapeless"
})
end