'use strict'; // Check one shared version; Creator caches each requested file by its versioned URL. const config = require('./cloud-rise-package-config'); const names = ['matching', 'stage1', 'stage2', 'stage3', 'art']; const cacheKey = 'cloud_rise_bundle_version_v2'; const downloader = cc.assetManager.downloader, original = downloader._downloaders.bundle; let versionTask = null, selectedVersion = ''; const isVersion = value => typeof value === 'string' && value.length <= 32 && /^\d+\.\d+\.\d+$/.test(value); const warn = (message, error) => console.warn('[cloud-rise-package] ' + message, error && (error.message || error.errMsg) || ''); function readCacheState() { try { return JSON.parse(cc.sys.localStorage.getItem(cacheKey)) || {}; } catch (_) { return {}; } } function remember(version) { try { cc.sys.localStorage.setItem(cacheKey, JSON.stringify({ version, baseUrl: config.baseUrl })); } catch (error) { warn('Cannot persist selected version', error); } } function selectVersion() { if (versionTask) return versionTask; if (!/^https:\/\/[^\s?#]+\/$/.test(config.baseUrl)) { return Promise.reject(new Error('Invalid Cloud Rise resource address')); } const previous = readCacheState(); const fallback = previous.baseUrl === config.baseUrl && isVersion(previous.version) ? previous.version : ''; versionTask = new Promise((resolve, reject) => { let finished = false, request; const finish = (error, version) => { if (finished) return; finished = true; clearTimeout(timer); if (error && !fallback) { reject(error); return; } if (error) warn('Version check failed; using cached version ' + fallback, error); // Same version reuses the same cache keys; a changed version cannot hit old entries. selectedVersion = version || fallback; resolve(selectedVersion); }; const timer = setTimeout(() => { finish(new Error('Version check timed out')); if (request && request.abort) request.abort(); }, 5000); try { request = wx.request({ url: config.baseUrl + 'version.json?_t=' + Date.now(), timeout: 5000, header: { 'Cache-Control': 'no-cache' }, success: response => { try { if (response.statusCode !== 200) throw new Error('Version HTTP ' + response.statusCode); const data = typeof response.data === 'string' ? JSON.parse(response.data) : response.data; if (!data || !isVersion(data.version)) throw new Error('Invalid Cloud Rise version'); finish(null, data.version); } catch (error) { finish(error); } }, fail: error => finish(error) }); } catch (error) { finish(error); } }).catch(error => { versionTask = null; throw error; }); return versionTask; } window.__prepareCloudRiseVersion = selectVersion; function resourceUrl(url) { const owned = names.some(name => url.startsWith(config.baseUrl + name + '/')); if (!selectedVersion || !owned) return url; return url + (url.includes('?') ? '&' : '?') + 'v=' + selectedVersion; } // Include packed import JSON as well as images/native files, without changing other games' URLs. Object.keys(downloader._downloaders).filter(type => type !== 'bundle').forEach(type => { const handler = downloader._downloaders[type]; downloader.register(type, (url, options, done) => { const versioned = resourceUrl(url); handler(versioned, versioned === url ? options : Object.assign({}, options, { cacheEnabled: true }), done); }); }); downloader.register('bundle', function (nameOrUrl, options, onComplete) { // Only redirect the five named bundles. Explicit URLs and other gameplay keep the engine loader. if (!names.includes(nameOrUrl)) return original(nameOrUrl, options, onComplete); selectVersion().then(version => { const base = config.baseUrl + nameOrUrl + '/', url = base + 'config.json'; __cocos_require__('src/scripts/' + nameOrUrl + '/index.js'); const cache = cc.assetManager.cacheManager; cache.makeBundleFolder(nameOrUrl); downloader._downloaders['.json'](url, Object.assign({}, options, { __cacheBundleRoot__: nameOrUrl, cacheEnabled: true }), (error, data) => { if (!error && (!data || data.name !== nameOrUrl || data.isZip || data.cloudRiseVersion !== version)) { error = new Error('Cloud Rise bundle version mismatch: ' + nameOrUrl); const key = resourceUrl(url); delete cache.cacheQueue[key]; cache.tempFiles.remove(key); cache.removeCache(key); } if (!error) { data.base = base; remember(version); } onComplete(error, data); }); }).catch(error => onComplete(error)); });