TheYellowArchitect / doubledamnation

Exclusively Co-Op Metroidvania with Movement as smooth as Smash Bros Melee
GNU General Public License v3.0
19 stars 2 forks source link

ONLINE MULTIPLAYER #42

Open TheYellowArchitect opened 2 years ago

TheYellowArchitect commented 2 years ago

Double Damnation can already be finished fully online, on Steam and LAN Then, why is it not advertised as such on Steam? It even has desync as a feature, which exists in no other game in existence - this is where I spent most of my netcoding devtime (5 months?), yet why is it nowhere mentioned or promoted?

Because Forge Remastered(the netcoding framework I used) clashes with SteamP2P. The steamworks integration is buggy, but even worse, Forge Remastered has packet bugs (only noticeable at >0 ping)

Ultimately, on Steam, this means there is jitter for the client (Player2/Mage), and all packets are unreliable (unironically UDP) hence you can imagine the infinite bugs. On LAN, there is no jitter and all packets are reliable (except streaming packets like position and input snapshots), but there are still some packet bugs: One of the worse being code-wise that the host has to send a position snapshot each frame even if his position is exactly the same as the past snapshot, otherwise packet acks flood the network because of faulty timestamps!

tl;dr: High-Level Netcoding is complete. Low-Level Netcoding is bugged, and I must port to Mirror.

Forge Remastered is dead, so its not like devs gave up development but at least it was a complete, stable project, no. Anyway, assuming I'm hyped to return to do some huge update on Double Damnation, I will focus on Online Multiplayer, since all of netcoding game logic is complete, and its a damn shame the transport code below is bugged because of the netcoding framework. "Swapping" low-level should be possible. Porting in Mirror must be done.

==================

Mirror Tracker below, to complete and public release Online Multiplayer

===================

That last item may have surprised you. Believe it or not, coding more players is easier than having another player "share" the same entity. Seriously, generally speaking, all you need to do is sync a position (Vector2), and an animation/sprite (enum ushort)

And for this reason, I plan to release online multiplayer + 12 player mode, together, so its not "the exact same game with the exact same content, but with online multiplayer", but having an incredible unique new mode atop of that! A proper "ultimate" version.

WHEN? When I get the will and desire. The hype, so to speak. Explained here

TheYellowArchitect commented 2 years ago

Just finished the second task, aka replicating the old packet transfer design: RPCs which host can only send to client, and client to host. It kinda sucks that code-wise it's not as simple as Forge's (Receivers.All/Other), but if it works, idc, its not overwhelming bloat.

MirrorCommunicationController (imitation of NetworkCommunicationController) spawns once, and here I shall dump the RPCs.

TheYellowArchitect commented 2 years ago

I ported the Position Interpolation + Input Synchronization logic, to use Mirror's packets instead of Forge's (bless my modular netcoding, making netcoding logic a layer above and seperate from game logic) The only difference from Forge's netcoding version, is the serialization/deserialization and packet sending/receiving. Yet...

There is heavy jitter, at 0 ping

https://user-images.githubusercontent.com/25630803/185691929-bfe9ba9c-0a68-456b-831b-1a7e99b77f03.mp4

I use KCP's transport for Mirror. For position, I send a float timestamp and Vector2 position only when position has changed (so as not to flood the network) Unreliable RPC, of course. And as seen in debug log above, the timestamps are perfectly delivered in expected time. Input snapshots also are greatly delayed So, here is what I think could be wrong on position interpolation:

  1. Collision with Unity physics/velocity, somewhere. No idea where, would take a few days to debug via shotgun debugging.
  2. Network Flood I do not know how I can confirm that in Mirror, or otherwise
  3. My position interpolation code is flawed Needs more testing, to ensure different timestamp diffs dont bug it (previously, all timestamp diffs were the same and hence there was no jitter, at the cost of sending a snapshot each frame even if it was the same as previous -_-)

Here is what I think could be wrong for input snapshots:

  1. Horrible serialization Unlike Forge's where I do my own serialization, I let Mirror do it for me. But I really doubt it's that bad as to make bloated packets, as I use primitives.
  2. KCP Transport For input snapshots, I use reliable RPC. Still, having 0 ping and having that delay, is just not normal. I can only hope I was sloppy on my porting input snapshot manager, otherwise Mirror is a bad netcoding framework as well

There is also some weird behaviour I noticed with my ported code. One is that levelsync/levelskip is sometimes bugged, even though the levelsync/levelskip code is ported 1:1 which makes me think I missed something. Something obviously important, as netcoding must be 100% stable, yet isn't. Some race condition bug. Also see the duplicate snapshot in the above video. Doesn't matter though, as jitter is unrelated to it, no way a duplicated packet can cause this.

========

Ultimately, I overestimated my abilities, thinking I can just port the entirety of my netcoding in a week, right before release. Crunching isn't enough. Merely reading and understanding how Mirror works - and trying to twist it into my old netcoding architecture - took 2 full days by itself. And I just keep running into issues and annoying errors, which I fix but in a slow pace. At least, there has been some obvious progress. Sure, I could spend a week to port all RPCs (aka all the netcoding) as I have done for Position Interpolation and InputSnapshotManager but I am certain there will be further race condition bugs, or something else I hadn't calculated. I cannot imagine desync code running perfectly, that's for sure. And the goal of porting to Mirror is to run perfectly... It just feels Mirror is made for a headless server setup, and that is against the design I had for Forge. Add that to my inexperience with a new netcoding framework (because anyone can know high-level netcoding, but each API is so different and it will take a few days to figure out each edge-case)

Anyway, I shall delay online multiplayer for now, until I figure out the 1/2 points above, aka why it jitters, before I continue.

It is kinda sad that I spent 5 days (5 days away from release!) because Forge has issues with Steam. I could have used this time to learn how to make a master server onto my own VPS server which I already have. Should be simple. Ah well. Until release, I will just polish the game, there are some serious bugs I need to fix.

TheYellowArchitect commented 2 years ago

Actually, I should test again, while disabling Unity's physics from the player character (rigidbody or colliders) to confirm whether the netcoding framework is to blame. Should be an easy test.