And so I've teached them simulations to talk to each other.
To revisit my protocol code, two years old at that, was surely a fascinating journey into myself of time past.

As a result, I've already been able to ride a truck with two of my friends as passengers.

There's a catch however: I am still working on client-side input prediction.
This is not at all simple to get right in a game with this kind of dynamics, not to mention physics-based projectiles.
If I let the client be autoritative over bullet collisions... a victim you'll be getting damage even though the bullet flew somewhere else on your screen;
to make it worse, the attacker may even be facing a completely different direction.
These problems arise because the other player sees the past version of you.

Contrary to FPSes, this is a 2D game -
canvas reveals way more imperfection than a 3D world with huge horizons and blazingly fast bullets.

I did this before; it was the scripted (Lua) version of Hypersomnia and it worked not that bad.
If I don't come up with something fancy (like, some astral body being a reflection of the past self?), I will stick to the good old approach and live with the consequences.

(In case you're wondering, yes, I love to have these messy figures from the profiler all over the place.
I recognize it as a form of beauty. I've even redirected the console output to text rendered in-game, as seen in right top corners)

The screenshot above is nothing else than a test of two independent client simulations connected to a local server,
all three in a single process, so tapping F5 once in Visual Studio completely setups my cosmic laboratory.
(The connection is powered by ENet networking library. I will not be using RakNet anymore.)

Here I must necessarily brag about my architecture (or put more gently, my habit to keep the code reasonably clean),
for I am perfectly able to deterministically replay both the server and the two client sessions visible on the screen.

This possibility is a huge advantage to say the least.
It practically lets the server to have backups of every step of the simulation and as a player,
you will be able to accurately replay your gaming session from the very main menu until logging out and pressing quit.
Both of these perks with negliglible overhead, since inputs are several orders of magnitude lighter than state.

The recording itself is so cheap that I might even consider leaving it enabled by default in clients.
This way, precious memories of raiding Metropolis with a bunch of Resistance friends will never be lost.
Plus, you will always have conclusive evidence for somebody cheating.

In the meantime, I made some drastic improvements to how the game makes a copy of the world.
Using per-field serialization, cloning a 40 MB world took around 12 ms and now it takes around 5 ms.
The new cloning function is basically a bunch of memcpy calls, one call per component type.
(To achieve this I needed to make the state completely devoid of pointers for real, to the extent that I had to implement constant-sized versions of vector and map)

Now this is huge, especially for the server, since cloning itself is the bottleneck of operations like occasional state backup and/or delta compression.
Having successfully cloned a cosmos, you can always offload related work to some worker thread and continue simulating the main game world without further interruption.

I made my rectangle packing algorithm (used in the game to pack textures) available as a standalone repository in our TeamHypersomnia.

Delta compression is also complete. It turned out to be quite a verbose beast, to the point that I've put together several unit tests.
Thanks to delta, the server can transfer a 40 MB universe to the newly connected client with maybe just several kilobytes worth of network traffic.
My fellow philosopher helped a bit with raw byte-wise delta encoding.

Last but not least, I've implemented stress tests of determinism. (this is sort of a developer tool more than anything else, but still deserves a honorable mention)
I'm even considering making this a unit test.

Right now you simply set launch mode to LOCAL_DETERMINISM_TEST and decide upon determinism_test_cloned_cosmoi_count, whose name speaks for itself.
This will launch the game as always, but with several worlds in the background, initialized with the same state.
Your inputs (or ones extracted from a recording file) will be applied to each single world in existence.
After every logic step, the test serializes all worlds and compares the byte contents. They must remain identical down to a single bit.
If they're not, it stops the simulation and tells you the faulty step number. Obviously you can replay it later so that you can delve deeper into the issue.

This will totally come in handy because as of currently, my netcode needs the simulation be completely deterministic (and when I say completely I mean bit-wise).
This tool is going to catch even the tiniest divergence.

That would be all about last month's progress.
Expect some playable multiplayer soon!