MDFramework
MDFramework copied to clipboard
Feature: Ability to make only server authorative setup
Right now, some logic is intended to be server-relayed (for example, synching player info) If i disable server-relay, it would work work as intended (thought, one error would be thrown into log when new player connects on server with at least one host and 1 player) Is there a plans possibly to implement that feature? Server authoritative setups are quite often used for example, in competitive games, where cheating would ruin entire game, so relaying RPC over server to clients automatically is not thing that you want to do in that case.
This is something I'm interested in as it's how I'm used to developing games. We'll need a breakdown of what needs to be done to fully support this.
So what we lose when ServerRelay is disabled is when a Client is a network master, other clients will not receive RPCs from that client. How should we handle that? I could imagine there are cases where that behaviour is desired but other times where you want the RPC to go to the server and then the server can validate it before broadcasting it out to other clients.
The first thing we need to do is either make sure the framework doesn't make any assumptions around ServerRelay or handle the case where it is disabled. Then is there any functionality we can add to make it easier for a user to build a server authoritative game?
I don't see how we can not make assumption about ServerRelay. This is either RPC's stops on server, or relays automatically. The problem i see, is either we resolve this like you said (no assumption), or making custom logic for every new feature that needs relaying to multiple players. If we would make disable server relay, this would double the work internally sometimes. So, if we don't resolve this with no-assumption, we need to choose between server-authorative rpc's or automatic server-relayed methods.
I don't see the problem here, except for the GameSynchronizer and the GameClock for the rest of the framework it makes no difference. Most commands are only allowed on server (ie. SpawnNetworkNode, ChangeNetworkMaster).
If you make a client the network master of something and disable server relay, you just have to implement your logic so that the signal from the client goes to the server and then the server re-distributes this signal. If we somehow automated this then it would defeat the point of disabling server relay completely wouldn't it?
The framework respects the godot [Master], [Puppet] and [Remote] attributes. If you disable server relay these methods / members with these attributes will behave in the exact same way as they would if you implemented stuff yourself (without MDFramework) with server relay disabled.
There is already a backlog item to fix the ping implementation in the GameSynchronizer, once this is fixed I think the framework should work fine with or without server relay.
If we ever add any more code that needs to send signals between clients we simply do the relaying ourselves and then the framework would still be compatible with both modes.
I think there are some considerations we need to make for PlayerInfo as it's intended to be a place where a user can share info about themselves with other players (eg. PlayerName) but there is other info someone would probably want there (eg. Player score) that should be server authoritative.
If we somehow automated this then it would defeat the point of disabling server relay completely wouldn't it?
I think the idea would be that the default behaviour wouldn't support Client A -> Client B data flow, but a user could opt-in to wanting it with a server validation step in between. For example a chat message could be a Client -> Server -> Client RPC where the server filters mature language in the message first (either replacing the text with stars or denying the message completely) and I think that's something the framework could help streamline.
I see, well if we want something like that my suggestion would be the following.
- Either add a new keyword attribute like
[Master]
,[Puppet]
, etc.. Maybe something like[PuppetAuth]
and[RemoteAuth]
so authorative server puppet message. - Or we add a new replicated mode or a MDReplicatedSetting. However I think maybe extending with
[*Auth]
is the cleanest. - Add a new setting to MDReplicatedSettings at the MDReplicatedMember level similar to the OnValueChanged setting we got for clocked values. Instead it could be something like MDReplicatedMember.Settings.AuthorativeContentValidator, where you supply a
Func<object, bool>
which if it returns false we do not pass the content on.
Edit:
Or it could be Func<object, object>
so you are able to edit the content of the message. Where if it returns null we do not pass the message on. If it returns anything else we pass it on.
I think there are some considerations we need to make for PlayerInfo as it's intended to be a place where a user can share info about themselves with other players (eg. PlayerName) but there is other info someone would probably want there (eg. Player score) that should be server authoritative.
For the PlayerInfo class I wonder if we should change the way it works in general. In the current implementation I avoided using the replicator for the player name, I don't remember why I did that or if there even is a point?
If we just make stuff in the player info replicate like everywhere else, we could just make all the stuff there [RemoteAuth] (assuming we go with that solution). We could hook up validation functions to each of the default settings we put in there and make all the validation functions virtual. Then if someone wants player score they can just inherit from it and follow the example we made with PlayerName.
I like the idea of [*Auth]
(probably [MD*Auth]
) and then we add the option for setting a validator function that can alter or reject data.
With #86 this is slightly more possible now that PlayerInfos are owned by the server and the initialization flow helps the client pass data to the server for its own player info