Files
bladwin-RP/lua/bladw_announcement/server/sv_function.lua
T
nocode e357313204 feat(announcement): add access control and announcement queueing
- Add BladW.Announcement.HasAccess() permission check to menu commands and net receive
- Implement announcement queueing: prevent stacking announcements while one is already displaying
- Track active announcement duration with activeUntil timer
- Add feedback to admin: send result status and remaining queue time after broadcast attempt
- Improve chat command handling: hide command from chat for all users, only open menu if authorized
- Refactor configuration and duration retrieval for clarity
2026-07-20 14:23:08 +02:00

97 lines
3.5 KiB
Lua

BladW = BladW or {}
BladW.Announcement = BladW.Announcement or {}
-- pour que les clients téléchargent le son
resource.AddFile("sound/announce.mp3")
-- coupe une chaîne à maxChars caractères (propre avec les accents)
local function LimitChars(str, maxChars)
str = tostring(str or "")
local n = utf8.len(str)
if not n or n <= maxChars then return str end
local endByte = utf8.offset(str, maxChars + 1)
return endByte and string.sub(str, 1, endByte - 1) or str
end
-- ouvre le menu pour le joueur (faut avoir le droit)
concommand.Add("bladw_amenu", function(ply, cmd)
if not IsValid(ply) or not BladW.Announcement.HasAccess(ply) then return end
net.Start("bladWOpenAnnouncementMenu")
net.Send(ply)
end)
-- /bannonce (ou !bannonce) dans le chat = ouvre le menu
hook.Add("PlayerSay", "BladW:AnnouncementChatCmd", function(ply, text)
local cmd = string.lower(string.Trim(text))
if cmd ~= "/bannonce" and cmd ~= "!bannonce" then return end
-- que ceux qui ont le droit ouvrent le menu, mais on cache la commande pour tout le monde
if IsValid(ply) and BladW.Announcement.HasAccess(ply) then
net.Start("bladWOpenAnnouncementMenu")
net.Send(ply)
end
return "" -- commande reconnue -> on la retire du chat
end)
-- reconstruit l'annonce finale : le preset sert de base, title/text passent devant
function BladW.Announcement.Resolve(entry)
local presets = BladW.Announcement.Presets or {}
local base = (entry.preset and presets[entry.preset]) or {}
return {
title = (entry.title and entry.title ~= "" and entry.title) or base.title or "Annonce",
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,
}
end
-- envoie l'annonce à tout le monde. false si rien à envoyer ou si une annonce est déjà en cours
function BladW.Announcement.Broadcast(entry)
-- déjà une annonce à l'écran ? on n'en empile pas une autre
if CurTime() < (BladW.Announcement.activeUntil or 0) then return false end
local a = BladW.Announcement.Resolve(entry)
if a.text == "" then return false end
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)
-- on bloque les suivantes le temps que celle-ci s'affiche
BladW.Announcement.activeUntil = CurTime() + dur
net.Start("bladWShowAnnouncement")
net.WriteString(LimitChars(a.title, 64))
net.WriteString(LimitChars(a.text, maxLen))
net.WriteString(a.style or "")
net.WriteUInt(math.Clamp(a.duration, 0, 65535), 16)
net.Broadcast()
return true
end
-- un admin veut poster une annonce -> je la diffuse
net.Receive("bladWSendAnnouncement", function(len, ply)
if not IsValid(ply) or not BladW.Announcement.HasAccess(ply) then return end
local preset = net.ReadString()
local title = net.ReadString()
local text = net.ReadString()
local ok = BladW.Announcement.Broadcast({
preset = preset ~= "" and preset or nil,
title = title,
text = text,
})
-- je réponds à l'admin : publié -> il ferme le menu, refusé -> il garde son texte
local left = math.Clamp(math.ceil((BladW.Announcement.activeUntil or 0) - CurTime()), 0, 255)
net.Start("bladWAnnouncementResult")
net.WriteBool(ok)
net.WriteUInt(left, 8)
net.Send(ply)
end)