Files
TankIC/tools/hornet_prefetch.js

128 lines
4.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ===== 车库资源预热模块 =====
// 目的:从战局返回车库时,车库界面要一次性加载大量贴图/图标/坦克模型,
// 首次全部现场拉取会明显卡顿。这里在**战局空闲时**后台把这些资源拉进浏览器缓存。
//
// 预热两批:
// ① /play/<static/...> —— 车库/大厅 UI 图片(由 resources.json 资源表枚举,本地直出)
// ② /resources/<...> —— res.3dtank.com 上最近访问过的模型/贴图
// 清单由本地 serve.js 的 /__prefetch_list__ 提供(按缓存文件 mtime 倒序)
//
// 策略:
// - 只在捕获到 __gameMode__(已在战局)后 8 秒才开始,避开进入战局的加载高峰
// - 串行 + 间隔限速,避免抢占战局带宽
// - 10 分钟内只跑一次(localStorage 记录),可用 __hornetPrefetch__.stop() 手动停止
// - localStorage.hornetPrefetch = '0' 可永久关闭
(function () {
var KEY_AT = 'hornetPrefetchAt';
var KEY_OFF = 'hornetPrefetch';
var GAP_STATIC = 40; // UI 图片间隔(ms)
var GAP_RES = 30; // 模型/贴图间隔(ms)
var State = { running: false, stopped: false, timers: [] };
function LastRunAt() {
try { return Number(localStorage.getItem(KEY_AT) || 0) || 0; } catch (e) { return 0; }
}
function MarkRun() {
try { localStorage.setItem(KEY_AT, String(Date.now())); } catch (e) {}
}
// 串行限速加载;命中缓存的资源不会产生网络请求
function LoadList(List, Gap, Done) {
var Index = 0, Ok = 0;
function Next() {
if (State.stopped) return;
if (Index >= List.length) {
if (Ok > 0) console.log('[预热] 完成 ' + Ok + '/' + List.length + ' 项');
if (Done) Done();
return;
}
var Url = List[Index++];
fetch(Url, { cache: 'force-cache' })
.then(function () { Ok++; })
.catch(function () {})
.then(function () { setTimeout(Next, Gap); });
}
Next();
}
// ① 车库/大厅 UI 图片:从 webpack 资源表枚举
function PreloadStatic() {
fetch('/play/static/js/unpacked/resources.json', { cache: 'force-cache' })
.then(function (R) { return R.json(); })
.then(function (Json) {
var Map = (Json && Json.resourceMap) || {};
var Seen = {};
var List = [];
for (var K in Map) {
if (!Object.prototype.hasOwnProperty.call(Map, K)) continue;
var V = Map[K];
if (typeof V !== 'string' || Seen[V]) continue;
Seen[V] = 1;
List.push('/play/' + V);
}
console.log('[预热] 车库 UI 资源 ' + List.length + ' 项');
LoadList(List, GAP_STATIC, PreloadRes);
})
.catch(function () { PreloadRes(); });
}
// ② res.3dtank.com 资源:按本地缓存清单(最近访问优先)
function PreloadRes() {
fetch('/__prefetch_list__?n=600')
.then(function (R) { return R.json(); })
.then(function (Json) {
var List = (Json && Json.list) || [];
if (!List.length) return;
console.log('[预热] 战局/车库资源 ' + List.length + ' 项');
LoadList(List, GAP_RES, null);
})
.catch(function () {});
}
function Run() {
if (State.stopped) return;
if (Date.now() - LastRunAt() < 10 * 60 * 1000) return; // 10 分钟内只跑一次
MarkRun();
PreloadStatic();
}
function _start() {
if (State.running) return;
State.running = true;
State.stopped = false;
try {
if (localStorage.getItem(KEY_OFF) === '0') {
console.log('[预热] 已被 localStorage.hornetPrefetch=0 关闭');
State.running = false;
return;
}
} catch (e) {}
console.log('===== 车库资源预热启动 =====');
// 等进入战局:__gameMode__ 由 hook_gamemode.js 捕获
var Wait = setInterval(function () {
if (State.stopped) { clearInterval(Wait); return; }
if (!window.__gameMode__) return;
clearInterval(Wait);
setTimeout(Run, 8000);
}, 2000);
State.timers.push(Wait);
window.__hornetPrefetch__ = {
running: true,
stop: function () {
State.stopped = true;
for (var I = 0; I < State.timers.length; I++) clearInterval(State.timers[I]);
console.log('[预热] 已停止');
}
};
}
_start();
})();