This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Основной процесс монтирования использует liveupdate.add_mount(), liveupdate.remove_mount() и liveupdate.get_mounts(). Полный список доступных функций см. в справочнике API liveupdate.
Если коду необходимо определить, ожидает ли манифест сборки исключённый контент Live Update, используйте liveupdate.is_built_with_excluded_files():
if liveupdate.is_built_with_excluded_files() then
print("The bundle expects excluded Live Update content")
end
Функция сообщает только о метаданных манифеста сборки. Она не означает, что какой-либо архив сейчас смонтирован или что конкретный ресурс доступен. Для просмотра активных mount’ов используйте liveupdate.get_mounts(), а для просмотра записанных в манифесте хешей ресурсов Collection Proxy — collectionproxy.get_resources().
Рекомендуемый процесс — скачать и смонтировать целый Zip-архив с URI zip:.
liveupdate.get_mounts() возвращает mount’ы, активные в текущей сессии. Каждая запись содержит строку uri, числовой priority и хеш name. Список также содержит базовые mount’ы движка, приоритет которых меньше нуля и которые невозможно удалить.
Движок не восстанавливает mount’ы после перезапуска. Если приложению нужен ранее скачанный контент в следующей сессии, оно должно сохранить URI, имя и приоритет пакета в собственных данных сохранения и снова вызвать liveupdate.add_mount() при запуске.
Поскольку mount.name является хешем, используйте его как ключ таблицы или сравнивайте с hash("name"); не добавляйте его к строке пути. Сопоставьте каждому хешу имени уникальный путь к метаданным:
local function remove_old_mounts()
local mounts = liveupdate.get_mounts() -- таблица с mount'ами
local version_resources = {
[hash("liveupdate")] = "/version_liveupdate.json",
}
-- У каждого mount'а есть: mount.uri, mount.priority, mount.name
for _,mount in ipairs(mounts) do
-- Имя файла должно быть уникальным, чтобы мы не получили файл из другого архива
-- Эти данные разработчик создает как способ задать метаданные для архива
local version_resource = version_resources[mount.name]
local version_data = version_resource and sys.load_resource(version_resource)
if version_data then
version_data = json.decode(version_data)
elseif mount.priority >= 0 then
version_data = {version = 0} -- если файла версии нет, скорее всего архив старый или недействительный
end
-- Проверяем версию архива относительно версии, поддерживаемой игрой
if version_data and version_data.version < sys.get_config_int("game.minimum_lu_version") then
-- Архив недействителен, поэтому размонтируем его
liveupdate.remove_mount(mount.name)
end
end
end
Collection proxy, исключенный из бандла, работает как обычный collection proxy, но с одним важным отличием. Если отправить ему сообщение load, пока часть его ресурсов недоступна в хранилище бандла, загрузка завершится ошибкой.
В архивном сценарии вы обычно заранее определяете, какой архив или набор архивов нужен proxy, и монтируете их перед загрузкой. Чтобы просмотреть записанные в манифесте хеши ресурсов известного исключённого proxy, используйте collectionproxy.get_resources().
После монтирования пакета исключённый и незагруженный прокси также можно перенаправить на другую скомпилированную коллекцию с помощью collectionproxy.set_collection(). Ограничения и порядок загрузки описаны в разделе Изменение коллекции исключённого прокси.
При сборке архива с публикацией контента Live Update основной манифест в бандле не содержит исключённых записей Live Update, а манифест опубликованного пакета сохраняет их. collectionproxy.get_resources() читает метаданные зависимостей из манифеста, но не проверяет доступность каждого указанного блока данных:
collectionproxy.get_resources("#proxy") возвращает пустую таблицу {};{
"a1b2c3...",
"d4e5f6...",
"7890ab...",
...
}
Следующий пример кода предполагает, что ресурсы доступны по URL, указанному в настройке game.http_url.
-- Нужно отслеживать, какой архив содержит какой контент
-- В этом примере используется только один архив liveupdate, содержащий все отсутствующие ресурсы.
-- Если вы используете несколько архивов, нужно соответствующим образом организовать загрузки
local lu_infos = {
liveupdate = {
name = "liveupdate",
priority = 10,
}
}
local function get_lu_info_for_level(level_name)
if level_name == "level1" then
return lu_infos['liveupdate']
end
end
local function mount_zip(self, name, priority, path, callback)
liveupdate.add_mount(name, "zip:" .. path, priority, function(_self, _name, _uri, _result) -- <1>
callback(_name, _uri, _result)
end)
end
local function has_mount(name)
local name_hash = hash(name)
for _, mount in ipairs(liveupdate.get_mounts()) do
if mount.name == name_hash then
return true
end
end
return false
end
function init(self)
self.http_url = sys.get_config_string("game.http_url", nil) -- <2>
local level_name = "level1"
local info = get_lu_info_for_level(level_name) -- <3>
msg.post("#", "load_level", {level = "level1", info = info }) -- <4>
end
function on_message(self, message_id, message, sender)
if message_id == hash("load_level") then
local proxy_resources = collectionproxy.get_resources("#" .. message.level) -- <5>
-- Сборка, публикующая контент Live Update, исключает соответствующие записи
-- из манифеста бандла, поэтому таблица пуста до монтирования манифеста
-- нужного пакета. После монтирования она содержит хеши ресурсов proxy.
if message.info and #proxy_resources == 0 and not has_mount(message.info.name) then
msg.post("#", "download_archive", message) -- <6>
else
msg.post("#" .. message.level, "load")
end
elseif message_id == hash("download_archive") then
local zip_filename = message.info.name .. ".zip"
local download_path = sys.get_save_file("mygame", zip_filename)
local url = self.http_url .. "/" .. zip_filename
-- Если архив уже существует, пробуем смонтировать его!
if sys.exists(download_path) then
mount_zip(self, message.info.name, message.info.priority, download_path, function(name, uri, result) -- <8>
if result == liveupdate.LIVEUPDATE_OK then
msg.post("#", "load_level", message) -- пробуем загрузить уровень снова
else
os.remove(download_path) -- удаляем и пробуем
msg.post("#", "load_level", message) -- скачать снова
end
end)
else
-- Выполняем запрос. При необходимости можно использовать учётные данные
http.request(url, "GET", function(self, id, response) -- <7>
if response.status == 200 or response.status == 304 then
mount_zip(self, message.info.name, message.info.priority, download_path, function(name, uri, result) -- <8>
if result == liveupdate.LIVEUPDATE_OK then
msg.post("#", "load_level", message) -- пробуем загрузить уровень снова
else
print("Не удалось смонтировать архив", download_path, ":", result)
end
end)
else
print("Не удалось скачать архив", download_path, "из", url, ":", response.status)
end
end, nil, nil, {path=download_path})
end
elseif message_id == hash("proxy_loaded") then -- уровень загружен, и теперь его можно включить
msg.post(sender, "init")
msg.post(sender, "enable")
end
end
liveupdate.add_mount() монтирует один архив, используя заданные имя, приоритет и zip-файл. После этого данные сразу доступны для загрузки, перезапускать движок не нужно. Mount активен только в текущей сессии. Сохраните путь к скачанному пакету и требуемые настройки mount в собственных данных сохранения и после каждого перезапуска снова вызывайте liveupdate.add_mount().collectionproxy.get_resources() проверяем метаданные исключённого контента proxy. Функция возвращает {} до монтирования манифеста нужного пакета, а после монтирования — непустую таблицу хешей ресурсов. Эти хеши описывают зависимости; результат сам по себе не подтверждает доступность каждого блока данных.download_path.После того как код загрузки готов, можно протестировать приложение. Однако при запуске из редактора ничего скачиваться не будет. Это происходит потому, что Live Update работает только в собранном бандле. При запуске в среде редактора ресурсы никогда не исключаются. Чтобы убедиться, что все работает корректно, нужно создать бандл.