
A prototype of the War Robots game appeared a few years ago (then it was also called Walking War Robots). This was Pixonic's first tactical PvP experience, so many future problems were built into the code from the beginning. But despite a number of difficulties (the popularity of the project was growing rapidly, a small team could not completely change the architecture of the game in a short time), we eventually managed to minimize the number of cheaters, as well as fix other shortcomings of the original code. I'll tell you a little more.
The very first WR implementation did not use an authoritarian server — each of the clients independently controlled their own health indicators and forwarded the changes to the other players through the network. For forwarding messages, we used remote procedure call (RPC).
')
A schematic view of sending a new health value using RPC when taking damage through the Photon Cloud Server and then delivering it to other players.This approach was easier to implement in terms of architecture, since it did not require logic on the server, and the calculations were performed on clients. As a result, the team was able to quickly get a pilot version of the game and assess the interest of the audience.
Of course, in the end, the question of fair play became acute. It is not possible to directly verify whether the client actually registers all incoming damage. And with the growth of the audience, this problem is expectedly becoming more urgent.
"Neubivashki"
The problem of "immortal" players can be conditionally described in three situations:
- The player has problems connecting to the network. As a result, he simply "does not see" his damage and does not send an updated state. For the other participants of the game, it looks as if the hit on the target was delayed, incomplete or completely absent at some point in time.
- The player deliberately terminates its internet connection (for example, by putting the application in inactive mode) and ignores incoming damage.
- The player cheats in another way and becomes immortal.

There are several ways to solve this problem.
- You can seek out and ban cheaters or automate their search according to different criteria (for example, average damage in combat). To do this, you need to build a comprehensive software protection, which, based on the player's behavior and other aspects of the match, could recognize the unfair game.
But this is a rather time-consuming option, since it will be necessary to track the gameplay of each player, as well as form and test a set of rules by which cheaters will stand out from the crowd. - Another popular solution is the authoritarian server. In this case, all the logic of the match runs on the server, and it fully controls the shooting and damage.
We thought about different ways to implement this approach, also considered the option of launching Unity in batchmod, but eventually abandoned the idea, as it required completely redoing the client-server interaction in the project.
Then we began to look for another way out that would reduce the problem to a minimum.
What have we come to? ..
Democracy

We used the same database that was already in the prototype, but changed one key point - the health of the players was now controlled by the server based on all the data received by it.
Each of the clients sent damage indicators to the server not only on their own, but also on other players. Then the server made a decision about the current state of health of the clients, collecting a quorum of readings and sending it to the players. Thus, we have some mix between local damage calculation and authoritarian server.
Immediately it is worth noting the limitations of this method. It does not work for games 1 on 1. Quite. If two players have a discrepancy in the testimony - it is unclear which of them is telling the truth.The main plus is that it was a relatively “cheap” solution, since we did not have to rewrite the network code globally and at the same time managed to solve the problem with the cheaters.
Algorithm


In fact, the algorithm for causing damage can be divided into 3 parts:
- Registration of damage by each client of all players and sending these readings to the server.
- Collection of damage indicators, aggregation, calculation of the current health of the victim and sending out the total value to all participants of the match.
- Getting current health from the server.
In more detail, this happens as follows: each of the clients tracks hits for each player and records this damage on the server. An RPC message is sent to the server with information about the hit in the form of:

The message indicates the victim's ID, the ID of the damage, the shot ID, and the damage itself. It is worth noting that in War Robots, each projectile is assigned a specific identifier that is synchronized between clients.

The next step is aggregation of damage indicators on the server. A quorum of size N is taken, after which the client damage indicators are aggregated. The final damage is applied to the target and a new state of health is sent to all participants in the battle. Schematically it looks like this:

Thus, this is not an authoritarian server, but also not a simple local damage calculation for each player. As a result, one person cannot “drop” the entire system. Of course, he may try to correct the damage, but he will not be able to completely avoid him.
Of course, this solution is not perfect. The main difficulty is the need to synchronize the ID of each shot (which is a separate problem). But what happened to the players' complaints about cheaters after the introduction of a new damage calculation system:
Blue graph - the number of complaints from players to cheaters .
Of course, the work on WR continues, but the main thing that we learned from this story is that you should not always rely on ready-made answers from textbooks. At each stage, from prototyping to retaining the existing player base, we proceeded from current tasks and needs.
If everything was done right away a few years ago, some mistakes could have been avoided, but the game itself could simply not have fired, and the resources would have been wasted.