📜 ⬆️ ⬇️

How to make an automatic update of the client online game

In this article I will talk about how I made the auto-update system for the client online game. Link to the source (Delphi) at the end of the article. In fact, I implemented such a feature in two of my games, and if the first pancake came out a little lumpy (in the game Spectromancer), then the second implementation was very convenient and effective. This is my first article on Habré, so do not hit hard, but rather point out the flaws in the comments :)

Game Update Algorithm



Version check


First of all, at startup, the client asks the server for the number of the current version (X) and the minimum number without an update (Y). If the client version is not lower than Y, then the update is not required, otherwise the client launches the update utility " GetNewVersion.exe X ", and terminates.

As you can see, the version number is passed by the parameter - this allows you to upgrade the game to any version available on the server if you wish, and even lower it. If the parameter is not passed, the utility itself will ask the server for the current version number. The version number is just an integer, the numbering scheme can be any, for example, my version 1.12 corresponds to the number 1120.
')
The answer from the server does not come instantly, but before we receive it, we cannot create a game window, you may have to close it right away, and strange flickering on the screen is not at all what we need. Waiting for an answer would be necessary to take something, and the client takes it by loading / unpacking the most difficult JPEGs. You can't wait too long either: the player started the game - and nothing happens on the screen, it’s a mess. Therefore, if within 1.0 sec. the response from the server never arrived - the game loading continues in the usual manner. There is nothing wrong with that: as soon as a player tries to log in to the server, he will receive a message about the need to update the client, or that the server is unavailable.

Download file list


Knowing the version number, the update utility downloads the list of files to the address: [base_ur]>/[]/filelist
This is just a list of files in CSV format with checksums, as well as sizes in compressed and uncompressed form, each line looks like this in it:
18*Priest.tga;1053151921D9;91719;107372
Here "18 *" means that the 18 characters in the file name are the same as the previous file. Since files usually go in alpha order, and paths can be long - this significantly saves the size of the file list. For a web server where compression is not enabled, this means that the file will download faster and the update will start earlier.

Downloading new or changed files


We do not know how outdated the game client is, maybe some files have been changed or deleted manually. We also don’t want to download too much, so after receiving the list of files, the utility starts checking them in order for updates: if the file is missing from the game folder or its checksum is different, the file is added to the download queue. At the same time, no more than 2 files can be loaded - this is quite enough so that on the one hand the download does not slow down, but on the other hand, it happens sequentially.



A special theme is the display of progress. Until the entire list has been processed, we do not know exactly how many files are to be downloaded and what size they are. However, as soon as the first file is uploaded, we can already display some information. In fact, the progress displays the download queue: how much to download and how much has already been downloaded.

The downloaded files are immediately unpacked and saved in a temporary folder, I use the zlib library for compression.

When the entire list of files has been processed and all downloads have ended, the utility checks for the existence of the changes.txt file and, if it exists, displays it. The user is prompted to start the update process. There are no changes in the game folder before pressing the “Update” button, so you can refuse it without any problems.

By the way, if the user interrupts the download or refuses the installation, then the next time he will not have to download all the files again: before downloading the next file, the utility checks its presence in the temporary folder and if the checksum is the same, the download is considered successful.



But when you click on "Update", the utility launches another utility - " InstallUpdate.exe ", and itself closes.

Install Update


Why do I need another utility? It's simple: to update the game files you need to run with administrator rights. And for downloading updates, on the contrary, it is contraindicated. Because, if only you are not the lucky owner of an EV-certificate of code signing, launching the process with administrator rights results in displaying the UAC window. And if at the start of the game, instead of the usual interface, the player sees this:



... then this is, at least, a reason to be wary, or even to refuse to launch. It’s another matter if you manually agree to install the update - in this context, the UAC window is perceived normally. Unfortunately, the process in Windows cannot elevate its rights at run time - this property has been invariably since its launch. Therefore, I use two separate files. In fact, GetNewVersion.exe and InstallUpdate.exe are the same utility, the files are identical. And the action is determined by the transmitted parameters and the name of the executable file.

So, being launched, InstallUpdate copies the game client files from the temporary folder to the game folder, and then launches the updated client and terminates. At the same time, the file GetNewVersion.exe can be updated.

All actions, as well as errors that occur, are logged in detail in the log, this is very useful for debugging.

The process of preparing a new version


We reviewed the update operation scheme from the point of view of the game client, but how to make it all work? To prepare new builds, I wrote another utility - CompressBuild . It recursively scans the folder, compresses files using the Deflate method, and lists information about them in the file list - the filelist . After compression, the symbol "_" is added to the file name. Compressed files are not compressed again, so if necessary, only separate files can be updated in the build folder, CompressBuild will update only them.

Some files in the game client are changed during the work, for example, they contain settings. Such files should be ignored; the corresponding templates the utility takes from the exclude file. That is, these files simply do not fall into the filelist and do not deteriorate on the client during the update.

Thus, to prepare a new build, I need:

1. Copy the \master folder to the \[_] folder
2. Run CompressBuild , which will pack the files in it and list them.
3. Upload all this to the game site.
4. Change the current version number to the number you just downloaded on the game server. Voila!

From now on, when upgrading, people will receive a new version.

Well, folders with old builds on the server can be deleted so as not to take up space.

Conclusion


Of course, my update system is not perfect and not without flaws. For example, if a file has been deleted in the client, it will remain with the players. If the file has been renamed, it will be loaded as new, and the old instance will not be deleted. You can, of course, modify the update utility by adding commands to delete / rename files to the list of files, but in general such problems are irrelevant for my game, so I did not bother.

Well, the source can be taken here: astralheroes.com/files/UpdaterSrc.zip
(compiled in Delphi-2006 / Turbo Delphi, I can not vouch for other compilers).

Source: https://habr.com/ru/post/423207/


All Articles