Version: alpha
FUNCTIONS | |
---|---|
liveupdate.add_mount() | Add resource mount |
liveupdate.get_current_manifest() | return a reference to the Manifest that is currently loaded |
liveupdate.get_mounts() | Get current mounts |
liveupdate.is_using_liveupdate_data() | is any liveupdate data mounted and currently in use |
liveupdate.remove_mount() | Remove resource mount |
liveupdate.store_archive() | register and store a live update zip file |
liveupdate.store_manifest() | create, verify, and store a manifest to device |
liveupdate.store_resource() | add a resource to the data archive and runtime index |
CONSTANTS | |
---|---|
liveupdate.LIVEUPDATE_BUNDLED_RESOURCE_MISMATCH | LIVEUPDATE_BUNDLED_RESOURCE_MISMATCH |
liveupdate.LIVEUPDATE_ENGINE_VERSION_MISMATCH | LIVEUPDATE_ENGINE_VERSION_MISMATCH |
liveupdate.LIVEUPDATE_FORMAT_ERROR | LIVEUPDATE_FORMAT_ERROR |
liveupdate.LIVEUPDATE_INVAL | LIVEUPDATE_INVAL |
liveupdate.LIVEUPDATE_INVALID_HEADER | LIVEUPDATE_INVALID_HEADER |
liveupdate.LIVEUPDATE_INVALID_RESOURCE | LIVEUPDATE_INVALID_RESOURCE |
liveupdate.LIVEUPDATE_IO_ERROR | LIVEUPDATE_IO_ERROR |
liveupdate.LIVEUPDATE_MEM_ERROR | LIVEUPDATE_MEM_ERROR |
liveupdate.LIVEUPDATE_OK | LIVEUPDATE_OK |
liveupdate.LIVEUPDATE_SCHEME_MISMATCH | LIVEUPDATE_SCHEME_MISMATCH |
liveupdate.LIVEUPDATE_SIGNATURE_MISMATCH | LIVEUPDATE_SIGNATURE_MISMATCH |
liveupdate.LIVEUPDATE_UNKNOWN | LIVEUPDATE_UNKNOWN |
liveupdate.LIVEUPDATE_VERSION_MISMATCH | LIVEUPDATE_VERSION_MISMATCH |
liveupdate.add_mount(name,uri,priority,callback)
Adds a resource mount to the resource system. The mounts are persisted between sessions. After the mount succeeded, the resources are available to load. (i.e. no reboot required)
PARAMETERS
name |
string |
Unique name of the mount |
uri |
string |
The uri of the mount, including the scheme. Currently supported schemes are 'zip' and 'archive'. |
priority |
integer |
Priority of mount. Larger priority takes prescedence |
callback |
function |
Callback after the asynchronous request completed |
RETURNS
result |
number | The result of the request |
EXAMPLES
Add multiple mounts. Higher priority takes precedence.liveupdate.add_mount("common", "zip:/path/to/common_stuff.zip", 10) -- base pack
liveupdate.add_mount("levelpack_1", "zip:/path/to/levels_1_to_20.zip", 20) -- level pack
liveupdate.add_mount("season_pack_1", "zip:/path/to/easter_pack_1.zip", 30) -- season pack, overriding content in the other packs
liveupdate.get_current_manifest()
Return a reference to the Manifest that is currently loaded.
PARAMETERS
None
RETURNS
manifest_reference |
number | reference to the Manifest that is currently loaded |
liveupdate.get_mounts()
Get an array of the current mounts This can be used to determine if a new mount is needed or not
PARAMETERS
None
RETURNS
mounts |
array | Array of mounts |
EXAMPLES
Output the current resource mountspprint("MOUNTS", liveupdate.get_mounts())
DEBUG:SCRIPT: MOUNTS,
{ --[[0x119667bf0]]
1 = { --[[0x119667c50]]
name = "liveupdate",
uri = "zip:/device/path/to/acchives/liveupdate.zip",
priority = 5
},
2 = { --[[0x119667d50]]
name = "_base",
uri = "archive:build/default/game.dmanifest",
priority = -10
}
}
liveupdate.is_using_liveupdate_data()
Is any liveupdate data mounted and currently in use? This can be used to determine if a new manifest or zip file should be downloaded.
PARAMETERS
None
RETURNS
bool |
bool | true if a liveupdate archive (any format) has been loaded |
liveupdate.remove_mount(name)
Remove a mount the resource system. The remaining mounts are persisted between sessions. Removing a mount does not affect any loaded resources.
PARAMETERS
name |
string |
Unique name of the mount |
RETURNS
result |
number | The result of the call |
EXAMPLES
Add multiple mounts. Higher priority takes precedence.liveupdate.remove_mount("season_pack_1")
liveupdate.store_archive(path,callback,[options])
Stores a zip file and uses it for live update content. The contents of the zip file will be verified against the manifest to ensure file integrity. It is possible to opt out of the resource verification using an option passed to this function. The path is stored in the (internal) live update location.
PARAMETERS
path |
string |
the path to the original file on disc |
callback |
function(self, status) |
the callback function
executed after the storage has completed
|
[options] |
table |
optional table with extra parameters. Supported entries:
|
EXAMPLES
How to download an archive with HTTP and store it on device.local LIVEUPDATE_URL = <a file server url>
-- This can be anything, but you should keep the platform bundles apart
local ZIP_FILENAME = 'defold.resourcepack.zip'
local APP_SAVE_DIR = "LiveUpdateDemo"
function init(self)
self.proxy = "levels#level1"
print("INIT: is_using_liveupdate_data:", liveupdate.is_using_liveupdate_data())
-- let's download the archive
msg.post("#", "attempt_download_archive")
end
-- helper function to store headers from the http request (e.g. the ETag)
local function store_http_response_headers(name, data)
local path = sys.get_save_file(APP_SAVE_DIR, name)
sys.save(path, data)
end
local function load_http_response_headers(name)
local path = sys.get_save_file(APP_SAVE_DIR, name)
return sys.load(path)
end
-- returns headers that can potentially generate a 304
-- without redownloading the file again
local function get_http_request_headers(name)
local data = load_http_response_headers(name)
local headers = {}
for k, v in pairs(data) do
if string.lower(k) == 'etag' then
headers['If-None-Match'] = v
elseif string.lower(k) == 'last-modified' then
headers['If-Modified-Since'] = v
end
end
return headers
end
local function store_archive_cb(self, path, status)
if status == true then
print("Successfully stored live update archive!", path)
sys.reboot()
else
print("Failed to store live update archive, ", path)
-- remove the path
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("attempt_download_archive") then
-- by supplying the ETag, we don't have to redownload the file again
-- if we already have downloaded it.
local headers = get_http_request_headers(ZIP_FILENAME .. '.json')
if not liveupdate.is_using_liveupdate_data() then
headers = {} -- live update data has been purged, and we need do a fresh download
end
local path = sys.get_save_file(APP_SAVE_DIR, ZIP_FILENAME)
local options = {
path = path, -- a temporary file on disc. will be removed upon successful liveupdate storage
ignore_cache = true -- we don't want to store a (potentially large) duplicate in our http cache
}
local url = LIVEUPDATE_URL .. ZIP_FILENAME
print("Downloading", url)
http.request(url, "GET", function(self, id, response)
if response.status == 304 then
print(string.format("%d: Archive zip file up-to-date", response.status))
elseif response.status == 200 and response.error == nil then
-- register the path to the live update system
liveupdate.store_archive(response.path, store_archive_cb)
-- at this point, the "path" has been moved internally to a different location
-- save the ETag for the next run
store_http_response_headers(ZIP_FILENAME .. '.json', response.headers)
else
print("Error when downloading", url, "to", path, ":", response.status, response.error)
end
-- If we got a 200, we would call store_archive_cb() then reboot
-- Second time, if we get here, it should be after a 304, and then
-- we can load the missing resources from the liveupdate archive
if liveupdate.is_using_liveupdate_data() then
msg.post(self.proxy, "load")
end
end,
headers, nil, options)
liveupdate.store_manifest(manifest_buffer,callback)
Create a new manifest from a buffer. The created manifest is verified by ensuring that the manifest was signed using the bundled public/private key-pair during the bundle process and that the manifest supports the current running engine version. Once the manifest is verified it is stored on device. The next time the engine starts (or is rebooted) it will look for the stored manifest before loading resources. Storing a new manifest allows the developer to update the game, modify existing resources, or add new resources to the game through LiveUpdate.
PARAMETERS
manifest_buffer |
string |
the binary data that represents the manifest |
callback |
function(self, status) |
the callback function
executed once the engine has attempted to store the manifest.
|
EXAMPLES
How to download a manifest with HTTP and store it on device.local function store_manifest_cb(self, status)
if status == liveupdate.LIVEUPDATE_OK then
pprint("Successfully stored manifest. This manifest will be loaded instead of the bundled manifest the next time the engine starts.")
else
pprint("Failed to store manifest")
end
end
local function download_and_store_manifest(self)
http.request(MANIFEST_URL, "GET", function(self, id, response)
if response.status == 200 then
liveupdate.store_manifest(response.response, store_manifest_cb)
end
end)
end
liveupdate.store_resource(manifest_reference,data,hexdigest,callback)
add a resource to the data archive and runtime index. The resource will be verified internally before being added to the data archive.
PARAMETERS
manifest_reference |
number |
The manifest to check against. |
data |
string |
The resource data that should be stored. |
hexdigest |
string |
The expected hash for the resource, retrieved through collectionproxy.missing_resources. |
callback |
function(self, hexdigest, status) |
The callback
function that is executed once the engine has been attempted to store
the resource.
|
EXAMPLES
function init(self)
self.manifest = liveupdate.get_current_manifest()
end
local function callback_store_resource(self, hexdigest, status)
if status == true then
print("Successfully stored resource: " .. hexdigest)
else
print("Failed to store resource: " .. hexdigest)
end
end
local function load_resources(self, target)
local resources = collectionproxy.missing_resources(target)
for _, resource_hash in ipairs(resources) do
local baseurl = "http://example.defold.com:8000/"
http.request(baseurl .. resource_hash, "GET", function(self, id, response)
if response.status == 200 then
liveupdate.store_resource(self.manifest, response.response, resource_hash, callback_store_resource)
else
print("Failed to download resource: " .. resource_hash)
end
end)
end
end
Mismatch between between expected bundled resources and actual bundled resources. The manifest expects a resource to be in the bundle, but it was not found in the bundle. This is typically the case when a non-excluded resource was modified between publishing the bundle and publishing the manifest.
Mismatch between running engine version and engine versions supported by manifest.
Failed to parse manifest data buffer. The manifest was probably produced by a different engine version.
Argument was invalid
The handled resource is invalid.
The header of the resource is invalid.
I/O operation failed
Memory wasn't allocated
LIVEUPDATE_OK
Mismatch between scheme used to load resources. Resources are loaded with a different scheme than from manifest, for example over HTTP or directly from file. This is typically the case when running the game directly from the editor instead of from a bundle.
Mismatch between manifest expected signature and actual signature.
Unspecified error
Mismatch between manifest expected version and actual version.