feat: integrate login flow, lobby UI and bitmap font resources
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { resolveRuntimeMode, type RuntimeMode } from './runtime-mode.ts';
|
||||
|
||||
|
||||
/** 调试用登录玩家档案;值只能由测试或本地启动配置显式注入。 */
|
||||
export interface DebugAccount {
|
||||
openid: string;
|
||||
@@ -12,6 +13,8 @@ export interface DebugAccount {
|
||||
}
|
||||
|
||||
export interface StartupConfig {
|
||||
/** 输出全部收发包、配置文件内容及连接状态/重连原因。 */
|
||||
readonly debugIO: boolean;
|
||||
readonly mode: RuntimeMode;
|
||||
/** 配置内容来源;local 仅允许 debug,独立于 WebSocket 服务器选择。 */
|
||||
readonly configSource: 'remote' | 'local';
|
||||
@@ -24,6 +27,7 @@ export interface StartupConfig {
|
||||
|
||||
/** 唯一发布配置入口;mode 与服务器选择互相独立。 */
|
||||
export const STARTUP_CONFIG: Readonly<StartupConfig> = Object.freeze({
|
||||
debugIO: true,
|
||||
mode: 'debug',
|
||||
// 开发时改为 local,编辑 assets/resources/dev-config/update_jsonv2.txt 后重新预览。
|
||||
configSource: 'local',
|
||||
@@ -53,6 +57,7 @@ export function validateLocalServer(value: string, field = 'localServers'): void
|
||||
export function validateStartupConfig(source: Readonly<StartupConfig>): Readonly<StartupConfig> {
|
||||
if (!source || typeof source !== 'object') invalid('source', 'must be an object');
|
||||
const mode = resolveRuntimeMode(source.mode);
|
||||
if (typeof source.debugIO !== 'boolean') invalid('debugIO', 'must be boolean');
|
||||
if (source.configSource !== 'remote' && source.configSource !== 'local') invalid('configSource', 'must be remote or local');
|
||||
if (source.configSource === 'local' && mode !== 'debug') invalid('configSource', 'local is only allowed in debug mode');
|
||||
if (typeof source.localConfigResource !== 'string' || !/^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(source.localConfigResource)) {
|
||||
@@ -65,7 +70,7 @@ export function validateStartupConfig(source: Readonly<StartupConfig>): Readonly
|
||||
if (url.protocol !== 'http:' && url.protocol !== 'https:') invalid('gameserver', 'must be http(s) URL');
|
||||
if (!Array.isArray(source.localServers) || source.localServers.length === 0) invalid('localServers', 'must be a nonempty array');
|
||||
for (let index = 0; index < source.localServers.length; index++) validateLocalServer(source.localServers[index], 'localServers[' + index + ']');
|
||||
return Object.freeze({mode, configSource:source.configSource, localConfigResource:source.localConfigResource, gameserver:source.gameserver, useLocalServer:source.useLocalServer, localServers:Object.freeze([...source.localServers])});
|
||||
return Object.freeze({mode, debugIO:source.debugIO, configSource:source.configSource, localConfigResource:source.localConfigResource, gameserver:source.gameserver, useLocalServer:source.useLocalServer, localServers:Object.freeze([...source.localServers])});
|
||||
}
|
||||
|
||||
/** 忠实旧 min_replaceAll 链:- → /,# → :,再包成 http://...txt。 */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ConfigFetcher } from './remote-config.ts';
|
||||
import { STARTUP_CONFIG } from './profiles.ts';
|
||||
import { ConfigFetchError, ConfigParseError } from './remote-config.ts';
|
||||
|
||||
type FetchImplementation = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
||||
@@ -15,8 +16,11 @@ export class HttpConfigFetcher implements ConfigFetcher {
|
||||
}
|
||||
const text = await response.text();
|
||||
try {
|
||||
return JSON.parse(text) as unknown;
|
||||
const data: unknown = JSON.parse(text);
|
||||
if (STARTUP_CONFIG.debugIO) console.log('[Config REMOTE]', url, data);
|
||||
return data;
|
||||
} catch {
|
||||
if (STARTUP_CONFIG.debugIO) console.log('[Config REMOTE]', url, { parseError: 'Invalid JSON', raw: text });
|
||||
throw new ConfigParseError(`远程配置 JSON 解析失败: ${url}`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user