From 6f579fb2dbfbc6d882fcd560b11149c46228c702 Mon Sep 17 00:00:00 2001 From: nocode Date: Mon, 20 Jul 2026 15:41:28 +0200 Subject: [PATCH] feat(announcement): add usergroup targeting and recipient filtering to broadcasts Add support for targeting announcements to specific usergroups or individual players. - Add 'target' field to store a usergroup to filter recipients - Implement recipient filtering logic that prioritizes explicit player lists over usergroup lists over preset target - Update net.Broadcast() to net.Send() when specific recipients are selected - Parse scope parameter from client to determine targeting type (all/group/players) - Return early if no valid recipients are found after filtering --- lua/bladw_announcement/server/sv_function.lua | 53 +++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/lua/bladw_announcement/server/sv_function.lua b/lua/bladw_announcement/server/sv_function.lua index cd21d27..b49996d 100644 --- a/lua/bladw_announcement/server/sv_function.lua +++ b/lua/bladw_announcement/server/sv_function.lua @@ -45,6 +45,7 @@ function BladW.Announcement.Resolve(entry) text = (entry.text and entry.text ~= "" and entry.text ) or base.text or "", style = entry.style or base.style or "", duration = tonumber(entry.duration) or tonumber(base.duration) or 0, + target = entry.target or base.target, -- usergroup ciblé (nil = tout le monde) } end @@ -56,6 +57,30 @@ function BladW.Announcement.Broadcast(entry) local a = BladW.Announcement.Resolve(entry) if a.text == "" then return false end + -- destinataires (nil = tout le monde) : + -- liste de joueurs (menu) > liste de groupes (menu) + target unique (preset/schedule) + local recipients + if istable(entry.players) and #entry.players > 0 then + recipients = {} + for _, p in ipairs(entry.players) do + if IsValid(p) and p:IsPlayer() then recipients[#recipients + 1] = p end + end + elseif (istable(entry.groups) and #entry.groups > 0) + or (a.target and a.target ~= "" and a.target ~= "all") then + local set = {} + if istable(entry.groups) then + for _, g in ipairs(entry.groups) do set[g] = true end + end + if a.target and a.target ~= "" and a.target ~= "all" then set[a.target] = true end + + recipients = {} + for _, p in ipairs(player.GetAll()) do + if set[p:GetUserGroup()] then recipients[#recipients + 1] = p end + end + end + + if recipients and #recipients == 0 then return false end -- personne à qui envoyer + local Conf = BladW.Announcement.Conf or {} local maxLen = tonumber(Conf.announcement_max_length) or 120 local dur = a.duration > 0 and a.duration or (tonumber(Conf.announcement_duration) or 10) @@ -68,7 +93,7 @@ function BladW.Announcement.Broadcast(entry) net.WriteString(LimitChars(a.text, maxLen)) net.WriteString(a.style or "") net.WriteUInt(math.Clamp(a.duration, 0, 65535), 16) - net.Broadcast() + if recipients then net.Send(recipients) else net.Broadcast() end return true end @@ -81,10 +106,30 @@ net.Receive("bladWSendAnnouncement", function(len, ply) local title = net.ReadString() local text = net.ReadString() + -- destinataires : "all" / "group" (liste de groupes) / "players" (liste de joueurs) + -- le choix du menu est explicite -> il prime sur le target du preset + local scope = net.ReadString() + local target, groups, players = "all", nil, nil + if scope == "group" then + target = "" -- vide = on ignore le target du preset, on prend la liste + groups = {} + for _ = 1, net.ReadUInt(8) do groups[#groups + 1] = net.ReadString() end + elseif scope == "players" then + target = "" + players = {} + for _ = 1, net.ReadUInt(8) do + local p = net.ReadEntity() + if IsValid(p) and p:IsPlayer() then players[#players + 1] = p end + end + end + local ok = BladW.Announcement.Broadcast({ - preset = preset ~= "" and preset or nil, - title = title, - text = text, + preset = preset ~= "" and preset or nil, + title = title, + text = text, + target = target, + groups = groups, + players = players, }) -- je réponds à l'admin : publié -> il ferme le menu, refusé -> il garde son texte