question

Jérémy avatar image
Jérémy asked

What's a proper way to get a persistent server by group/clan ?

Our scenario is the following:

- Players can create clans and invites other players
- Each clan has it's own world state
- A player can start a realtime game in that world
- If an other player wants to play in that clan, it will join the same game

My current plan:

- I plan to use a Group entity to store the clan world state and the server infos.
- When a player wants to play in a clan he call a CloudScript function

// Pseudo code of that function
function(groupId)
{
                
// retrieve the clan data data = getGroup(groupId); // if a server already exist, return it
if (data.server) return data.server; // if there's no server, request a new server
data.server = requestServer(groupId); // Write the new group state
if (updateGroup(data))
return data.server; // if there was a problem during the Group update
// ie. a sync issue with 2 players joining at the same time
shutdownServer(data.server); // Ask the client to retry
return RETRY }

- When a server is empty it removes itself from the Group entity

This plan assumes a lot of things as I'm new to PlayFab. In particular:
- there's a way to tell when 2 players update the Group at the same time
- a server can reliably remove itself from the Group

The question is then: Does it sounds viable ? Is there a better way ? Or should I look somewhere else ?

And as a bonus question:
I was hoping there would be a way to request the list of active server and get some infos (I'm interested in the Group id) but some other forum post seems to imply there's no way to do it. ( https://community.playfab.com/questions/40393/getting-a-list-of-servers-on-20.html )

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

·
brendan avatar image
brendan answered

Having a server host a group of players is straightforward enough - the capacity of the server is going to be down to your server code and the model of server machine you go with, so there's no real issue there.

As far as Groups being used to track on this, there are two key points:

1. (to your question about updates) If multiple users try to update the Group or any of its data (Entity Files/Objects) at exactly the same time, only one is going to succeed. The other(s) will get an error and have to retry.

2. You'll want to throttle the rate at which you update the Group data to keep your costs reasonable. Updating every time anything changes in a realtime game session would be extremely expensive, for most game models. Ideally, just have the server update the Group's Entity File (assuming that's your target, since it'll be a non-trivial amount of data) at the end of the session, or once every N (15? 30?) minutes if sessions are long.

For removing the server from the Group, you'll need to have it do that as part of its shutdown logic. If a server crashes and so doesn't remove itself, you'll want to have logic that requests a new server if the one listed in the Group is non-responsive, and have it update the Group for the server info.

Finally, correct - v2 server hosting does not have a "list servers" call. You'd need to track that externally, currently (potentially in a Redis table).

9 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Jérémy avatar image Jérémy commented ·

Thanks for your help @Brendan, I have some more question around this:

- I found the limits to Group entities and files, but I'm not sure wich categories in the pricing page apply to Group entities.

- What is the behaviour of RequestMultiplayerServer when providing the same SessionID ? the only info I could find is this:

"SessionID- An identifier for the session. This is a GUID string generated by the caller. Retries to this API for the same logical session should re-use the same identifier. This mitigates the possibility of caller retry behavior creating unnecessary servers."

But I don't know if it throw an error or return the already existing connection info. If it returns the existing server, I could put the Group EntityKey as a SessionID wich will simplify my script: no need to store anything, just call RequestServer

0 Likes 0 ·
brendan avatar image brendan Jérémy commented ·

Apologies, Jeremy - sometimes the AnswerHub system fails to send email notifications of follow-ups. If you don't get an answer for a while, feel free to re-ping on the post.

The answer is that we would advise against trying that. The Session ID is meant to be a globally unique identifier (GUID), so that it does not collide with others.

0 Likes 0 ·
Denzie Gray avatar image Denzie Gray brendan commented ·

@Brendan

Using https://docs.microsoft.com/en-us/rest/api/playfab/multiplayer/multiplayerserver/requestmultiplayerserver?view=playfab-rest

to mean - RequestMultiplayerServer - no C#, only CloudScript.

Assuming the GUIDs were kept server side and the client was unable to make Server Requests directly, would that be okay?

Does "RequestMultiplayerServer" reset the server heartbeat TTK?

When a server shuts down, if I call RequestMultiplayerServer
and use the same SessionID, will this be a new instance of the server? What I mean is, should I expect every call to an inactive session/server to be from a 'clean' state?

Say I have a SessionID in Cloudscript or even better (RequestMultiplayerServerResponse), how would I use this to communicate to the gameserver?

My plan is to have a Webhook that the clients call which will,
Request the server and then pass an action to it. Here is a breakdown.

1. Make call to CloudScript with action

2. Request server.

3. Pass action to server (this is a Unity.exe).

4. Potentially return response to player

5. CloudScript function ends;

This is a turn-based game so I don't expect latency to be an issue.

Thanks in advance. And thanks for the previous response.

0 Likes 0 ·
Show more comments
Show more comments
Denzie Gray avatar image Denzie Gray commented ·

@Brendan

@Jeremy

Is there any answer to this question by Jeremy?

""SessionID- An identifier for the session. This is a GUID string generated by the caller. Retries to this API for the same logical session should re-use the same identifier. This mitigates the possibility of caller retry behavior creating unnecessary servers."

But I don't know if it throw an error or return the already existing connection info. If it returns the existing server, I could put the Group EntityKey as a SessionID wich will simplify my script: no need to store anything, just call RequestServer"

0 Likes 0 ·
brendan avatar image brendan Denzie Gray commented ·

Thanks for letting us know this was missed - answered above.

0 Likes 0 ·
Denzie Gray avatar image Denzie Gray brendan commented ·

Thanks for the reply.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.