I have a question about designing event systems for network-enabled games. I'm writing it from scratch, for fun, and am working on the details in my head of how this system should work
If you have a character with a gun and they fire a gun, my assumption that this happens locally and remotely
The "fire event" occurs
local machine: The animation for the fun firing happens. Any secondary effects (sparks, sprites, ammo ejecting, etc) also occurs
local -> remote: The "fire event" is sent to the server, I'm guessing as a hard-coded integer, that represents the action that the user has taken
server -> local: The server tells all other connected players that it received the fire event and plays the same animation back on their side
It's simple in concept (assuming I'm right so far). I was hoping to ask about implementation details about this.
To minimize information needed to be sent to the server and to prevent cheating, I'm guessing you wouldn't want to send raw client-side values directly to the event system. I could totally see a cheater reverse engineering the event system to say "my bullet just did 9999999 damage".
And because there will be some latency between the point that the local user shooting the gun fires -> sent to server -> broadcasted to the other clients, it'd make sense to also store...
- The time that the event occurred
- The player that generated the event (their ID)
And when the code goes "server -> local", you'd diff the local machine's current time by the received time. If the recipient has a lot of latency or a poor connection, the fire animation starts not at frame 0 but maybe frame 3 (based on the diff). And you use the player ID from the event to determine who to apply the animation to.
I haven't thought much about how hitscan would work in this system. Maybe the event system prioritizes the shooter's local session. e.g. if they think they hit the other player (even if the other player has a different real position) then the shot counts. Stuff like that.
Anyway to wrap it up, I was thinking that an event would look like this:
struct FireEvent {
// all events have these
event_id: 1234;
origin_time: date-time-here; // epoch float value
// player-originated events have these
string player_id;
// Xformable events have these
position: [x, y, z];
orientation: some_quaternion;
// FireEvent has this
weapon_id: 5678; // pistol
hit: other_player_id,
};
And then I'd implement this system not just for firing but for jumping, sprinting, etc. Anything else that is an action that generates a change in a user's state. I'm not super sure when to not make something an Event but I guess I can feel that part out as I go.
Is that all sound or did I miss anything? There's other details I'm interested in, regarding anti-cheat, but this post is pretty long and those details aren't as important.