Sign In Register

How can we help you today?

Start a new topic
Answered

Counting ppl "online"

Our game have lots of different playable matches. What we've been doing till now is simply requesting a specific match when the player choose an event from the game menu.

 (Its an Olympics game, matches are like Running 100/200/400/800m, swimming(freestyle/butterfly/breast/..) 50/100m/.. etc. Min 2 players max 8).


Everything is working fine, our real time multiplayer is already working for every event. So far so good.


 Theres a problem(more like a nuisance) tho: Since the game is still in beta on the google store (thou we have 200k downloads already), it will  happen that most events will be empty or have too few players, cause theres too few players online for too many events. It will be hard for players actually find a match till we achieve lots of players online at the same time all the time.


So instead of going trough "which event player want to play multiplayer", it would be better (at least on that stage) if he could see the number of players trying to match in each event, and the total number of players online. So he could go for an available match instead of trying his luck.


Im not sure how is the best way to do that (considering least band consumption).


# Theres anyway I can count number of ongoing requested matches? I under the impression findpendingmatches is too heavyweight cause it will return lots of unnecessary info. And Im not sure it have a limit on how much pending matches it can return either (Id need all, just to display number of players for each match). Note that Id need to update that info from time to time to update the number displayed, so its not a one time thing either..


#For displaying total number of "online" players, I think the only way here is to create a challenge(from the portal) that never expires, and always make players join that challenge automatically when going under the multiplayer menu in our game, and removing them when they leave or start a real time session..This is just to count number of player on the challenge..I will also need to keep the number of players updated, not sure if I need to request that or theres a listener for when someone joins/leaves the challenge? I have no experience with challenges..


Note this is just to count number of ppl, total and for each event. In the future we might implement full lobbies, not now.


Best Answer

Hi Giuliano,


The method you mentioned above is the most common way people find out how many players are online, yes.


You could store that as a single document in a runtime collection to query as much as you'd like, though in the event of simultaneous connections, you might want to enable some locking around the database to make sure that the numbers are consistent. 


Another method I'd recommend would be to store this in a Redis Hash. Specifically you could use something like hincrBy 1 on Connect, and hincrBy -1 on disconnect. Redis has the advantage of being very very fast, as well as wholly atomic.


-Pádraig


Giving more though about this, I think theres a way simpler way: I think I can just create global counters, every time the player connects or disconnects (system event GS_PLAYER_CONNECT/DISCONNECT ) I get the counter and increment/decrement it.

Or maybe I should use authentication response instead of GS_PLAYER_CONNECT? Not sure if theres a difference.


I will have a counter for each different match, I can just intercept the requests and increment each global counter..On Match request response I decrement.


I need runtime collections for that right? Really not used to that stuff. Do you think that will work?

Answer

Hi Giuliano,


The method you mentioned above is the most common way people find out how many players are online, yes.


You could store that as a single document in a runtime collection to query as much as you'd like, though in the event of simultaneous connections, you might want to enable some locking around the database to make sure that the numbers are consistent. 


Another method I'd recommend would be to store this in a Redis Hash. Specifically you could use something like hincrBy 1 on Connect, and hincrBy -1 on disconnect. Redis has the advantage of being very very fast, as well as wholly atomic.


-Pádraig


1 person likes this

Why not just query the system.pendingMatches table manually?


1 person likes this

Didnt even know about system.pendingMatches.

 I need to create an event to access this on the cloud and return this data to the client right?


Never heard about that Redis stuff either, and have no clue on how to use it.


The data I need is:

total players online

total players matching in r100m, r200m...sw50m...(each of the olympic events available)

total players current playing a real time session would be interesting.


 Now that you mention system.pendingMatches, cant I use system.players collection to query for the online ones, and return the count?

Total players online probably better using redis and the System.Player_Connected Cloud code.

Total players matching, can query system.pendingMatches. Will need two steps, one to query the matches, and another to go through all matches and count the participants in them.

Currently playing, can query system.matchInstance. Same 2-step as above.


Regarding system.players, you have a couple options here. One is to query the count of players where lastActiveHour < SomeTime (ie 5 minutes). However, I wouldn't trust that without a bunch of testing to determine what updates that field. I'd just go the easier route and use what I said above and use the Player Connected and Player Disconnected Cloud Code events to increment/decrement some counter.

I would also like to note in addition to above Player Connection/Disconnected, you can be in a Real-time session and still "disconnect" from GameSparks. Not sure if being in real-time and inactive elsewhere will trigger it, would need to test it.

I dunno what system.matchInstance, but its not ongoing matches since I have a bunch of it even with no players current playing it.


Can someone explain me how to use Redis? Some usage example, where do I create it?

system.matchInstance is all current and past matches. You'd need a flag in the match data to indicate it has ended, and then filter based on that.

Redis is memory caching put simply. Think of it as being able to store variables that are stored at the server level (and therefore able to be accessed in any cloud code, for any player, at any time).

What Padraig was saying was in Player Connected, do: 

Spark.getRedis().incr("onlineCount");

  in Player Disconnected, do:  

Spark.getRedis().decr("onlineCount");

  and then, whenever you want to get the number of players online, ie in LogEventRequest:   

if(Spark.getRedis().exists("onlineCount")){
    var numOnline = Spark.getRedis().get("onlineCount");
}

Spark.setScriptData("onlinePlayers", numOnline);

   


Does that help?


1 person likes this

Awesome, thanks a lot.


Theres anyway to check the Redis state in the portal like you do with the collections?

No, but you can use .keys() to return a list of all keys that you have set. You might be able to make an Admin Screen using this to make a GUI (maybe?). I have no clue if portal is separate from game server, I'd assume so. Best bet is to make a personal LogEventRequest and just return list of keys.


1 person likes this

Redis was returning one more online player than the actual number of current online players. I dunno when it started returning one more, and I dunno the cause.


Is there a chance that the system events GS_PLAYER_CONNECT/ DISCONNECT may not always be reliable(guarantee to be called)?


I now have decreased 1 manually trough an event I called from the portal. Im trying to reproducing the error logging with same account in different devices, that doesnt seem to be the issue..


But Im getting the conclusion I should really query the player system collection..All Im doing is Spark.getRedis().incr("nOnline"); on GS_PLAYER_CONNECT and Spark.getRedis().decr("nOnline"); on GS_PLAYER_DISCONNECT.


Im returning the info like that:

   

var nOnline = "-1";
if(Spark.getRedis().exists("nOnline")){
    
    nOnline = Spark.getRedis().get("nOnline");
}
Spark.setScriptData("nOnline", nOnline);

//

   (btw, I really cant get the values from redis as number? redis.get() returns strings only?...why)


Any ideas? Cant have that number starting to accumulate errors.

I've been making a chatbox last few days that is heavily reliant on showing when users are active/online, and it uses the connect/disconnect with no issues that I have seen. I don't need to use redis for that however. If you have a user login and log off 10 times via test harness what is the redis value? Repeat same process in your client. Might help narrow down if its a server issue or a client issue.

Login to post a comment