import { macro, sys } from 'cc'; import { EDITOR } from 'cc/env'; import { readMiniGameHostInfo } from './MiniGameHostInfo'; /** * 仅开发者工具把 SUPPORT_TEXTURE_FORMATS 改成 PNG 优先。 * 须在首场景贴图加载前执行(由 GameLaunch 首行 import)。 * * 真机 Android 的 navigator.platform 常为 Linux aarch64 / Linux arm, * 不得按 Linux 判断 IDE,否则会丢掉 ASTC/ETC,getGFXTexture 空引用每帧卡死。 */ class MiniGameTextureBoot { /** 模块加载时立即判定并改格式列表 */ static apply(): void { if (EDITOR) return; try { if (this.isIde()) { this.preferPng(); } } catch { /* 宿主 API 异常时不改格式,避免误伤真机 */ } } /** * 开发者工具:宿主标签,或电脑桌面指纹 + 小游戏 API。 * 不认裸 Linux:真机 Android WebView 也是 Linux。 */ private static isIde(): boolean { const g = globalThis as MiniGameGlobal; if (g.GameGlobal?.isDevtools) return true; const pf = g.ks ?? g.tt ?? g.wx; const info = readMiniGameHostInfo(pf); let platform = String(info?.platform ?? ''); const appName = String(info?.appName ?? ''); const model = String(info?.model ?? ''); const system = String(info?.system ?? ''); let hostEnv = ''; const host = info?.host; if (host && typeof host === 'object') { const rec = host as { env?: unknown; appName?: unknown }; hostEnv = String(rec.env ?? rec.appName ?? ''); } if (appName === 'devtools') { platform = 'devtools'; } const launchScene = String(pf?.getLaunchOptionsSync?.()?.scene ?? pf?.getLaunchOptionsSync?.()?.from ?? ''); const tagged = platform === 'devtools' || appName === 'devtools' || appName.toLowerCase().includes('devtools') || appName.includes('开发者') || hostEnv.toLowerCase().includes('devtools') || /devtools|simulator|emulator/i.test(launchScene) || /simulator|emulator|devtools/i.test(model) || /devtools/i.test(system); if (tagged) return true; const miniGame = !!(g.ks || g.tt || g.wx) || sys.platform === sys.Platform.BYTEDANCE_MINI_GAME || sys.platform === sys.Platform.WECHAT_GAME; if (!miniGame) return false; const ua = String(g.navigator?.userAgent ?? ''); if (/BytedanceIDE|wechatdevtools|miniprogramdevtools/i.test(ua)) return true; const navPlatform = String(g.navigator?.platform ?? ''); if (/^(Win32|Win64|MacIntel)$/i.test(navPlatform)) return true; const uaData = g.navigator?.userAgentData?.platform; if (uaData === 'Windows' || uaData === 'macOS') return true; const proc = g.process?.platform; if (proc === 'win32' || proc === 'darwin') return true; return sys.os === sys.OS.WINDOWS || sys.os === sys.OS.OSX; } /** 去掉 ASTC/ETC/PVR,走 PNG */ private static preferPng(): void { macro.SUPPORT_TEXTURE_FORMATS = ['.png', '.jpg', '.jpeg', '.webp', '.bmp']; } } MiniGameTextureBoot.apply(); /** 微信 / 抖音 jsbridge */ interface MiniGameHost { getDeviceInfo?: () => Record; getWindowInfo?: () => Record; getAppBaseInfo?: () => Record; getSystemInfoSync?: () => Record; getLaunchOptionsSync?: () => { scene?: string | number; from?: string }; } /** 探测用全局对象 */ interface MiniGameGlobal { ks?: MiniGameHost; tt?: MiniGameHost; wx?: MiniGameHost; GameGlobal?: { isDevtools?: boolean }; navigator?: { userAgent?: string; platform?: string; userAgentData?: { platform?: string }; }; process?: { platform?: string }; }