no message
This commit is contained in:
@@ -10,6 +10,11 @@
|
||||
var streamingBase = '';
|
||||
var bundleManifest = null;
|
||||
var levelsManifest = null;
|
||||
var levelsManifestPromise = null;
|
||||
var assetsCoreLoaded = false;
|
||||
var assetsCorePromise = null;
|
||||
var loadedLevelDbShards = new Set();
|
||||
var levelDbShardPromises = new Map();
|
||||
var levelPackPromises = new Map();
|
||||
var loadedLevelIds = new Set();
|
||||
var levelPrefabsBundlePromise = null;
|
||||
@@ -54,9 +59,8 @@
|
||||
return;
|
||||
}
|
||||
var existing = am.getBundle('level-prefabs');
|
||||
if (existing) {
|
||||
if (onComplete) onComplete(null, existing);
|
||||
return existing;
|
||||
if (existing && typeof am.removeBundle === 'function') {
|
||||
try { am.removeBundle(existing); } catch (e) { /* ignore */ }
|
||||
}
|
||||
if (levelPrefabsBundlePromise) {
|
||||
levelPrefabsBundlePromise.then(function (bundle) {
|
||||
@@ -131,6 +135,40 @@
|
||||
}
|
||||
}
|
||||
|
||||
/** Cocos bundle 常请求 import/NN/uuid.json,zip 内路径带 assets/.../import/ 前缀(NN 为 uuid 前 2 位 hex) */
|
||||
var IMPORT_SHARD = '[0-9a-fA-F]{2}';
|
||||
function resolveImportFileKey(pathname) {
|
||||
if (!pathname) return null;
|
||||
var p = String(pathname).replace(/\\/g, '/').replace(/^\/+/, '');
|
||||
var shardRe = new RegExp('^unity/assets/(level-prefabs|resources|main|internal)/(' + IMPORT_SHARD + ')/(.+)$', 'i');
|
||||
p = p.replace(shardRe, function (_, bundle, dir, file) {
|
||||
return 'assets/' + bundle + '/import/' + dir + '/' + file;
|
||||
});
|
||||
if (files.has(p)) return p;
|
||||
var bundleImport = new RegExp('^assets/(level-prefabs|resources|main|internal)/(' + IMPORT_SHARD + ')/([^/]+)$', 'i').exec(p);
|
||||
if (bundleImport) {
|
||||
var withImport = 'assets/' + bundleImport[1] + '/import/' + bundleImport[2] + '/' + bundleImport[3];
|
||||
if (files.has(withImport)) return withImport;
|
||||
}
|
||||
var short = new RegExp('^(' + IMPORT_SHARD + ')/(.+)$', 'i').exec(p);
|
||||
if (short) {
|
||||
var bases = [
|
||||
'assets/level-prefabs/import/',
|
||||
'assets/resources/import/',
|
||||
'assets/main/import/',
|
||||
'assets/internal/import/',
|
||||
'assets/resources/native/',
|
||||
'assets/main/native/',
|
||||
'assets/internal/native/',
|
||||
];
|
||||
for (var i = 0; i < bases.length; i++) {
|
||||
var key = bases[i] + short[1] + '/' + short[2];
|
||||
if (files.has(key)) return key;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function lookupFile(pathname) {
|
||||
var keys = [pathname, pathname.replace(/^\.?\//, '')];
|
||||
var parts = pathname.split('/');
|
||||
@@ -141,6 +179,8 @@
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var k = keys[i];
|
||||
if (files.has(k)) return files.get(k);
|
||||
var importKey = resolveImportFileKey(k);
|
||||
if (importKey && files.has(importKey)) return files.get(importKey);
|
||||
var idx = k.indexOf('StreamingAssets/aa/WebGL/');
|
||||
if (idx >= 0 && files.has(k.slice(idx + 'StreamingAssets/aa/WebGL/'.length))) {
|
||||
return files.get(k.slice(idx + 'StreamingAssets/aa/WebGL/'.length));
|
||||
@@ -151,6 +191,8 @@
|
||||
}
|
||||
if (k.indexOf('assets/') === 0 && files.has(k)) return files.get(k);
|
||||
}
|
||||
var fallbackKey = resolveImportFileKey(pathname);
|
||||
if (fallbackKey && files.has(fallbackKey)) return files.get(fallbackKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -221,10 +263,20 @@
|
||||
var u = new URL(String(raw), global.location.href);
|
||||
var p = u.pathname;
|
||||
if (files.size > 0) {
|
||||
var importKey = resolveImportFileKey(p) || resolveImportFileKey(p.replace(/^\/+/, ''));
|
||||
if (importKey) {
|
||||
var importVirt = virtualUrlForBundleFile(importKey);
|
||||
if (importVirt) return importVirt;
|
||||
}
|
||||
var rel = relPathFromUrlPath(p);
|
||||
if (rel) {
|
||||
var virt = virtualUrlForBundleFile(rel);
|
||||
if (virt) return virt;
|
||||
importKey = resolveImportFileKey(rel);
|
||||
if (importKey) {
|
||||
importVirt = virtualUrlForBundleFile(importKey);
|
||||
if (importVirt) return importVirt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p.indexOf(getRootPathname()) === 0) return u.href;
|
||||
@@ -366,6 +418,12 @@
|
||||
proto.__tfrhLevelPrefabScript = true;
|
||||
}
|
||||
|
||||
function needsAssetsCore(pathname) {
|
||||
var p = String(pathname || '');
|
||||
if (needsLevelPrefabs(p)) return false;
|
||||
return p.indexOf('assets/') >= 0 || p.indexOf('/assets/') >= 0;
|
||||
}
|
||||
|
||||
function installFetchShim() {
|
||||
global.fetch = function (input, init) {
|
||||
input = rewriteEmbeddedUrl(input);
|
||||
@@ -378,6 +436,19 @@
|
||||
headers: { 'Content-Type': mimeForPath(p) },
|
||||
}));
|
||||
}
|
||||
if (needsAssetsCore(p)) {
|
||||
return ensureAssetsCoreLoaded().then(function () {
|
||||
var hit2 = lookupFile(p);
|
||||
if (hit2) {
|
||||
var body2 = /\.(m?js|json)$/i.test(p) ? bytesToText(hit2) : hit2;
|
||||
return new Response(body2, {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': mimeForPath(p) },
|
||||
});
|
||||
}
|
||||
return origFetch(input, init);
|
||||
});
|
||||
}
|
||||
if (needsLevelPrefabs(p)) {
|
||||
return ensureLevelPackForPath(p).then(function () {
|
||||
var hit2 = lookupFile(p);
|
||||
@@ -407,6 +478,18 @@
|
||||
var origSend = xhr.send;
|
||||
xhr.send = function () {
|
||||
var hit = lookupFile(toPath(reqUrl));
|
||||
if (!hit && needsAssetsCore(reqUrl)) {
|
||||
ensureAssetsCoreLoaded().then(function () {
|
||||
hit = lookupFile(toPath(reqUrl));
|
||||
if (!hit) return origSend.apply(xhr, arguments);
|
||||
var isText = /\.(m?js|json|txt|xml|atlas|tmx|tsx|vsh|fsh|fnt|plist)$/i.test(toPath(reqUrl))
|
||||
|| xhr.responseType === 'json'
|
||||
|| xhr.responseType === 'text'
|
||||
|| !xhr.responseType;
|
||||
deliverXhrHit(xhr, isText ? bytesToText(hit) : null, isText ? null : hit);
|
||||
}).catch(function () { origSend.apply(xhr, arguments); });
|
||||
return;
|
||||
}
|
||||
if (!hit && needsLevelPrefabs(reqUrl)) {
|
||||
ensureLevelPackForPath(reqUrl).then(function () {
|
||||
hit = lookupFile(toPath(reqUrl));
|
||||
@@ -510,32 +593,36 @@
|
||||
if (onProgress) pending.then(function () { onProgress(1); }).catch(function () {});
|
||||
return pending;
|
||||
}
|
||||
if (!levelsManifest || !levelsManifest.levels || !levelsManifest.levels[levelId]) {
|
||||
return Promise.reject(new Error('关卡包未在 manifest 中: Level' + levelId));
|
||||
}
|
||||
if (!streamingBase) return Promise.reject(new Error('streamingBase 未初始化'));
|
||||
var entry = levelsManifest.levels[levelId];
|
||||
var url = joinUrl(streamingBase, 'aa/WebGL/' + entry.bundle);
|
||||
dispatchLevelsBundleProgress(0);
|
||||
var promise = fetchBinaryWithProgress(
|
||||
url,
|
||||
function (frac) {
|
||||
dispatchLevelsBundleProgress(frac);
|
||||
if (onProgress) onProgress(frac);
|
||||
},
|
||||
0,
|
||||
1,
|
||||
).then(function (buf) {
|
||||
mergeZipIntoFiles(unzip(buf));
|
||||
var ok = (entry.files || []).every(function (rel) { return files.has(rel); });
|
||||
if (!ok) {
|
||||
throw new Error('关卡包解压不完整: Level' + levelId);
|
||||
}
|
||||
loadedLevelIds.add(levelId);
|
||||
return invalidateLevelPrefabsBundle();
|
||||
var promise = ensureAssetsCoreLoaded().then(function () {
|
||||
return ensureLevelsManifestLoaded();
|
||||
}).then(function () {
|
||||
dispatchLevelsBundleProgress(1);
|
||||
if (onProgress) onProgress(1);
|
||||
if (!levelsManifest || !levelsManifest.levels || !levelsManifest.levels[levelId]) {
|
||||
return Promise.reject(new Error('关卡包未在 manifest 中: Level' + levelId));
|
||||
}
|
||||
if (!streamingBase) return Promise.reject(new Error('streamingBase 未初始化'));
|
||||
var entry = levelsManifest.levels[levelId];
|
||||
var url = joinUrl(streamingBase, 'aa/WebGL/' + entry.bundle);
|
||||
dispatchLevelsBundleProgress(0);
|
||||
return fetchBinaryWithProgress(
|
||||
url,
|
||||
function (frac) {
|
||||
dispatchLevelsBundleProgress(frac);
|
||||
if (onProgress) onProgress(frac);
|
||||
},
|
||||
0,
|
||||
1,
|
||||
).then(function (buf) {
|
||||
mergeZipIntoFiles(unzip(buf));
|
||||
var ok = (entry.files || []).every(function (rel) { return files.has(rel); });
|
||||
if (!ok) {
|
||||
throw new Error('关卡包解压不完整: Level' + levelId);
|
||||
}
|
||||
loadedLevelIds.add(levelId);
|
||||
return invalidateLevelPrefabsBundle();
|
||||
}).then(function () {
|
||||
dispatchLevelsBundleProgress(1);
|
||||
if (onProgress) onProgress(1);
|
||||
});
|
||||
}).catch(function (e) {
|
||||
levelPackPromises.delete(levelId);
|
||||
throw e;
|
||||
@@ -721,6 +808,7 @@
|
||||
var raw = String(path || '').trim();
|
||||
var m = /Level(\d+)/.exec(raw);
|
||||
var lid = m ? parseInt(m[1], 10) : NaN;
|
||||
var loadPath = raw.indexOf('level-prefabs/') === 0 ? raw : ('level-prefabs/' + raw.replace(/^level-prefabs\//, ''));
|
||||
var prep = (typeof global.__tfrhEnsureLevelPack === 'function' && !Number.isNaN(lid))
|
||||
? global.__tfrhEnsureLevelPack(lid)
|
||||
: Promise.resolve();
|
||||
@@ -728,17 +816,35 @@
|
||||
return prep.then(function () {
|
||||
return invalidateLevelPrefabsBundle();
|
||||
}).then(function () {
|
||||
return ensureLevelsManifestLoaded();
|
||||
}).then(function (manifest) {
|
||||
var entry = manifest && manifest.levels && manifest.levels[String(lid)];
|
||||
var uuid = entry && entry.uuid;
|
||||
return new Promise(function (resolve, reject) {
|
||||
cc.assetManager.loadBundle('level-prefabs', function (err, bundle) {
|
||||
if (err || !bundle) {
|
||||
reject(err || new Error('level-prefabs bundle unavailable'));
|
||||
return;
|
||||
}
|
||||
bundle.load(raw, Prefab, function (e, asset) {
|
||||
if (e || !asset) reject(e || new Error('missing prefab: ' + raw));
|
||||
else resolve(asset);
|
||||
function finish(err, asset) {
|
||||
if (!err && asset) resolve(asset);
|
||||
else reject(err || new Error('missing prefab: ' + loadPath));
|
||||
}
|
||||
function tryBundleLoad() {
|
||||
cc.assetManager.loadBundle('level-prefabs', function (err, bundle) {
|
||||
if (err || !bundle) {
|
||||
reject(err || new Error('level-prefabs bundle unavailable'));
|
||||
return;
|
||||
}
|
||||
bundle.load(loadPath, Prefab, finish);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (uuid) {
|
||||
cc.assetManager.loadAny({ uuid: uuid, type: Prefab }, function (err, asset) {
|
||||
if (!err && asset) {
|
||||
resolve(asset);
|
||||
return;
|
||||
}
|
||||
tryBundleLoad();
|
||||
});
|
||||
return;
|
||||
}
|
||||
tryBundleLoad();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1060,26 +1166,83 @@
|
||||
return out;
|
||||
}
|
||||
|
||||
function isZipBytes(bytes) {
|
||||
return bytes && bytes.length >= 2 && bytes[0] === 0x50 && bytes[1] === 0x4b;
|
||||
}
|
||||
|
||||
function isJsonText(text) {
|
||||
if (!text) return false;
|
||||
var c = text.charCodeAt(0);
|
||||
return c === 0x7b || c === 0x5b;
|
||||
}
|
||||
|
||||
function decodeBrotliToBytes(ab) {
|
||||
if (typeof DecompressionStream !== 'undefined') {
|
||||
return new Response(ab).pipeThrough(new DecompressionStream('brotli'))
|
||||
.arrayBuffer()
|
||||
.then(function (buf) { return new Uint8Array(buf); });
|
||||
}
|
||||
return Promise.reject(new Error('浏览器不支持 Brotli 解压'));
|
||||
}
|
||||
|
||||
/** OSS 若对 .br 文件再设 Content-Encoding:br,fetch 已解压成 zip/json,勿二次 Brotli */
|
||||
function normalizeBinaryPayload(bytes, expectBrotli) {
|
||||
if (!expectBrotli || isZipBytes(bytes)) {
|
||||
return Promise.resolve(bytes);
|
||||
}
|
||||
var slice = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
||||
return decodeBrotliToBytes(slice).catch(function () {
|
||||
if (isZipBytes(bytes)) return bytes;
|
||||
return Promise.reject(new Error('Brotli 解压失败'));
|
||||
});
|
||||
}
|
||||
|
||||
function fetchBinary(url, onProgress) {
|
||||
return origFetch(url).then(function (res) {
|
||||
if (!res.ok) throw new Error('HTTP ' + res.status + ' for ' + url);
|
||||
if (onProgress) onProgress(0.3);
|
||||
return res.arrayBuffer();
|
||||
}).then(function (ab) {
|
||||
if (onProgress) onProgress(0.6);
|
||||
return new Uint8Array(ab);
|
||||
return fetchBinaryWithProgress(url, onProgress, 0, 1);
|
||||
}
|
||||
|
||||
function decodeBrotliToText(ab) {
|
||||
if (typeof DecompressionStream !== 'undefined') {
|
||||
return new Response(ab).pipeThrough(new DecompressionStream('brotli'))
|
||||
.arrayBuffer()
|
||||
.then(function (buf) { return new TextDecoder().decode(buf); });
|
||||
}
|
||||
return Promise.reject(new Error('浏览器不支持 Brotli 解压'));
|
||||
}
|
||||
|
||||
function normalizeJsonPayload(ab, expectBrotli) {
|
||||
var text = new TextDecoder().decode(ab);
|
||||
if (!expectBrotli || isJsonText(text)) return Promise.resolve(text);
|
||||
return decodeBrotliToText(ab).catch(function () {
|
||||
text = new TextDecoder().decode(ab);
|
||||
if (isJsonText(text)) return text;
|
||||
return Promise.reject(new Error('Brotli JSON 解压失败'));
|
||||
});
|
||||
}
|
||||
|
||||
function fetchBinaryWithProgress(url, onProgress, weightStart, weightEnd) {
|
||||
weightStart = weightStart == null ? 0 : weightStart;
|
||||
weightEnd = weightEnd == null ? 1 : weightEnd;
|
||||
return origFetch(url).then(function (res) {
|
||||
var brUrl = String(url).replace(/\.bundle(\?.*)?$/i, '.bundle.br$1');
|
||||
if (!/\.br(\?|$)/i.test(brUrl) && brUrl.indexOf('.bundle') >= 0) {
|
||||
/* brUrl already set */
|
||||
} else if (/\.json(\?|$)/i.test(url)) {
|
||||
brUrl = url.replace(/\.json(\?.*)?$/i, '.json.br$1');
|
||||
} else if (!/\.br(\?|$)/i.test(url)) {
|
||||
brUrl = url + '.br';
|
||||
} else {
|
||||
brUrl = url;
|
||||
}
|
||||
|
||||
function readResponse(res, isBrotli) {
|
||||
if (!res.ok) throw new Error('HTTP ' + res.status + ' for ' + url);
|
||||
if (!res.body || !res.body.getReader) {
|
||||
return res.arrayBuffer().then(function (ab) {
|
||||
if (onProgress) onProgress(weightEnd);
|
||||
return new Uint8Array(ab);
|
||||
var bytes = new Uint8Array(ab);
|
||||
return normalizeBinaryPayload(bytes, isBrotli).then(function (out) {
|
||||
if (onProgress) onProgress(weightEnd);
|
||||
return out;
|
||||
});
|
||||
});
|
||||
}
|
||||
var reader = res.body.getReader();
|
||||
@@ -1089,13 +1252,19 @@
|
||||
function pump() {
|
||||
return reader.read().then(function (result) {
|
||||
if (result.done) {
|
||||
if (onProgress) onProgress(weightEnd);
|
||||
var out = new Uint8Array(received);
|
||||
var off = 0;
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
out.set(chunks[i], off);
|
||||
off += chunks[i].length;
|
||||
}
|
||||
if (isBrotli) {
|
||||
return normalizeBinaryPayload(out, true).then(function (decoded) {
|
||||
if (onProgress) onProgress(weightEnd);
|
||||
return decoded;
|
||||
});
|
||||
}
|
||||
if (onProgress) onProgress(weightEnd);
|
||||
return out;
|
||||
}
|
||||
chunks.push(result.value);
|
||||
@@ -1108,11 +1277,45 @@
|
||||
});
|
||||
}
|
||||
return pump();
|
||||
}
|
||||
|
||||
return origFetch(brUrl).then(function (res) {
|
||||
if (res.ok) return readResponse(res, true);
|
||||
return origFetch(url).then(function (plain) { return readResponse(plain, false); });
|
||||
}).catch(function () {
|
||||
return origFetch(url).then(function (plain) { return readResponse(plain, false); });
|
||||
});
|
||||
}
|
||||
|
||||
function ensureAssetsCoreLoaded(onProgress) {
|
||||
if (assetsCoreLoaded) return Promise.resolve();
|
||||
if (assetsCorePromise) return assetsCorePromise;
|
||||
if (!bundleManifest || !bundleManifest.assetsUrl) {
|
||||
return Promise.reject(new Error('assets_all manifest 未就绪'));
|
||||
}
|
||||
assetsCorePromise = fetchBinaryWithProgress(
|
||||
bundleManifest.assetsUrl,
|
||||
onProgress || function () {},
|
||||
0,
|
||||
1,
|
||||
).then(function (buf) {
|
||||
mergeZipIntoFiles(unzip(buf));
|
||||
patchSettingsScriptPackages();
|
||||
assetsCoreLoaded = true;
|
||||
}).catch(function (e) {
|
||||
assetsCorePromise = null;
|
||||
throw e;
|
||||
});
|
||||
return assetsCorePromise;
|
||||
}
|
||||
|
||||
global.__tfrhEnsureAssetsCore = function (onProgress) {
|
||||
return ensureAssetsCoreLoaded(onProgress);
|
||||
};
|
||||
|
||||
function loadStartupBundles(manifest, onProgress) {
|
||||
onProgress(0.05);
|
||||
/* internal/main 等引擎启动即需,assets_all 须与 scenes 并行首屏加载 */
|
||||
var scenesP = fetchBinaryWithProgress(manifest.scenesUrl, onProgress, 0.05, 0.42);
|
||||
var assetsP = fetchBinaryWithProgress(manifest.assetsUrl, onProgress, 0.42, 0.58);
|
||||
return Promise.all([scenesP, assetsP]).then(function (bufs) {
|
||||
@@ -1120,6 +1323,7 @@
|
||||
assertCocosRuntimeLoaded();
|
||||
mergeZipIntoFiles(unzip(bufs[1]));
|
||||
patchSettingsScriptPackages();
|
||||
assetsCoreLoaded = true;
|
||||
onProgress(0.6);
|
||||
});
|
||||
}
|
||||
@@ -1190,6 +1394,58 @@
|
||||
});
|
||||
}
|
||||
|
||||
function ensureLevelsManifestLoaded() {
|
||||
if (levelsManifest) return Promise.resolve(levelsManifest);
|
||||
if (levelsManifestPromise) return levelsManifestPromise;
|
||||
if (!streamingBase) return Promise.reject(new Error('streamingBase 未初始化'));
|
||||
levelsManifestPromise = loadLevelsManifest(streamingBase).then(function (lm) {
|
||||
levelsManifest = lm;
|
||||
return lm;
|
||||
});
|
||||
return levelsManifestPromise;
|
||||
}
|
||||
|
||||
function findLevelDbShard(index, levelId) {
|
||||
if (!index || !index.shards) return null;
|
||||
var id = Number(levelId);
|
||||
for (var i = 0; i < index.shards.length; i++) {
|
||||
var s = index.shards[i];
|
||||
if (id >= s.min && id <= s.max) return s;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function ensureLevelDbShardLoaded(levelId) {
|
||||
var index = global.__tfrhLevelsDbIndex;
|
||||
if (!index || index.mode !== 'sharded') return Promise.resolve();
|
||||
var shard = findLevelDbShard(index, levelId);
|
||||
if (!shard) return Promise.resolve();
|
||||
var key = shard.file;
|
||||
if (loadedLevelDbShards.has(key)) return Promise.resolve();
|
||||
if (levelDbShardPromises.has(key)) return levelDbShardPromises.get(key);
|
||||
if (!streamingBase) return Promise.reject(new Error('streamingBase 未初始化'));
|
||||
var url = joinUrl(streamingBase, 'aa/' + key.replace(/^\/+/, ''));
|
||||
var promise = fetchLevelsDatabaseJson(url).then(function (json) {
|
||||
loadedLevelDbShards.add(key);
|
||||
if (!global.__tfrhLevelsDatabaseJson) {
|
||||
global.__tfrhLevelsDatabaseJson = { version: index.version || 2, levels: {} };
|
||||
}
|
||||
var merged = global.__tfrhLevelsDatabaseJson.levels || {};
|
||||
var incoming = (json && json.levels) || {};
|
||||
Object.keys(incoming).forEach(function (k) { merged[k] = incoming[k]; });
|
||||
global.__tfrhLevelsDatabaseJson.levels = merged;
|
||||
}).catch(function (e) {
|
||||
levelDbShardPromises.delete(key);
|
||||
throw e;
|
||||
});
|
||||
levelDbShardPromises.set(key, promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
global.__tfrhEnsureLevelDbShard = function (levelId) {
|
||||
return ensureLevelDbShardLoaded(levelId);
|
||||
};
|
||||
|
||||
function loadBundleManifest(config) {
|
||||
var base = resolveStreamingBase(config);
|
||||
var catalogUrl = joinUrl(base, 'aa/catalog.json');
|
||||
@@ -1198,16 +1454,13 @@
|
||||
return res.json();
|
||||
}).then(function (catalog) {
|
||||
var bundles = parseCatalogBundles(catalog);
|
||||
return loadLevelsManifest(base).then(function (lm) {
|
||||
levelsManifest = lm;
|
||||
var manifest = {
|
||||
scenesUrl: joinUrl(base, 'aa/WebGL/' + bundles.scenes),
|
||||
assetsUrl: joinUrl(base, 'aa/WebGL/' + bundles.assets),
|
||||
bundleNames: bundles,
|
||||
};
|
||||
bundleManifest = manifest;
|
||||
return manifest;
|
||||
});
|
||||
var manifest = {
|
||||
scenesUrl: joinUrl(base, 'aa/WebGL/' + bundles.scenes),
|
||||
assetsUrl: joinUrl(base, 'aa/WebGL/' + bundles.assets),
|
||||
bundleNames: bundles,
|
||||
};
|
||||
bundleManifest = manifest;
|
||||
return manifest;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1268,36 +1521,33 @@
|
||||
packageRoot = getPackageRoot();
|
||||
installEmbeddedPathFix();
|
||||
|
||||
function resolveLevelsDatabaseUrl(config) {
|
||||
if (global.__tfrhLevelsDatabaseUrl) return global.__tfrhLevelsDatabaseUrl;
|
||||
function resolveLevelsDbBase(config) {
|
||||
var sa = config && config.streamingAssetsUrl;
|
||||
if (sa && /^https?:\/\//i.test(sa)) {
|
||||
var cdnRoot = String(sa).replace(/\/StreamingAssets\/?$/i, '');
|
||||
return joinUrl(cdnRoot, 'levels-database.json');
|
||||
return String(sa).replace(/\/StreamingAssets\/?$/i, '');
|
||||
}
|
||||
return joinUrl(packageRoot || getPackageRoot(), 'levels-database.json');
|
||||
return packageRoot || getPackageRoot();
|
||||
}
|
||||
|
||||
function decodeBrotliToText(ab) {
|
||||
if (typeof DecompressionStream !== 'undefined') {
|
||||
return new Response(ab).pipeThrough(new DecompressionStream('brotli'))
|
||||
.arrayBuffer()
|
||||
.then(function (buf) { return new TextDecoder().decode(buf); });
|
||||
}
|
||||
return Promise.reject(new Error('浏览器不支持 Brotli 解压'));
|
||||
function resolveLevelsDatabaseUrl(config) {
|
||||
if (global.__tfrhLevelsDatabaseUrl) return global.__tfrhLevelsDatabaseUrl;
|
||||
return joinUrl(resolveLevelsDbBase(config), 'levels-database.json');
|
||||
}
|
||||
|
||||
function resolveLevelsDbIndexUrl(config) {
|
||||
if (global.__tfrhLevelsDbIndexUrl) return global.__tfrhLevelsDbIndexUrl;
|
||||
return joinUrl(resolveLevelsDbBase(config), 'levels-db-index.json');
|
||||
}
|
||||
|
||||
function fetchLevelsDatabaseJson(url) {
|
||||
var brUrl = url.replace(/\.json(\?.*)?$/i, '.json.br$1');
|
||||
return origFetch(brUrl).then(function (res) {
|
||||
if (!res.ok) throw new Error('HTTP ' + res.status);
|
||||
var enc = (res.headers.get('content-encoding') || '').toLowerCase();
|
||||
if (enc === 'br' || /\.br(\?|$)/i.test(brUrl)) {
|
||||
return res.arrayBuffer().then(decodeBrotliToText).then(function (text) {
|
||||
return res.arrayBuffer().then(function (ab) {
|
||||
return normalizeJsonPayload(ab, true).then(function (text) {
|
||||
return JSON.parse(text);
|
||||
});
|
||||
}
|
||||
return res.json();
|
||||
});
|
||||
}).catch(function () {
|
||||
return origFetch(url).then(function (res) {
|
||||
if (!res.ok) throw new Error('HTTP ' + res.status);
|
||||
@@ -1306,14 +1556,20 @@
|
||||
});
|
||||
}
|
||||
|
||||
function prefetchMainSiteLevelDb(config) {
|
||||
var url = resolveLevelsDatabaseUrl(config);
|
||||
global.__tfrhLevelsDatabaseUrl = url;
|
||||
if (!url || global.__tfrhLevelsDatabaseJson) return Promise.resolve();
|
||||
return fetchLevelsDatabaseJson(url).then(function (json) {
|
||||
global.__tfrhLevelsDatabaseJson = json;
|
||||
function prefetchLevelDbIndex(config) {
|
||||
var indexUrl = resolveLevelsDbIndexUrl(config);
|
||||
var legacyUrl = resolveLevelsDatabaseUrl(config);
|
||||
global.__tfrhLevelsDbIndexUrl = indexUrl;
|
||||
global.__tfrhLevelsDatabaseUrl = legacyUrl;
|
||||
if (global.__tfrhLevelsDbIndex) return Promise.resolve();
|
||||
return fetchLevelsDatabaseJson(indexUrl).then(function (json) {
|
||||
if (json && json.mode === 'sharded') {
|
||||
global.__tfrhLevelsDbIndex = json;
|
||||
return;
|
||||
}
|
||||
throw new Error('非分片索引');
|
||||
}).catch(function (e) {
|
||||
console.warn('[mstest5] 关卡库预取失败', url, e);
|
||||
console.warn('[mstest5] 关卡库索引预取失败,启动时将由 LevelDatabase 回退', indexUrl, e);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1339,7 +1595,7 @@
|
||||
onProgress = onProgress || function () {};
|
||||
onProgress(0.02);
|
||||
resolveStreamingBase(config);
|
||||
return prefetchMainSiteLevelDb(config).then(function () {
|
||||
return prefetchLevelDbIndex(config).then(function () {
|
||||
return shouldUseBundlePackFlow(config);
|
||||
}).then(function (useBundles) {
|
||||
if (!useBundles) {
|
||||
|
||||
Reference in New Issue
Block a user