Check OnlinePlayers [HELP]

Hello guys

I’m using this addon to check the players connecting to the server, It’s working perfectly, but the problems is that, when i Change the map, Even if we are 40 players on the server, the OnlinePlayerNum become 0.

Does anyone know how to fix this?

local OnlinePlayerNum = 0

gameevent.Listen( “player_disconnect” )
hook.Add( “player_disconnect”, “MinusPlayers”, function( data )
OnlinePlayerNum = OnlinePlayerNum - 1

gameevent.Listen( “player_connect” )
hook.Add( “player_connect”, “PlusPlayers”, function( data )
OnlinePlayerNum = OnlinePlayerNum + 1

The Lua state is restarted on map change/server restart. Meaning the line [lua]local OnlinePlayerNum = 0[/lua] will be called again setting it to 0. You could try setting that var to the current player count instead of 0 as this would return 0 on a fresh server restart anyway. [lua]local OnlinePlayerNum = #player.GetAll()[/lua].

Edit: what’s the need in having the above code when #player.GetAll() returns the current connected player count (not counting connecting players)?


local OnlinePlayerNum = OnlinePlayerNum or 0

work too? Should save it if I am right.

Not unless you made OnlinePlayerNum global.

Even then it won’t do in this case because OP stated he changes the map and changing map causes full reload of Lua state.

I need to check how many players connected to the server, and not how much players are Fully Connected on the server.

#player.GetAll() check only when the player fully connected to the server.

Do you mean with “fully” that they are connecting? You should try what Mrkrabz told you.

So you want OnlinePlayerNum to save across restarts/mapchange and have it increase when a player is connecting and decrease when a player leaves? Just leave what you have but save OnlinePlayerNum in a file or liteSql.

I’m not sure what you’d use this for but I guess you’ve found a reason.

local OnlinePlayerNum = 0

if OnlinePlayerNum > #player.GetAll() then 

     OnlinePlayerNum = #player.GetAll() 


     OnlinePlayerNum = OnlinePlayerNum 


I’m using it for a Reserved Slots addon, Do you know how i can save the OnlinePlayerNum ?

If I could rate myself dumb I would

Thanks for your answer DaWhale, but #player.GetAll() output how much Players are Connected on the server,
So the new players who tries to connect on the server, need to Download The Workshop files before connecting, and take slots.

That’s why i did a player_disconnect and player_connect hook. to make it works correctly,

But when i change the map, the addon broke.

[editline]24th August 2015[/editline]

Here is my addon

hook.Add(“CheckPassword”, “RSSlots”, function(Steam64, IP, ServerPass, ClientPass, PlayerName)

local SteamID = util.SteamIDFrom64(Steam64)
local IsReserved = table.HasValue(RS.SteamIDs, SteamID)
local slots = GetConVarNumber( "ulx_rslots" )
local cur = #player.GetAll()
local max = game.MaxPlayers()
if OnlinePlayerNum >= 60 then
	if !IsReserved then
		return false, "Reserved Slots"


If I remember correctly, gmsv_gatekeeper was able to count connecting players. I’m unsure if any version of it still works, though.

Wrote this a while back for my reserved slots addon because I was running in to the same problems during map change.
It needs bromsock.

CreateConVar(“squery_bind_port”, “-1”, FCVAR_NONE, “Sets the port to use for outgoing source queries.”)
local bindPort = GetConVar(“squery_bind_port”):GetInt() or (tonumber(GetConVarString(‘hostport’)) + 500)

cvars.AddChangeCallback( “squery_bind_port”, function()
if(GetConVar(“squery_bind_port”):GetInt() != -1) then
bindPort = GetConVar(“squery_bind_port”):GetInt()

local function SourceQueryDecode(packetContents, ip, port)
local pktLen = string.len(packetContents)
local splitPositions = {}
for i=1, pktLen do
if string.byte(packetContents, i, i) == 0 then
if #splitPositions == 4 and i < splitPositions[4]+10 then continue end
splitPositions[#splitPositions+1] = i

local queryTable = {}
queryTable.protocol = string.byte(string.sub(packetContents, 6, 6)) = string.sub(packetContents, 7, splitPositions[1]-1) = string.sub(packetContents, splitPositions[1]+1, splitPositions[2]-1) = string.sub(packetContents, splitPositions[2]+1, splitPositions[3]-1)
queryTable.mod = string.sub(packetContents, splitPositions[3]+1, splitPositions[4]-1)
queryTable.players = string.byte(string.sub(packetContents, splitPositions[4]+3, splitPositions[4]+3))
queryTable.maxplayers = string.byte(string.sub(packetContents, splitPositions[4]+4, splitPositions[4]+4))
queryTable.bots = string.byte(string.sub(packetContents, splitPositions[4]+5, splitPositions[4]+5))
queryTable.type = string.sub(packetContents, splitPositions[4]+6, splitPositions[4]+6)
queryTable.os = string.sub(packetContents, splitPositions[4]+7, splitPositions[4]+7)
queryTable.passworded = string.byte(string.sub(packetContents, splitPositions[4]+8, splitPositions[4]+8)) == 1
queryTable.vac = string.byte(string.sub(packetContents, splitPositions[4]+9, splitPositions[4]+9)) == 1
queryTable.version = string.sub(packetContents, splitPositions[4]+10, splitPositions[5]-1)
queryTable.ip = tostring(ip)..":"..tostring(port)

return queryTable


function SourceQuery(sendToIP, sendToPort, callback)
if !sendToIP or !sendToPort or !callback then return true end

local querySock = BromSock(BROMSOCK_UDP)
local qPacket = BromPacket()

querySock:SetCallbackReceiveFrom(function(sockobj, packet, ip, port)
	--print("[S] Received:", packet, ip, port)
	local packetContents = packet and packet:ReadStringAll()
	querySock = nil
	qPacket = nil
	if !packet then return end
	callback(SourceQueryDecode(packetContents, ip, port))

querySock:SetCallbackSendTo( function(sock, datalen, ip, port)
	--print("Packet sent to "..tostring(ip)..":"..tostring(port))

	--print("[BS:S] Disconnected:", sock)


qPacket:WriteStringNT("Source Engine Query")
querySock:SendTo(qPacket, sendToIP, tonumber(sendToPort))


concommand.Add(“sendUDP”, function(ply, str, tab, fullStr)
if IsValid(ply) then return end
if #string.Explode(" “, fullStr) != 1 then return end
local srv = string.Explode(”:", fullStr)
if #srv != 2 then print(“Invalid arguments!”) return end
local callback = function(input)
SourceQuery(srv[1], srv[2], callback)

usage: SourceQuery(“”, “27015”, function(results) PrintTable(results) end)

That’s not the whole thing that’s just so it carries over after a mapchange

That’s what I did for my server for slots, the check function isn’t doing much but you get the just.

I haven’t tested this yet though it should work, though I’m not sure if CheckPassword is called before or after the player takes up the slot, if before just add 1 to the player.GetAll value

local Slots = {
    "64bitid" = true,
    "another64bitid" = true,

hook.Add("CheckPassword", "ServerSlotCheck", (steamID64, ipAddress, svPassword, clPassword, name)
    if (#player.GetAll() > game.MaxPlayers() - #Slots) and (not Slots[tostring(steamID64)]) then
        return false, "Reserved Slots"

One thing.
When a player is connecting and then client dissconects by clicking on the cancel button while loading, it doesn’t call the playerdiconnect hook, so what will you do about that?

use the gameevent listening.

[editline]26th August 2015[/editline]


gameevent.Listen )