Thanks, ya amazingly it got posted an hour after I asked!

I wasted two years of my life back around 2005 trying to implement P2P networking over UDP through double NAT with TCP fallback through a central server tunnel. It was before promises, coroutines, green threads, software transactional memories (STMs), conflict-free replicated data types (CRDTs), Firebase, CouchDB, Redux, declarative programming, etc etc etc had really gone mainstream. So I lost all of that time reinventing the wheel, only to come up with something that wasn't deterministic, because I couldn't figure out how to fork/join conditional logic around multiple conditions and data sources. My cooperative threads would just stall waiting for some network event after a user had already shut down the game lobby, and I'd find myself trying to use signals/exceptions and polling throughout my business logic.

That experience taught me that async programming isn't the way to go for mission critical code. The way to do it today looks like Raft, where event streams are centrally handled in synchronous blocking code in either an event handler or a separate thread to create a single source of truth like an STM. So last-known global state is available to all peers, the only differences coming from latency, permissions and distance cutoff. Player input as either events or composed states is sent over the network to update each peer's view of the STM to derive the final global state. Then each physics frame, peers simulate playing forward from that state for dead reckoning and update the scene view. The next frame may have a new STM state, so inconsistencies get resolved through animation metaphors like in CSS and Apple's Core Animation. But there should never be any logic that interacts with the network directly or hand waves its way through paradoxes.

Loosely that means that when you hit another player, you may see it lose a life, but then pop back in if the STM decides that the shot was a miss. The game itself is written the standard way, as if all players are on a single server, using (at most) cooperative threads like in Unity to handle game business logic in a coroutine style, rather than using switch commands to implement a state machine around player modes like IS_SPAWNING, IS_SHOT, IS_DYING, etc like most games do. Since everything is sync blocking within each cooperative thread, determinism is guaranteed by eliminating whole classes of bugs.

It would be nice if someone would put together everything I just said in a single package that's infinitely scalable to any number of peers like BitTorrent and runs on Mac/Windows/Linux without requiring a separate process or superuser privileges. The Raft/STM interface should look like a browser's local storage and provide fully indexed distributed associative key-value pairs as a JSON interface with the same transaction limitations as Firebase to allow updating trees with something close to ACID compliance from databases.

<rant>

If I ever get free of the rat race, I'd like to implement that P2P STM, but without world peace or UBI, I'll probably spend the next 20 years making rent like everyone else. I imagine the lifetimes of knowledge and experience siloed in all of our brains that could get out if we just had an extra 40 hours per week to work on the side projects of our dreams to get real work done and it haunts me. Nearly everything I do now in middle age is a waste of time because it would be straightforward to write better tools to make my job easier, but I'll never have the time to do that. So I toil in obscurity implementing other people's dreams in the hopes that someday one of their successes might help me win the internet lottery. But hey it's a living, and after going through a healing and growth process, just this year coming out of the dark night of the soul, I'm grateful for all of the lost decades and what they taught me about the nature of suffering and why we incarnated in this reality. Maybe the next generation will achieve the revolution that eluded mine.