<i>Develop strong out of sync (OOS) detection tools early, and learn how to use them.</i><p>The way lockstep work is that the clients gives themselves a rendez-vous in the future and agree to compute one turn of the game, given the players' input of that turn, at that moment. It's very clever. The players input are sent to every clients and will be computed in the future in a deterministic way. So every client is computing the exact same game. Now if the clients doesnt compute the same game given the same players' input, the game is OOS and that basically should never happen because the game is dead.<p>To detect an OOS, a client needs to compute a hash of some relevant game data (ultimately "everything" ends up being represented by the position of the units (plus a dead state)), every <i>turn</i> and send them with its "end of turn" message to the server/clients. If clients disagree with the value of the hash, they are OOS.<p>The cool thing with lockstep is that you can record every turn inputs (which is fairly light) and then replay the whole game - because that's already how a game is played. So, when you have an OOS - or any bug, you can just replay the game until the OOS and try to fix it. Sometimes it doesnt work though and you may replay the game without detecting any OOS.<p>If you dont detect an OOS after a replay, you're basically in deep shit. I mean <i>needle in a haystack of c++</i> kind of deep shit. Every client needs to dump <i>every data of every function that ever ran</i> in a log file, and then you need to reproduce the OOS and then compare the log files and then guess what caused the data to differ.
As with all historic RPG's, The key lesson is in how you craft your C integer types. One type allows you to cleverly assign various character traits to specific groups and users, the other turns Ghandi from a benevolent peace loving icon to a harbinger of endless misery and destruction<p><a href="https://www.geek.com/games/why-gandhi-is-always-a-warmongering-jerk-in-civilization-1608515/" rel="nofollow">https://www.geek.com/games/why-gandhi-is-always-a-warmongeri...</a>
Looks like they want to avoid changing gameplay as much as possible.<p>Considering their focus on preserving even minute details of game dynamics... I wish they'd made an exception for pathfinding - the algorithm in the original AoE is extremely bad.<p>In particular, I really wish they'd introduce some improved ways to command groups of units. IIRC the Rise of Rome expansion introduced double-click group selection of all similar units, so it's not without precedent.
If they change nothing else, my number one wish would be formations like in AoE II. I can't stand the way units just swarm like ants when told to move together.
<i>> Assume the original developers knew what they were doing. The old code shipped and was successful. If you don't understand it, most likely the problem is you, not the code.</i><p>This needs to be chiseled on a tablet somewhere.
Love reading gamedev post-mortems such as these ;)<p>Although what author discusses is specific to Age1 engine. Time sync in webrtc peer networks encounters many of the same pitfalls. With errors tending to propagate non-linearly as more peers (and more complex scene objects) are added.<p>ThreeNetwork - Network sync library for Three.js<p><a href="https://github.com/takahirox/ThreeNetwork" rel="nofollow">https://github.com/takahirox/ThreeNetwork</a>
Not building custom containers is generally good advice. The chance you build something that underperforms is noticeable. Other coders won't know what you've made. There is a fair chance that std has what you need if you're even just a little bit thoughtful.
Good thing they decided to keep the gameplay the same, like Starcraft: Remastered. I never played AoE 1 competitively, but if it's like SC many bugs/glitches became core gameplay mechanics. Here's hoping the AoE 1 remake fares better than the one for AoE 2!
I have no real experience with C/C++ as well as game development but I always wonder what would happen if old games like these would get recompiled with an, for example, avx2 flag.