- Wisp Technology
For support on this component, please use the forums.
The binary difference patcher is built on our WISP networking library but is otherwise entirely standalone.
- The patcher is available free of charge and may be used in your projects, royalty free.
- You may not decompile or reverse engineer any of the files in the included download, except where the source code is explicitly included in the download.
- You may not re-sell or otherwise profit directly from the redistribution of Darkmoon Labs software. In other words, you can use the patching software as part of your project, but you can’t sell the stuff we made directly. Common sense, right?
Let’s get started.
After initial setup, creating patches is a quick and easy process. The basic steps are outlined in the image below:
1. Creating a patch
First thing is first – let’s make some super sweet patches to serve up for your game or application.
Unzip the package you downloaded to a convenient folder on the machine where you wish to deploy the server. You’ll find a folder structure that looks like the image above. Guess the directory containing the Patch Generator and open it.
There are two files that you care about in here:
- WispPatchGen.exe – this is the command line utility that creates patches. Run it without any parameters and it will give you a helpful message telling you how to structure your parameters to create a patch. This is useful if you feel like you need to create the patch as part of an automated process, but is otherwise a bit cumbersome. We recommend the patch generator GUI instead.
- PatchGenGUI.exe - graphical user interface to the patch generator utility. Just run it and fill in the blanks, as per the instructions below to generate your patch. It’s quite painless, normally.
The basic principle behind creating patches is that you have two directories – the “from” directory containing the exact files and structure of the installation/version that you’re moving FROM and a second, “to” directory that contains the exact files and structure that you’re moving TO. You can structure this any way you like, but for illustration’s sake, let’s say I have 4 versions that I’ve released so far… I might choose to set up my directories for patch generation as follows:
Notice that \PatchGen\0\ is a completely empty directory. This allows me to create an initial patch which contains the entirety of Version 1 of my release. This way, all I have to distribute to the user is the Patch Client (which is a small and quick download) and when the user connects for the first time, the entire application gets patched down. Alternatively, you could have the user download and install the initial version as part of the install package. The choice is yours. For now, however, we’re going to assume that Version 1 (the initial version) will be distributed via the patcher.
So, to recap – Directory “0″ is empty. All the other numbered directories each contain the entire application directory for those versions.
Next, we’re going to point the patch generator at two of our directories and the generator will then determine the differences between the two (added files, removed files, changed files) and will package the differences into a singular “.patch” file which we will then put up on our patch server for distribution.
Run PatchGenGUI.exe. It should look like this:
We’re going to create our initial patch, which goes from version “0″, i.e. nothing installed, to version 1.
The fields in the GUI are self explanatory. Note that “patch notes” are sent to the client whenever they download this particular patch.
Pick a location where you want the patch to be saved to and hit “Generate Patch”. This should fire up the PatchGen utility command window and your patch will be built.
Maximum compression is used during patch generation, so it could take a while, depending on the size of your installation.
You just made your first patch. And it didn’t even hurt.
Don’t close the GUI yet, we still need some information from this window for the next step.
2. Setting up the Server
Next, let’s set up the server. The server executable is in the… wait for it… “Server” directory of the download. Inside the Server directory you’ll find 4 items of note:
- PatchServer.exe – the server executable
- PathServer.exe.config – the server config file
- Console – shortcut to a command prompt with Administrator privileges
- Patches – your patch files go in this directory
Let’s configure your server. Open up PatchServer.exe.config in the XML/text editor of your choice. Visual Studio is nice, because it has support for collapsing some sections of the file so you don’t have to look at them when not needed. There is a lot of stuff in this config file that’s related to the Wisp core technology. It needs to be in the config file, but you don’t need to (and shouldn’t) remove/alter these settings. The settings you’re interested in are exclusively in the section titled <appSettings>.
Most of the settings are self explanatory.
<!--These two settings are only relevant if patch server is plugged into a WISP hive. Largely irrelevant for standalone patch servers.-->
<add key="ServerUserID" value="Patchy" />
<add key="ServerName" value="Patch Server" />
<!--The port on which the patch server listens. Make sure to open your firewall to open this port.-->
<add key="ListenOnPort" value="4534" />
<!--Number of seconds before an unresponsive client gets booted from the server-->
<add key="PlayerConnectionTimeout" value="60" />
<!--Maximum simultaneous client connections allowed on server. This affects how much memory the server reserves for networking.-->
<add key="ConnectionLimit" value="100" />
<!--Maximum clients that can be accepted simultaneously. Clients are only in the "being accepted" state for a fraction of a second. Leave this number reasonably low.-->
<add key="MaxSimultaneousNetworkAcceptOps" value="10" />
<!--Network send/receive buffer size. This affects how much memory the server reserves for networking.-->
<add key="NetworkBufferSize" value="2048" />
<!--Required for function in standalone mode-->
<add key="SupressStatLoad" value="TRUE"/>
<!--Required for function in standalone mode-->
<add key="SupressCharacterLoad" value="TRUE"/>
<!--The patch server does not require a client to login with an account. Leave this setting as FALSE for the patch server.-->
<add key="RequireAuth" value="FALSE"/>
<!--The patch server does not connect to any databases.-->
<add key="DatabaseConnectivity" value="FALSE"/>
<!--Should the patch client send information about the client machine's GPU. Captured in server logs in 'UserMetrics' channel-->
<add key="ReportClientGPU" value="FALSE"/>
<!--Should the patch client send information about the client machine's CPU. Captured in server logs in 'UserMetrics' channel-->
<add key="ReportClientCPU" value="TRUE"/>
<!--Should the patch client send information about the client machine's Disk drives. Captured in server logs in 'UserMetrics' channel-->
<add key="ReportClientDrives" value="FALSE"/>
<!--Should the patch client send information about the client machine's Motherboard. Captured in server logs in 'UserMetrics' channel-->
<add key="ReportClientMainBoard" value="FALSE"/>
<!--Should the patch client send information about the client machine's Operating Systm. Captured in server logs in 'UserMetrics' channel-->
<add key="ReportClientOS" value="FALSE"/>
<!--Should the patch client send information about the client machine's physical RAM. Captured in server logs in 'UserMetrics' channel-->
<add key="ReportClientRAM" value="TRUE"/>
Most important here is the ListenOnPort. Choose a port, make sure it’s open on your firewall (patcher uses TCP only). Make note of this port for later – we’ll have to point the patch client at this port.
You will also note that there several “ReportClientXXX” settings. The patch server can collect hardware specs from the patch client so that you can get a better picture of the hardware capabilities of your user base. Hardware specs are recorded in the server logs. You will need to parse these out of the logs if you are interested in them. If you’re not interested in collecting these, just set them all to false.
Find the sub-directory called ”Patches”. Inside you’ll find two files of note:
- Versions.txt – tells the server which patch files go with which version
- PatchNotes.txt – these are the master patch notes that every client sees as the first thing when they connect to the patch server. Use it for announcements and whatnot.
There’s only thing missing from this directory and that’s the .patch file you made in the last step. Find and copy that file into this directory. Remember the very bottom bit of the Patch Gen GUI that looked something like this after you hit “Generate Patch”?
That line is patch server speak for “version 1.00 is contained in patch file patch_0.00_1.00.patch”. Copy that line from the GUI and paste it into the Versions.txt file of your \Server\Patches\ directory.
Great. So far, we’ve generated a patch, copied it to server’s Patches directory and made an entry for that patch in the Versions.txt file. Our patch server now has something to serve… let’s fire it up.
Server Installation & Running
All WISP servers are intended to run as Windows services. In a pinch, the server can also be run in “standalone” mode, but there is no UI for this mode, so you will have to stop the server using the Windows Task Manager (CTRL-ALT-DEL). Standalone mode is really only intended for quick tests here and there.
To install the Patch Server as a windows service, follow these steps:
- Make sure your Windows account has admin privleges, otherwise you won’t be able to install the service.
- Execute “Console”. This opens an administrator privileged command prompt.
- Change directory (“CD DirectoryToPatchServer.exe”) to where the PatchServer.exe lives on your hard drive
- Execute “PatchServer.exe /i”. This will attempt to install the server as a service and run it. Results of this will appear in the log files.
- To uninstall the server later, simply run ”PatchServer.exe /u”
- To run the server in standalone mode, run “PatchServer.exe standalone”
Your server should now be running and listening for patch client connections on the specified ListenOnPort. Check the log file for confirmation.
Note: the server logs will always report the patches that server knows about on startup. You will notice that the patch server always reports ONE patch more than you actually have in the Patches directory. That is because internally, the patch server keeps a “zero” patch, which is used to correctly version new clients.
3. The Patch Client
This is the only part you distribute to your users. In the download, we give you both the binary for an example patch client as well as the source so you can modify it and build your own.
The most excellent art used in the prototype patch client was created by and used with permission from Game Artist Thomas King.
[Screenshot of the example patch client]
The user facing side of the patch client is entirely self working. As soon as the patch client is started, it attempts to connect to the patch server and will incrementally download and apply all patches that the server has until the client is current. Once the client is at the current version, the “Continue/Launch” button becomes available to the user, which will launch your application/game and close the patch client.
So, the way to set this up, is to point your application’s main shortcut at the patch client, not at your application’s executable. This way, when the user launches your app via the installed shortcut, they are actually launching the patcher and the patcher then launches your app once it has verified that the application is current.
Patch Client Setup
Setup for the patch client is easy. There are two files of note in the patch client directory:
- WispPatchClient.exe.config – this is the config file. Open this file and set these three properties:
<add key="PatchServerAddress" value="localhost"/>
<add key="PatchServerPort" value="4534"/>
<add key="LaunchOnCurrent" value="YourAppsExecutable.exe"/>
- PatchServerAddress – this is the IP address or domain name where you are running the patch server. If you’re just running it locally for testing, “localhost” will work.
- PatchServerPort – this corresponds to the ListenOnPort that you set for the patch server.
- LaunchOnCurrent – this is the executable that the patch server should launch once it is up to do date and the user presses the “Continue/Launch” button.
- ver.txt – This file will not exist until AFTER a patch has been completed. It contains the client’s current version number, as indicated by the last applied patch.
Corrupt Patch Recovery
Normally, patching is a smooth process, but external factors can sometimes corrupt the patching process. A user could have manually manipulated the files, the power goes out during patching, etc, etc. Some of these errors can be automatically recovered from by simply re-launching the patch client.
If, however, the patch is corrupted beyond recovery, have the user delete the ver.txt file and relaunch the patch client. This will restart the patch chain and should recover the client.
Customizing the Patch Client
The patch client source is extensively documented throughout the code. Here are the basics:
- Launch PatchClient.csproj in Visual Studio (2010+). Admin privileges are required.
- We chose WPF for this project, you might choose a different interface library if you wish.
- The class that does all of the work is PatchClient.Patcher. The methods & events you care about are all static. The Patcher object more or less automates the following order of events:
- Connect to patch server
- Client sends current version
- Server either responds with “version is current” message or with the next patch file in the patch chain to bring the client current.
- Client either launches the patched app or downloads the patch.
- Once patch is downloaded, client disconnects and decompresses the patch
- Once patch is unpacked, client applies the patch (adds, deletes, alters files/directories)
- Client reconnects to patch server and sequence restarts and repeats until client is current
- You will want to hook into the following Patcher events (most of these are informational, only one is actionable):
- Patcher.PatchInfoAdded – notifies you to display a progress/info message to the user
- Patcher.PatchDownloadProgress - as a patch file is downloaded this event periodically fires so you can update a progress bar with the download progress.
- Patcher.PatchApplyProgress – fire periodically as the patch is applied.
- Patcher.PatchUnzipProgress – fires periodically as the patch is decompressed.
- Patcher.PatchArrived – fires when a patch has completed downloading.
- Patcher.ClientIsCurrent – fires when the server tells the client that they are on the current version. The client should allow the user to launch the patched application when this event fires.
- Patcher.PatchNotesArrived – fires when the patch notes are sent from the patch server.
- The only method you need to call to kick off the self contained patch loop is
Calling that method will start the process and everything else is taken care of by the PatchClient.Patcher class. In the example client, this method is called as soon as the application is started, thus eliminating the need for user interaction to kick off the patch process.
- For examples of how you might respond to the various events, see MainWindow.xaml.cs in the PatchClient project.