Hello everyone,
I've been working on a game project: multiplayer fighter, which has client-server (authoritative) networking.
It works, but was written in a bit of salad code (worsen by the fact that was migrated from Unity).
I'm trying to tidy things up a bit, and given the client-server nature, the main flow I have goes like this (I'm not writing classes here, but operations to perform regarding players, in order of execution):
- Players Local
- read input
- perform action
- send to server
- Players Remote
- execute what the server says
- execute what the server says
- Players Local
- check what the sever said and rollback if different
- check what the sever said and rollback if different
Similar stuff happens in the server, but all players are treated as remote (so no input controllers read).
This means that I have similar blocks of code for Players that are local, and Remote ones, but slightly different or with some extras. Also, similar code for the immediate local action, and the deferred ones (but slightly different), after server messages. To summarize: before server, after server, local player, remote player. All the same but somehow different.
Do you know any standard or recommended way of organizing this? I've separated the network code as much as I could: it's in a separated external project. Middle classes in my Game project interact with both the Network and the Game. But still, given the multiplayer nature, there are these controversial elements, as shown in the bulletpoints.
I've thought about a “ControllerManager” class that would handle reading the controllers inputs and dealing with the local stuff. But then I thought “it'll probably go out of the ‘controller’ realm. Maybe better 'PlayerManager'. Hm, but I'll need a 'PlayerManagerLocal' and 'PlayerManagerRemote'…"
At the moment I have these responsibilities in some sort of “LogicClient” and “LogicServer” classes, but it's actually not the same if it's a menu screen or gameplay screen… And this is when a simple “button pressed” is multiplied x 4 different blocks of code…
My goal is to have a standardized structure where I don't have to worry about networking (just simple “sendMessageToServer()”), I don't have to worry about Input reading (should always be the same) and the player moves the same way (regardless if it's local or remote). If for example, if I need to have both a “createPlayerLocal()” and a “createPlayerRemote()” methods, it's acceptable. The question here is where would they belong to.
I don't know if I'm explaining myself properly; I hope you can get the idea 😅
Thanks in advance!