Skip to content

Instantly share code, notes, and snippets.

@x0rnn
Last active February 18, 2023 14:28
Show Gist options
  • Save x0rnn/f4e10d5af7ee761fb6e1593dc5749b54 to your computer and use it in GitHub Desktop.
Save x0rnn/f4e10d5af7ee761fb6e1593dc5749b54 to your computer and use it in GitHub Desktop.
-- full server kick (fsk) script by "a domestic cat"
local events = wolfa_requireModule("util.events")
local auth = wolfa_requireModule("auth.auth")
-------------------- Configuration --------------------
-- Defines delay before issuing a warning [seconds].
-- Default: 180 (3 minutes)
WarnTime = 180
-- Defines interval between warning and kick [seconds].
-- Default: 60 (1 minute)
KickTime = 60
-- Warning message text.
WarningMessage = "^7Server is full, please join a team or you might get kicked."
-- Starting level which from players are excluded from kicking.
AdminLevel = 2
-- Kick duration [minutes].
KickDuration = 0
-- Kick message.
KickMessage = "^7When server is full, you're supposed to join a team or leave."
-- Log file name.
LogFile = "fsk.log"
-- Warn/kick regardless if player chats as spectator?
ChatKick = 1
-------------------------------------------------------
players = {}
runFrameLast = 0
maxClients = 64
privateClients = 0
serverFull = false
fsk = {}
function fsk.onGameInit(levelTime, randomSeed, restartMap)
runFrameLast = 0
maxClients = tonumber(et.trap_Cvar_Get("sv_maxclients"))
privateClients = tonumber(et.trap_Cvar_Get("sv_privateclients"))
for clientNum = 0, maxClients - 1 do
players[clientNum] = nil
end
end
events.handle("onGameInit", fsk.onGameInit)
function fsk.onClientInfoChange(clientNum)
local team = tonumber(et.gentity_get(clientNum, "sess.sessionTeam"))
local level = auth.getPlayerLevel(clientNum)
if players[clientNum] == nil or players[clientNum].team ~= team then
local userinfo = et.trap_GetUserinfo(clientNum)
local password = et.Info_ValueForKey(userinfo, "password")
local private = false
local protected = false
if password ~= "" and password == et.trap_Cvar_Get("sv_privatepassword") then
private = true
protected = true
elseif level ~= nil and level >= AdminLevel then
protected = true
end
players[clientNum] = {team = team, joined = et.trap_Milliseconds(), warned = nil, protected = protected, private = private}
end
updateServerFull()
end
events.handle("onClientInfoChange", fsk.onClientInfoChange)
function fsk.onClientDisconnect(clientNum)
players[clientNum] = nil
local wasFull = serverFull
updateServerFull()
if wasFull and not serverFull then
for clientNum = 0, maxClients - 1 do
if players[clientNum] ~= nil and players[clientNum].warned ~= nil then
players[clientNum].warned = nil
end
end
end
end
events.handle("onClientDisconnect", fsk.onClientDisconnect)
function fsk.onGameFrame(levelTime)
if serverFull and runFrameLast + 5000 < levelTime then
runFrameLast = levelTime
local milliseconds = et.trap_Milliseconds()
local kickClientNum = nil
local kickMin = milliseconds
for clientNum = 0, maxClients - 1 do
if players[clientNum] ~= nil and players[clientNum].team == 3 and not players[clientNum].protected then
if players[clientNum].warned == nil and players[clientNum].joined + WarnTime * 1000 < milliseconds then
et.trap_SendServerCommand(clientNum, "cpm \"" .. WarningMessage .. "\n\"")
players[clientNum].warned = milliseconds
elseif players[clientNum].warned ~= nil and players[clientNum].warned + KickTime * 1000 < milliseconds then
if kickMin > players[clientNum].joined then
kickMin = players[clientNum].joined
kickClientNum = clientNum
end
end
end
end
if kickClientNum ~= nil then
local kName = et.gentity_get(kickClientNum, "pers.netname")
local userinfo = et.trap_GetUserinfo(kickClientNum)
local x, y, ip = string.find(string.upper(et.Info_ValueForKey(userinfo, "ip")), "(%d+%.%d+%.%d+%.%d+)")
local guid = et.Info_ValueForKey(userinfo, "cl_guid")
local time = os.date("%Y-%m-%d %H:%M:%S")
local line = "[" .. time .. "] [" .. ip .. "] [" .. guid .. "] [" .. kName .. "]\n"
local fd, len = et.trap_FS_FOpenFile(LogFile, et.FS_APPEND)
et.trap_FS_Write(line, string.len(line), fd)
et.trap_FS_FCloseFile(fd)
et.trap_DropClient(kickClientNum, KickMessage, KickDuration)
end
end
end
events.handle("onGameFrame", fsk.onGameFrame)
function updateServerFull()
local count = 0
for clientNum = 0, maxClients - 1 do
if players[clientNum] ~= nil and not players[clientNum].private then
count = count + 1
end
end
if count >= maxClients - privateClients then
serverFull = true
else
serverFull = false
end
end
function fsk.onClientCommand(clientNum, cmd)
if ChatKick == 0 then
if serverFull then
if et.trap_Argv(0) == "say" or et.trap_Argv(0) == "say_team" or et.trap_Argv(0) == "say_teamnl" or et.trap_Argv(0) == "pm" or et.trap_Argv(0) == "m" then
local team = tonumber(et.gentity_get(clientNum, "sess.sessionTeam"))
local level = auth.getPlayerLevel(clientNum)
if team == 3 then
local userinfo = et.trap_GetUserinfo(clientNum)
local password = et.Info_ValueForKey(userinfo, "password")
local private = false
local protected = false
if password ~= "" and password == et.trap_Cvar_Get("sv_privatepassword") then
private = true
protected = true
elseif level ~= nil and level >= AdminLevel then
protected = true
end
players[clientNum] = {team = team, joined = et.trap_Milliseconds(), warned = nil, protected = protected, private = private}
end
end
end
end
return(0)
end
events.handle("onClientCommand", fsk.onClientCommand)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment