starraid/star-raid/js/net.js
JOJO 9edc366cf9 图鉴测试模式+巡飞弹新武器+存档云同步+机库合并+默认无尽
①图鉴隐藏测试模式:连点标题'军'字10次开关,纯内存标志位全部军械可见可演示,不动SAVE.codex(persist/submitRun读它,动了会污染后端),刷新失效
②24件主武器说明文案全部替换(用户提供梗文案);演示页介绍单行显示、去掉类别前缀、删'实战模拟·自动驾驶'提示行
③新主武器'巡飞弹'(loiter):慢攻速追踪导弹(制导引擎新增maxSpd上限5保持中速),命中留火场(zones新kind:fire纯粒子火舌,无圆形区域)+分裂4枚小炸弹快爆;新精灵loms;CODEX_KEYS同步63
④存档云同步:星币/机体/选中机体/永久强化/本地纪录上服务端(player_state表+POST /api/state+vState白名单清洗);login/me/register响应带state;客户端persist()钩子防抖600ms自动上传;服务端整体替换本地防串号,登出全清;老账号首登自动上传本地存档迁移
⑤机体选择/购买从出击准备并入机库强化(buildShips);出击默认无尽模式
服务端已重启生效;/api/state全链路在独立测试库curl验证通过(合法推送/回读/非法拦截清洗/401)
2026-08-06 12:15:17 +08:00

109 lines
4.1 KiB
JavaScript
Raw 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.

"use strict";
/* ================= 网络层:服务端 API 客户端 ================= */
const NET = {
user: null, // {username,email}
stats: null, // {bossKills,endlessHigh,runs}
codexTotal: 63,
online: false,
async api(path, method, body) {
let res;
try {
res = await fetch(path, {
method: method || "GET",
credentials: "same-origin",
headers: body ? { "Content-Type": "application/json" } : undefined,
body: body ? JSON.stringify(body) : undefined,
});
} catch (e) {
return { ok: false, status: 0, data: { error: "无法连接服务器" } };
}
let data = {};
try { data = await res.json(); } catch (e) { /* 空响应 */ }
return { ok: res.ok, status: res.status, data };
},
/* 启动尝试恢复会话。true=已登录(未登录时服务端返回 200 {user:null} */
async boot() {
const r = await this.api("/api/me", "GET");
if (r.ok && r.data.user) { this._apply(r.data); return true; }
return false;
},
async login(id, password) {
const r = await this.api("/api/login", "POST", { id, password });
if (r.ok) { this._apply(r.data); return null; }
return r.data.error || "登陆失败";
},
async register(username, email, password) {
const r = await this.api("/api/register", "POST", { username, email, password });
if (r.ok) { this._apply(r.data); return null; }
return r.data.error || "注册失败";
},
async logout() {
await this.api("/api/logout", "POST");
this.user = null; this.stats = null; this.online = false;
/* 防同机下一账号继承:图鉴/星币/机体/强化/纪录全部清空user 已置空persist 不会触发上传) */
SAVE.codex = {};
SAVE.coins = 0; SAVE.ships = ["falcon"]; SAVE.m = {};
SAVE.best = { s0: 0, s1: 0, e0: 0, e1: 0, stage: 0 }; SAVE.rush = {};
if (typeof SETUP !== "undefined") SETUP.ship = "falcon";
persist();
},
/* 应用服务端返回的用户数据:图鉴以服务端为准【替换】本地
不能并集合并——localStorage 是浏览器级共享,同机多账号会互相污染,已踩坑) */
_apply(d) {
this.user = d.user;
this.stats = d.stats;
this.codexTotal = d.codexTotal || 63;
this.online = true;
SAVE.codex = {};
if (Array.isArray(d.codex)) for (const k of d.codex) SAVE.codex[k] = true;
/* 服务端存档权威:整体替换本地(防串号,与图鉴同理);替换期间禁止回传 */
this._mutePush = true;
if (d.state) {
SAVE.coins = d.state.coins;
SAVE.ships = d.state.ships.slice();
SAVE.m = Object.assign({}, d.state.m);
SAVE.best = Object.assign({ s0: 0, s1: 0, e0: 0, e1: 0, stage: 0 }, d.state.best);
SAVE.rush = Object.assign({}, d.state.rush);
if (d.state.ship && SAVE.ships.includes(d.state.ship) && typeof SETUP !== "undefined") SETUP.ship = d.state.ship;
}
persist();
this._mutePush = false;
if (!d.state) this.pushState(); // 服务端无存档(老账号首登):把本地存档上传初始化
},
/* 存档云同步(防抖 600ms星币/机体/选中机体/永久强化/本地纪录。任何 persist 都会触发 */
_stateT: null,
pushState() {
if (!this.user || this._mutePush) return;
clearTimeout(this._stateT);
this._stateT = setTimeout(() => {
if (!this.user) return;
this.api("/api/state", "POST", { state: {
coins: SAVE.coins, ships: SAVE.ships,
ship: typeof SETUP !== "undefined" ? SETUP.ship : "falcon",
m: SAVE.m, best: SAVE.best, rush: SAVE.rush || {},
} }).catch(() => { /* 网络失败静默:本地存档仍在 */ });
}, 600);
},
/* 结算上报fire-and-forget成功后回写最新统计 */
submitRun(payload) {
if (!this.user) return;
this.api("/api/run", "POST", payload).then((r) => {
if (r.ok) {
this.stats = r.data.stats;
if (Array.isArray(r.data.codex)) {
for (const k of r.data.codex) SAVE.codex[k] = true;
persist();
}
}
}).catch(() => { /* 网络失败静默:本地存档仍在 */ });
},
};