Sie werden normalerweise nicht einmal von derselben Maschine verarbeitet, geschweige denn von derselben Codebasis. Das Benutzerprofil wird von einem Dienst übergeben, der sich nur mit Benutzern befasst. Der Simulationsserver kümmert sich um Dinge im Spiel. Möglicherweise gibt es sogar einen anderen Sitzungsserver, der die beiden miteinander verbindet.
Der Simulationsserver verfügt über eine ID, die jedem Benutzer entspricht. Die Player
Klasse sieht also möglicherweise folgendermaßen aus:
struct Player {
UserId _user;
PlayerId _player;
int _health;
// etc.
};
Für alles, was das Benutzerkonto betrifft, sendet der Server eine Nachricht an den Benutzerdienst, in der er darüber informiert, was passiert ist, z
struct UserAchievementMessage : public UserMessage {
UserId _user;
AchievementId _achievement;
uint64 _timestamp;
// etc.
};
Wenn der Benutzer eine Leistung für etwas im Spiel erzielt, teilt der Simulationsserver dem Benutzerdienst lediglich dies mit (normalerweise über eine Art Messaging-Dienst, z. B. RabbitMQ oder dergleichen), und vergisst dies dann (da dies nicht die Aufgabe des Simulationsservers ist sich um Benutzer kümmern).
Wenn der Benutzerdienst Spiele im Spiel benachrichtigen muss, kann er erneut einen Nachrichtendienst (oder einen Proxy über einen Spieldienst) verwenden, um Spielerinstanzen dieses Benutzers über Änderungen zu informieren. Beispielsweise kennt der Match-Service alle laufenden Matches, wer an diesen Matches teilnimmt usw., sodass ein Benutzerdienst den Match-Service einfach auffordern kann, alle Simulationsserver zu benachrichtigen, auf denen eine Instanz dieses Benutzers (eines Spielers) vorhanden ist das hat sich geändert. Durch die geschickte Verwendung von RabbitMQ oder dergleichen kann auch die Notwendigkeit eines Proxy-Dienstes entfallen.
Samller / einfachere Spiele haben oft nur einen oder zwei Server und überlappen viele Funktionen. Dies liegt jedoch an Zeit- / Budgetmangel und nicht an guter Technik.
In jedem Fall User
und Player
(oder was auch immer Sie verwenden) sind zwei völlig getrennte Dinge. Die Kupplung sollte, falls vorhanden, so leicht wie möglich sein. Eindeutige IDs sind normalerweise der richtige Weg. Jeder Benutzer kann beispielsweise eine UUID haben, und jede Player
Instanz enthält nur diese UUID. Wenn sich etwas auf a Player
auswirkt User
, rufen Sie eine Methode auf oder senden Sie eine Nachricht UserManager
mit der betroffenen UUID und anderen Details an. Sie UserManager
können dann interne Datenstrukturen aktualisieren, Netzwerknachrichten senden oder andere Implementierungsdetails ausführen, die erforderlich sind.