From e6bf1c4d339b53536cf90de576d2f4ce6105006f Mon Sep 17 00:00:00 2001 From: alek13 Date: Sat, 30 Dec 2023 22:57:21 +0300 Subject: [PATCH] Add clan chest --- mods/lord/Blocks/clan_node/init.lua | 9 ++ .../Blocks/clan_node/locale/clan_node.ru.tr | 2 + .../lord/Blocks/clan_node/locale/template.txt | 2 + mods/lord/Blocks/clan_node/mod.conf | 3 + mods/lord/Blocks/clan_node/src/chest.lua | 20 ++++ mods/lord/Blocks/clan_node/src/chest/node.lua | 91 +++++++++++++++ .../Blocks/clan_node/src/chest/node/Form.lua | 106 ++++++++++++++++++ mods/lord/Player/clans/init.lua | 85 +++++++++++--- 8 files changed, 304 insertions(+), 14 deletions(-) create mode 100644 mods/lord/Blocks/clan_node/init.lua create mode 100644 mods/lord/Blocks/clan_node/locale/clan_node.ru.tr create mode 100644 mods/lord/Blocks/clan_node/locale/template.txt create mode 100644 mods/lord/Blocks/clan_node/mod.conf create mode 100644 mods/lord/Blocks/clan_node/src/chest.lua create mode 100644 mods/lord/Blocks/clan_node/src/chest/node.lua create mode 100644 mods/lord/Blocks/clan_node/src/chest/node/Form.lua diff --git a/mods/lord/Blocks/clan_node/init.lua b/mods/lord/Blocks/clan_node/init.lua new file mode 100644 index 000000000..d80ed17d7 --- /dev/null +++ b/mods/lord/Blocks/clan_node/init.lua @@ -0,0 +1,9 @@ +local mod_path = minetest.get_modpath(minetest.get_current_modname()) +local old_require = require +require = function(name) return dofile(mod_path .. "/src/" .. name:gsub("%.", "/") .. ".lua") end + + +require("chest").init() + + +require = old_require diff --git a/mods/lord/Blocks/clan_node/locale/clan_node.ru.tr b/mods/lord/Blocks/clan_node/locale/clan_node.ru.tr new file mode 100644 index 000000000..c15261e50 --- /dev/null +++ b/mods/lord/Blocks/clan_node/locale/clan_node.ru.tr @@ -0,0 +1,2 @@ +# textdomain: clan_node + diff --git a/mods/lord/Blocks/clan_node/locale/template.txt b/mods/lord/Blocks/clan_node/locale/template.txt new file mode 100644 index 000000000..e04953143 --- /dev/null +++ b/mods/lord/Blocks/clan_node/locale/template.txt @@ -0,0 +1,2 @@ +# textdomain: quest_node + diff --git a/mods/lord/Blocks/clan_node/mod.conf b/mods/lord/Blocks/clan_node/mod.conf new file mode 100644 index 000000000..192656470 --- /dev/null +++ b/mods/lord/Blocks/clan_node/mod.conf @@ -0,0 +1,3 @@ +name = clan_node +description = Clans specific nodes (chests, ... etc) +depends = default, clans diff --git a/mods/lord/Blocks/clan_node/src/chest.lua b/mods/lord/Blocks/clan_node/src/chest.lua new file mode 100644 index 000000000..534bcf071 --- /dev/null +++ b/mods/lord/Blocks/clan_node/src/chest.lua @@ -0,0 +1,20 @@ +local node = require("chest.node") + + +local function register() + minetest.register_node("clan_node:chest", node.definition) + minetest.register_on_player_receive_fields(node.form_handler) + minetest.register_craft({ + output = "clan_node:chest", + recipe = { + {"farming:string", "default:chest", "farming:string"} + }, + }) +end + + +return { + init = function() + register() + end +} diff --git a/mods/lord/Blocks/clan_node/src/chest/node.lua b/mods/lord/Blocks/clan_node/src/chest/node.lua new file mode 100644 index 000000000..1c5f24251 --- /dev/null +++ b/mods/lord/Blocks/clan_node/src/chest/node.lua @@ -0,0 +1,91 @@ +--- @type clan_node.chest.node.Form +local Form = require("chest.node.Form") + + +local S = minetest.get_translator('clan_node') + +local definition = { + description = S("Clan Chest"), + tiles = { + "default_chest_top.png", + "default_chest_top.png", + "default_chest_side.png", + "default_chest_side.png", + "default_chest_side.png", + "default_chest_front.png" + }, + sounds = default.node_sound_wood_defaults(), + sound_open = "default_chest_open", + sound_close = "default_chest_close", + groups = { + choppy = 2, + oddly_breakable_by_hand = 2, + not_in_creative_inventory = 1, + }, + is_ground_content = false, + paramtype = "light", + paramtype2 = "facedir", + + --- @param itemstack ItemStack + --- @param placer Player + --- @param pointed_thing pointed_thing + on_place = function(itemstack, placer, pointed_thing) + if not clans.get_by_player(placer) then + minetest.chat_send_player( + placer:get_player_name(), S("You can't place this item. This chest is only for clan players.") + ) + return itemstack, nil + end + return minetest.item_place(itemstack, placer, pointed_thing) + end, + --- @param pos Position + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", S("Clan Chest")) + meta:set_string("owned_clan", "") + local inventory = meta:get_inventory() + inventory:set_size("main", 8 * 4) + end, + --- @param pos Position + --- @param placer Player + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + local clan = clans.get_by_player(placer) + if not clan then + local node_name = minetest.get_node(pos).name + minetest.remove_node(pos) + minetest.add_item(pos, node_name) + end + meta:set_string("owned_clan", clan.name) + meta:set_string("infotext", S("@1 Clan Chest", clan.title)) + end, + --- @param pos Position + --- @param player Player + can_dig = function(pos, player) + return + clans.get_by_player(player) and + minetest.get_meta(pos):get_inventory():is_empty("main") + end, + on_blast = function() end, + --- @param pos Position + --- @param clicker Player + on_rightclick = function(pos, node, clicker) + local chest_clan_name = minetest.get_meta(pos):get_string("owned_clan") + if not chest_clan_name or not clans.clan_is_online(chest_clan_name) then + return + end + local player_clan = clans.get_by_player(clicker) + local player_clan_name = player_clan and player_clan.name or nil + if player_clan_name ~= chest_clan_name then + local chest_clan = clans.get_by_name(chest_clan_name) + minetest.chat_send_all(minetest.colorize("red", S("Clan @1 is under the raid", chest_clan.title))) + end + Form:new(pos, clicker):open() + end, +} + + +return { + definition = definition, + form_handler = Form.handler +} diff --git a/mods/lord/Blocks/clan_node/src/chest/node/Form.lua b/mods/lord/Blocks/clan_node/src/chest/node/Form.lua new file mode 100644 index 000000000..9433ad85e --- /dev/null +++ b/mods/lord/Blocks/clan_node/src/chest/node/Form.lua @@ -0,0 +1,106 @@ + +--- +--- @class clan_node.chest.node.Form +--- +local Form = { + --- @const + --- @type string + NAME = "clan_node:chest", + --- @static + --- @type table + opened_for = {}, + + --- @private + --- @type Position + node_position = nil, + --- @type string + player_name = nil, +} + +--- Constructor +--- @public +--- @param pos Position +--- @param player Player +--- @return clan_node.chest.node.Form +function Form:new(pos, player) + local class = self + self = {} + + self.node_position = pos + self.player_name = player:get_player_name() + + return setmetatable(self, {__index = class}) +end + +--- @public +--- @static +--- @param player Player +--- @return clan_node.chest.node.Form +function Form.get_opened_for(player) + return Form.opened_for[player:get_player_name()] +end + +--- @public +function Form:open() + local player_name = self.player_name + self.opened_for[player_name] = self; + + local node_pos = self.node_position + local sound = minetest.registered_nodes[minetest.get_node(node_pos).name].sound_open + if not sound then return end + minetest.sound_play(sound, { gain = 0.3, pos = node_pos, max_hear_distance = 10}, true) + minetest.show_formspec(player_name, self.NAME, self:get_spec()) +end + +--- @public +function Form:close() + self.opened_for[self.player_name] = nil + + local node_pos = self.node_position + local sound = minetest.registered_nodes[minetest.get_node(node_pos).name].sound_close + if not sound then return end + minetest.sound_play(sound, { gain = 0.3, pos = node_pos, max_hear_distance = 10}, true) +end + +--- @private +function Form:get_spec() + local pos = self.node_position + + local str_pos = pos.x .. "," .. pos.y .. "," .. pos.z + local formspec = "size[8,9]" .. + "list[nodemeta:" .. str_pos .. ";main;0,0.3;8,4;]" .. + "list[current_player;main;0,4.85;8,1;]" .. + "list[current_player;main;0,6.08;8,3;8]" .. + "listring[nodemeta:" .. str_pos .. ";main]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0,4.85) + + return formspec +end + +--- @static +--- @param player Player +--- @param form_name string +--- @param fields table +function Form.handler(player, form_name, fields) + if form_name ~= Form.NAME then + return + end + + local form = Form.get_opened_for(player) + if not form then return end + + if fields.quit then + form:close() + end +end + +minetest.register_on_leaveplayer(function(player, timed_out) + local form = Form.get_opened_for(player); + if form then + form:close() + end +end) + + +return Form diff --git a/mods/lord/Player/clans/init.lua b/mods/lord/Player/clans/init.lua index d772d7361..590b21c3f 100644 --- a/mods/lord/Player/clans/init.lua +++ b/mods/lord/Player/clans/init.lua @@ -1,4 +1,5 @@ ---- @class Clan +--- @class clans.Clan +--- @field public name string --- @field public title string --- @field public players table @@ -6,28 +7,33 @@ -- HACK: this is a quick hardcoded local storage for clans data -- TODO: save this data somewhere else (mod-storage?) -- TODO: commands for manage ---- @type table -local clans = { +--- @type table +local clans_storage = { masons = { - title = "Masons", + name = "masons", + title = "Masons", players = { "Petus_mason", "Swed_mason", "Dormi_mason", "JikiSo_mason", "Alek_mason", "Zhekil_mason" }, }, - havit = { - title = "Havit-Nakyar", - players = { "Doloment", "Sdoh", "Aiex" } - }, + --havit = { + -- name = "havit", + -- title = "Havit-Nakyar", + -- players = { "Doloment", "Sdoh", "Aiex" } + --}, vassals = { - title = "Vassals", - players = { "Pilsner_vassal", "PePe_vassal", "JakeVovaDimas", "Semi_vassal" }, + name = "vassals", + title = "Vassals", + players = { "Pilsner_vassal", "PePe_vassal", "JVD_vassal", "Semi_vassal" }, }, } +--- @type table local cache for clan is online +local clan_is_online_cache = {} --- @param player Player ---- @return Clan|table|nil returns clan data ( `{ title = "...", players {...}, ... }` ) -local function get_clan(player) +--- @return clans.Clan|nil returns clan data ( `{ title = "...", players {...}, ... }` ) +local function get_clan_by_player(player) local player_name = player:get_player_name() - for _, clan in pairs(clans) do + for _, clan in pairs(clans_storage) do if table.contains(clan.players, player_name) then return clan end @@ -36,17 +42,68 @@ local function get_clan(player) return nil end +--- @param name string +local function get_clan_by_name(name) + return clans_storage[name] +end + +--- @param name string +--- @return boolean|nil +local function check_clan_is_online(name) + local clan = get_clan_by_name(name) + if not clan then return nil end + for _, player in pairs(minetest.get_connected_players()) do + if table.contains(clan.players, player:get_player_name()) then + return true + end + end + return false +end + +--- @param name string +--- @return boolean|nil +local function clan_is_online(name) + if not clans_storage[name] then return nil end + if clan_is_online_cache[name] == nil then + clan_is_online_cache[name] = check_clan_is_online(name) + end + + return clan_is_online_cache[name] +end + minetest.register_on_joinplayer(function(player, last_login) if not player or not player:is_player() then return end - local clan = get_clan(player) + local clan = get_clan_by_player(player) if not clan then return end + clan_is_online_cache[clan.name] = true + player:set_nametag_attributes({ text = player:get_player_name() .. " " .. minetest.colorize("#3d7", "["..clan.title.."]"), }) end) + +minetest.register_on_leaveplayer(function(player, timed_out) + if not player or not player:is_player() then + return + end + local clan = get_clan_by_player(player) + if not clan then + return + end + + clan_is_online_cache[clan.name] = check_clan_is_online(clan.name) +end) + +--- API --- + +clans = { + get_by_player = get_clan_by_player, + get_by_name = get_clan_by_name, + clan_is_online = clan_is_online, +}