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
This commit is contained in:
2026-07-20 15:41:28 +02:00
parent 490d5a2194
commit 6f579fb2db
+49 -4
View File
@@ -45,6 +45,7 @@ function BladW.Announcement.Resolve(entry)
text = (entry.text and entry.text ~= "" and entry.text ) or base.text or "", text = (entry.text and entry.text ~= "" and entry.text ) or base.text or "",
style = entry.style or base.style or "", style = entry.style or base.style or "",
duration = tonumber(entry.duration) or tonumber(base.duration) or 0, duration = tonumber(entry.duration) or tonumber(base.duration) or 0,
target = entry.target or base.target, -- usergroup ciblé (nil = tout le monde)
} }
end end
@@ -56,6 +57,30 @@ function BladW.Announcement.Broadcast(entry)
local a = BladW.Announcement.Resolve(entry) local a = BladW.Announcement.Resolve(entry)
if a.text == "" then return false end 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 Conf = BladW.Announcement.Conf or {}
local maxLen = tonumber(Conf.announcement_max_length) or 120 local maxLen = tonumber(Conf.announcement_max_length) or 120
local dur = a.duration > 0 and a.duration or (tonumber(Conf.announcement_duration) or 10) 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(LimitChars(a.text, maxLen))
net.WriteString(a.style or "") net.WriteString(a.style or "")
net.WriteUInt(math.Clamp(a.duration, 0, 65535), 16) net.WriteUInt(math.Clamp(a.duration, 0, 65535), 16)
net.Broadcast() if recipients then net.Send(recipients) else net.Broadcast() end
return true return true
end end
@@ -81,10 +106,30 @@ net.Receive("bladWSendAnnouncement", function(len, ply)
local title = net.ReadString() local title = net.ReadString()
local text = 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({ local ok = BladW.Announcement.Broadcast({
preset = preset ~= "" and preset or nil, preset = preset ~= "" and preset or nil,
title = title, title = title,
text = text, text = text,
target = target,
groups = groups,
players = players,
}) })
-- je réponds à l'admin : publié -> il ferme le menu, refusé -> il garde son texte -- je réponds à l'admin : publié -> il ferme le menu, refusé -> il garde son texte