HTTPS/HTTP Updater
Ren'Py includes an updater that can automatically download and install updates to a Ren'Py game from a web host. The updates work on desktop platforms, with the exception of macOS apps.
The Ren'Py updater shows an updater screen during this process, prompting the user to proceed and allowing the user to cancel when appropriate.
There are two update formats supported. The modern format is called rpu, and was introduced in Ren'Py 8.2. An older format called zsync is obsolete, but can be generated to update from older versions.
Server Requirements
The updater requires that you provide your own hosting. You should be able to download the update files by going to the appropriate URL directly, and your server must support HTTP range queries.
Building an Update
Updates are built automatically when distributions are built. To build
an update, set build.include_update
to True in options.rpy. This will
unlock the "Build Updates" option in the "Build Distributions" section
of the launcher. Check this option, and Ren'Py will create the update
files.
The update files consist of:
- updates.json
An index of available updates and their versions.
- updates.ecdsa
A signature of updates.json, used to verify that it has not been tampered with.
- rpu/
The rpu directory contains the metadata and data used by the updates.
You should upload these to the same place on your webserver.
Functions
To cause an update to occur, invoke either updater.update or the updater.Update action.
- updater.Update(*args, **kwargs)
An action that calls
updater.update()
. All arguments are stored and passed to that function.
- updater.UpdateVersion(url, check_interval=21600, simulate=None, **kwargs)
This function contacts the server at url, and determines if there is a newer version of software available at that url. If there is, this function returns the new version. Otherwise, it returns None.
Since contacting the server can take some time, this function launches a thread in the background, and immediately returns the version from the last time the server was contacted, or None if the server has never been contacted. The background thread will restart the current interaction once the server has been contacted, which will cause screens that call this function to update.
Each url will be contacted at most once per Ren'Py session, and not more than once every check_interval seconds. When the server is not contacted, cached data will be returned.
Additional keyword arguments (including simulate) are passed to the update mechanism as if they were given to
updater.update()
.
- updater.can_update(base=None)
Returns true if it's possible that an update can succeed. Returns false if updating is totally impossible. (For example, if the update directory was deleted.)
Note that this does not determine if an update is actually available. To do that, use
updater.UpdateVersion()
.
- updater.get_installed_packages(base=None)
Returns a list of installed DLC package names.
- base
The base directory to update. Defaults to the current project's base directory.
- updater.update(url, base=None, force=False, public_key=None, simulate=None, add=[], restart=True, confirm=True, patch=True, prefer_rpu=True, allow_empty=False, done_pause=True, allow_cancel=True, screen='updater')
Updates this Ren'Py game to the latest version.
- url
The URL to the updates.json file.
- base
The base directory that will be updated. Defaults to the base of the current game. (This can usually be ignored.)
- force
Force the update to occur even if the version numbers are the same. (Used for testing.)
- public_key
The path to a PEM file containing a public key that the update signature is checked against. (This can usually be ignored.)
- simulate
This is used to test update guis without actually performing an update. This can be:
None to perform an update.
"available" to test the case where an update is available.
"not_available" to test the case where no update is available.
"error" to test an update error.
- add
A list of packages to add during this update. This is only necessary for dlc.
- restart
If true, the game will be re-run when the update completes. If "utter",
renpy.utter_restart()
will be called instead. If False, the update will simply end.- confirm
Should Ren'Py prompt the user to confirm the update? If False, the update will proceed without confirmation.
- patch
If true, Ren'Py will attempt to patch the game, downloading only changed data. If false, Ren'Py will download a complete copy of the game, and update from that. This is set to false automatically when the url does not begin with "http:".
This is ignored if the RPU update format is being used.
- prefer_rpu
If True, Ren'Py will prefer the RPU format for updates, if both zsync and RPU are available.
- allow_empty
If True, Ren'Py will allow the update to proceed even if the base directory does not contain update information. (add must be provided in this case.)
- done_pause
If true, the game will pause after the update is complete. If false, it will immediately proceed (either to a restart, or a return).
- allow_cancel
If true, the user will be allowed to cancel the update. If false, the user will not be allowed to cancel the update.
- screen
The name of the screen to use.
Screen
To customize the look of the updater, you may override the updater
screen. Here's an example screen:
screen updater(u=None):
add "#000"
frame:
style_group ""
has side "t c b":
spacing gui._scale(10)
label _("Updater")
fixed:
vbox:
if u.state == u.ERROR:
text _("An error has occured:")
elif u.state == u.CHECKING:
text _("Checking for updates.")
elif u.state == u.UPDATE_NOT_AVAILABLE:
text _("This program is up to date.")
elif u.state == u.UPDATE_AVAILABLE:
text _("[u.version] is available. Do you want to install it?")
elif u.state == u.PREPARING:
text _("Preparing to download the updates.")
elif u.state == u.DOWNLOADING:
text _("Downloading the updates.")
elif u.state == u.UNPACKING:
text _("Unpacking the updates.")
elif u.state == u.FINISHING:
text _("Finishing up.")
elif u.state == u.DONE:
text _("The updates have been installed. The program will restart.")
elif u.state == u.DONE_NO_RESTART:
text _("The updates have been installed.")
elif u.state == u.CANCELLED:
text _("The updates were cancelled.")
if u.message is not None:
null height gui._scale(10)
text "[u.message!q]"
if u.progress is not None:
null height gui._scale(10)
bar value (u.progress or 0.0) range 1.0 style "_bar"
hbox:
spacing gui._scale(25)
if u.can_proceed:
textbutton _("Proceed") action u.proceed
if u.can_cancel:
textbutton _("Cancel") action u.cancel
The updater screen is supplied a single parameter, an Updater object, which must be named u. The Updater object has the following fields on it, which can be used to customize the screen:
- class updater.Updater
- state
The current state of the updater. See the example above for possible values and their meanings. The values are all constants on the Updater object.
- message
If not None, a message to display to the user.
- progress
If not None, the progress of the current operation, as a float between 0.0 and 1.0.
- can_proceed
If True, the screen is being asked to display a button that will allow the user to proceed with the update.
- proceed
If can_proceed is True, this is the action that should be invoked when the user presses the proceed button.
- can_cancel
If True, the screen is being asked to display a button that will allow the user to cancel the update.
- cancel
If can_cancel is True, this is the action that should be invoked when the user presses the cancel button.
- old_disk_total
If not None, an integer giving the total number of bytes on the disk the game consumed at the start of the update.
- new_disk_total
If not None, an integer giving the total number of bytes on the disk the game will consume at the end of the update.
- download_total
If not None, an integer giving the total number of bytes that will be downloaded during the update.
- download_done
If not None, an integer giving the number of bytes that have been downloaded during the update, so far.
- write_total
If not None, an integer giving the total number of bytes that will be written to disk during the update.
- write_done
If not None, an integer giving the number of bytes that have been written to disk during the update, so far.