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
マウント(mount)の基本的なワークフローでは、liveupdate.add_mount()、liveupdate.remove_mount()、liveupdate.get_mounts() を使います。利用できるすべての関数については、liveupdate API リファレンスを参照してください。
バンドル(bundle)のビルドマニフェストが、除外された 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
この関数が返すのは、ビルドマニフェストのメタデータに関する情報だけです。現在アーカイブがマウントされていることや、特定のリソース(resource)が利用できることを意味するものではありません。有効なマウントを調べるには liveupdate.get_mounts() を使い、コレクションプロキシ(collection proxy)に対してマニフェストに記録されたリソースのハッシュ値を調べるには collectionproxy.get_resources() を使います。
推奨するワークフローは、完全な Zip アーカイブをダウンロードし、zip: URI を使ってマウントする方法です。
liveupdate.get_mounts() は、現在のセッションで有効なマウントを返します。各エントリーには、文字列の uri、数値の priority、ハッシュ値の name があります。このリストには、優先度がゼロ未満で削除できない、エンジンの基本マウントも含まれます。
再起動後に、エンジンがマウントを復元することはありません。アプリケーションが後のセッションでダウンロード済みのコンテンツを必要とする場合は、パッケージの URI、名前、優先度を独自のセーブデータに永続化し、起動時に liveupdate.add_mount() を再度呼び出す必要があります。
複数のパッケージをマウントする場合は、それぞれのパッケージにある、アプリケーションで定義したメタデータを検証すると便利です。mount.name はハッシュ値なので、テーブルのキーとして使うか、hash("mount-name") と比較してください。リソースパスに連結しないでください。次の例では、各名前のハッシュ値を、一意のメタデータリソースパスに対応付けています。
local function remove_old_mounts()
local mounts = liveupdate.get_mounts() -- table with mounts
local version_resources = {
[hash("level-pack")] = "/version_level_pack.json",
[hash("season-pack")] = "/version_season_pack.json",
}
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} -- if it has no version file, it's likely an old/invalid archive
end
-- Ignore the engine's base mounts, which have negative priorities.
if version_data and version_data.version < sys.get_config_int("game.minimum_lu_version") then
liveupdate.remove_mount(mount.name)
end
end
end
パッケージごとに異なるメタデータパスを使ってください。リソースの検索はマウントの優先度に従うため、複数のパッケージで同じパスを使うと、最も優先度の高いマウントにあるデータが読み込まれます。
バンドル作成から除外したコレクションプロキシは、通常のコレクションプロキシと同じように動作しますが、重要な違いが1つあります。バンドルのストレージで利用できないリソースがまだある状態で load メッセージを送信すると、読み込みに失敗します。
アーカイブを使うワークフローでは、通常、プロキシに必要な1つまたは複数のアーカイブをあらかじめ決め、読み込みの前にマウントします。対象の除外済みプロキシについて、マニフェストに記録されたリソースのハッシュ値を調べるには、collectionproxy.get_resources() を使います。
パッケージをマウントした後は、除外されていて未読み込みのプロキシの参照先を、collectionproxy.set_collection() で別のコンパイル済みコレクション(collection)に変更することもできます。制約と読み込み順序については、除外したプロキシのコレクションを変更するを参照してください。
Live Update コンテンツを公開するアーカイブビルドでは、バンドルに同梱されるメインマニフェストからは除外された Live Update のエントリーが省かれ、公開されるパッケージのマニフェストにはそれらが保持されます。collectionproxy.get_resources() はマニフェストの依存関係メタデータを読み取ります。参照先のすべてのデータブロブが利用できるかどうかを検証するものではありません。
collectionproxy.get_resources("#proxy") は空のテーブル {} を返します。{
"a1b2c3...",
"d4e5f6...",
"7890ab...",
...
}
次のコード例では、設定 game.http_url で指定された URL からリソースを利用できることを前提としています。
-- You'll need to track which archive contains which content
-- In this example, we only use a single liveupdate archive, containing all missing resource.
-- If you are using multiple archive, you need to structure the downloads accordingly
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>
-- A build that publishes Live Update content omits excluded entries from the
-- bundled manifest, so this table is empty until the relevant package manifest
-- is mounted. After mounting, it contains the resource hashes for the 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
-- Check if the archive already exists. If it does, try to mount it!
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) -- try to load the level again
else
os.remove(download_path) -- remove and try to
msg.post("#", "load_level", message) -- download again
end
end)
else
-- Make the request. You can use credentials
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) -- try to load the level again
else
print("Failed to mount archive", download_path, ":", result)
end
end)
else
print("Failed to download archive", download_path, "from", url, ":", response.status)
end
end, nil, nil, {path=download_path})
end
elseif message_id == hash("proxy_loaded") then -- the level is loaded, and we can enable it
msg.post(sender, "init")
msg.post(sender, "enable")
end
end
liveupdate.add_mount() は、指定した名前、優先度、zip ファイルを使って1つのアーカイブをマウントします。これにより、データはすぐに読み込み可能になります(エンジンを再起動する必要はありません)。マウントは現在のセッションでのみ有効です。ダウンロードしたパッケージのパスと必要なマウント設定を独自のセーブデータに永続化し、再起動するたびに liveupdate.add_mount() を再度呼び出してください。collectionproxy.get_resources() を使って、プロキシの除外されたコンテンツのメタデータを調べます。該当するパッケージマニフェストがマウントされるまでは {} を返し、マウント後はリソースのハッシュ値を含む、空ではないテーブルを返します。これらのハッシュ値は依存関係を表しており、この結果自体がすべてのデータブロブの利用可否を検証するものではありません。download_path にダウンロードします。読み込みコードを用意できたので、アプリケーションをテストできます。ただし、エディターから実行しても何もダウンロードされません。これは、Live Update がバンドルの機能だからです。エディター環境で実行する場合は、リソースが除外されることはありません。すべてが正常に動作することを確認するには、バンドルを作成する必要があります。