Files
Ananta-ps/Ananta.Proxy/proxy/tools/generate_client_config_patch.DRMK.reference.js
T

296 lines
15 KiB
JavaScript

"use strict";
const fs = require("fs");
const path = require("path");
const fengari = require("fengari");
const { lua, lauxlib, to_luastring } = fengari;
const { config, resolveProjectPath } = require("../private_server_config");
const clientVersion = String(config.client.version);
const fastPatchRoot = path.join(resolveProjectPath(config.paths.runtimeFastpatch), clientVersion);
const luaSrcRoot = resolveProjectPath("lua"); // decompiled client Lua source
const fileName = "LuaFiles#LX6#SGUI#StoreDefine#UidLayerPanelStore.lua";
const labelEnabled = config.ui?.uidLabel?.enabled !== false;
const label = labelEnabled ? String(config.ui?.uidLabel?.text || "Приватный Сервер Дремки!!!") : "";
const removeStock = config.ui?.removeStockConfidentialLabel !== false;
const forceDebugOff = config.ui?.forceDisableDebugBools !== false;
const debugClearAll = config.ui?.debugBoolsClearAll !== false;
const debugClearNames = (Array.isArray(config.ui?.debugBoolsClearNames) ? config.ui.debugBoolsClearNames : [])
.map((v) => String(v))
.filter((v) => v.length > 0);
const tryFeatureSwitchDebugOff = config.ui?.tryFeatureSwitchDebugOff === true;
const debugNamesLua = debugClearNames.length === 0
? "{ }"
: `{ ${debugClearNames.map((n) => JSON.stringify(n)).join(", ")} }`;
// Debug overlay forcing. The in-game GM panel's "clear debug bool" button walks
// gCS.DebugBoolMgr.GetView() -> viewList[i].list -> item.field = false + OnChange(item)
// (see LX6/SGUI/StoreDefine/TestMainPanelStore.lua); we do exactly the same from a Lua
// fastpatch so 坐标信息 / 水印 / other debug toggles start off instead of being switched
// off by hand every session. Re-applied on panel lifecycle events and a few delays after
// load, which is when the client populates the debug bool table.
const luaOverlayDefs =
`local FORCE_DEBUG_OFF = ${forceDebugOff ? "true" : "false"}\n` +
`local DEBUG_CLEAR_ALL = ${debugClearAll ? "true" : "false"}\n` +
`local DEBUG_CLEAR_NAMES = ${debugNamesLua}\n` +
`local TRY_FEATURE_SWITCH_OFF = ${tryFeatureSwitchDebugOff ? "true" : "false"}\n` +
`local DEBUG_REAPPLY_DELAYS = { 5, 15, 30 }\n` +
`local DEBUG_DUMP_LIMIT = 80\n` +
`local debugDumpLogged = false\n` +
`local debugErrorReported = false\n` +
`local debugScheduleStarted = false\n` +
`local debugReapplyStep = 0\n` +
`local featureSwitchTried = false\n` +
`local watermarkReported = false\n\n` +
`local function TryStep(label, fn)\n` +
` local ok, err = pcall(fn)\n` +
` if not ok and not debugErrorReported then\n` +
` debugErrorReported = true\n` +
` print("[DRMK] " .. label .. " failed: " .. tostring(err))\n` +
` end\n` +
` return ok\n` +
`end\n\n` +
`local function DisableUidWatermark()\n` +
` return TryStep("UIConfig watermark off", function()\n` +
` if CS and CS.SGUI and CS.SGUI.UIConfig then\n` +
` local inst = CS.SGUI.UIConfig.instance or CS.SGUI.UIConfig.Instance\n` +
` if inst then\n` +
` inst.enableImageWatermark = false\n` +
` inst.imageWatermarkText = ""\n` +
` if CS.UnityEngine and CS.UnityEngine.Color then\n` +
` inst.imageWatermarkColor = CS.UnityEngine.Color(0, 0, 0, 0)\n` +
` end\n` +
` end\n` +
` end\n` +
` end)\n` +
`end\n\n` +
`local function DisableMonitorWatermark()\n` +
` return TryStep("MonitorCheck watermark off", function()\n` +
` if CS and CS.LX6 and CS.LX6.Utils and CS.LX6.Utils.MonitorCheck then\n` +
` CS.LX6.Utils.MonitorCheck.IsShowWatermarkAlways = false\n` +
` CS.LX6.Utils.MonitorCheck.IsAntiMonitorAlways = false\n` +
` CS.LX6.Utils.MonitorCheck.IsAntiMonitorWithBlack = false\n` +
` end\n` +
` end)\n` +
`end\n\n` +
`local function DisableWatermarks()\n` +
` local uid = DisableUidWatermark()\n` +
` local monitor = DisableMonitorWatermark()\n` +
` if not watermarkReported then\n` +
` watermarkReported = true\n` +
` print("[DRMK] watermark channels: UIConfig=" .. tostring(uid) .. " MonitorCheck=" .. tostring(monitor))\n` +
` end\n` +
`end\n\n` +
`local function DebugBoolWanted(name, tip)\n` +
` if DEBUG_CLEAR_ALL then return true end\n` +
` if #DEBUG_CLEAR_NAMES == 0 then return false end\n` +
` local text = tostring(name or "") .. "|" .. tostring(tip or "")\n` +
` for i = 1, #DEBUG_CLEAR_NAMES do\n` +
` if string.find(text, DEBUG_CLEAR_NAMES[i], 1, true) then return true end\n` +
` end\n` +
` return false\n` +
`end\n\n` +
`local function TryFeatureSwitchDebugOff()\n` +
` if not TRY_FEATURE_SWITCH_OFF then return end\n` +
` local ok = pcall(function()\n` +
` if gCS.FeatureSwitch and gCS.FeatureSwitch.SetDebugItemValueFalse then\n` +
` gCS.FeatureSwitch.SetDebugItemValueFalse()\n` +
` print("[DRMK] FeatureSwitch.SetDebugItemValueFalse() called")\n` +
` end\n` +
` end)\n` +
` if not ok then print("[DRMK] FeatureSwitch.SetDebugItemValueFalse() failed (ignore)") end\n` +
`end\n\n` +
`local function DisableDebugBools(tag)\n` +
` if not FORCE_DEBUG_OFF then return end\n` +
` local ok, err = pcall(function()\n` +
` local viewList = gCS.DebugBoolMgr.GetView()\n` +
` local total, changed, names = 0, 0, ""\n` +
` for i = 0, viewList.Count - 1 do\n` +
` local group = viewList[i]\n` +
` local list = group and group.list\n` +
` if list then\n` +
` for j = 0, list.Count - 1 do\n` +
` local item = list[j]\n` +
` if item then\n` +
` total = total + 1\n` +
` local name, tip = item.name, item.tip\n` +
` if total <= DEBUG_DUMP_LIMIT then\n` +
` names = names .. "\\n[DRMK] " .. tostring(name) .. " | " .. tostring(tip) .. " = " .. tostring(item.field)\n` +
` end\n` +
` if item.field and DebugBoolWanted(name, tip) then\n` +
` item.field = false\n` +
` item.OnChange(item)\n` +
` changed = changed + 1\n` +
` end\n` +
` end\n` +
` end\n` +
` end\n` +
` end\n` +
` if not debugDumpLogged then\n` +
` debugDumpLogged = true\n` +
` print("[DRMK] debug bools: total=" .. tostring(total) .. " cleared=" .. tostring(changed) .. names)\n` +
` elseif changed > 0 then\n` +
` print("[DRMK] debug bools re-cleared=" .. tostring(changed) .. " (" .. tostring(tag) .. ")")\n` +
` end\n` +
` end)\n` +
` if not ok and not debugErrorReported then\n` +
` debugErrorReported = true\n` +
` print("[DRMK] debug bool clear failed: " .. tostring(err))\n` +
` end\n` +
` if not featureSwitchTried then\n` +
` featureSwitchTried = true\n` +
` TryFeatureSwitchDebugOff()\n` +
` end\n` +
`end\n\n` +
`local function ScheduleDebugOverlayClear()\n` +
` if not FORCE_DEBUG_OFF or debugScheduleStarted then return end\n` +
` debugScheduleStarted = true\n` +
` local function step()\n` +
` debugReapplyStep = debugReapplyStep + 1\n` +
` if debugReapplyStep > #DEBUG_REAPPLY_DELAYS then return end\n` +
` local delay = DEBUG_REAPPLY_DELAYS[debugReapplyStep]\n` +
` pcall(function()\n` +
` gLuaTimeMgrUtils.Delay(function()\n` +
` DisableDebugBools("delay" .. tostring(delay))\n` +
` step()\n` +
` end, delay, 1)\n` +
` end)\n` +
` end\n` +
` step()\n` +
`end\n\n`;
fs.rmSync(fastPatchRoot, { recursive: true, force: true });
fs.mkdirSync(fastPatchRoot, { recursive: true });
const qLabel = JSON.stringify(label);
const luaSource = `-- DRMK private-server fastpatch for client ${clientVersion}\n` +
`-- Persistent UID/watermark override only. Gameplay Lua is untouched.\n\n` +
`local CSPauseManager = LX6.Engine.PauseManager\n` +
`C_UidLayerPanelStore = DefClass("C_UidLayerPanelStore", C_UidLayerPanelStore, C_StoreGroup)\n` +
`GroupName2Class.UidLayerPanelStore = C_UidLayerPanelStore\n` +
`local M = C_UidLayerPanelStore\n` +
`local PRIVATE_SERVER_LABEL = ${qLabel}\n` +
`local REMOVE_STOCK_LABEL = ${removeStock ? "true" : "false"}\n` +
`local LABEL_ENABLED = ${labelEnabled ? "true" : "false"}\n\n` +
luaOverlayDefs +
`local function ApplyPrivateServerText(self)\n` +
` if not self or not self.bindData then return end\n` +
` local login = gPlayerManager and gPlayerManager.infoLogin and gPlayerManager.infoLogin.bindData or nil\n` +
` local pid = login and login.pid or nil\n` +
` if LABEL_ENABLED then\n` +
` self.bindData.uidLabel = pid ~= nil and ("UID:" .. ulong.tostring(pid)) or ""\n` +
` else\n` +
` self.bindData.uidLabel = ""\n` +
` end\n` +
` if REMOVE_STOCK_LABEL then self.bindData.confidentialLabel = PRIVATE_SERVER_LABEL end\n` +
` self.bindData.versionCtrl = 0\n` +
` self.bindData.showUID = 0\n` +
` DisableWatermarks()\n` +
` DisableDebugBools("lifecycle")\n` +
`end\n\n` +
`M.ctor = function(self)\n` +
` self.msgEvents = { [gEventConstants.L50_BEFORE_SWITCH_SCENE] = self.CreateAction(self, "OnBeforeSwitchScene") }\n` +
`end\n\n` +
`M.OnAwake = function(self)\n` +
` self.RegisterMessageEvents(self, self.msgEvents)\n` +
` gLuaUIMgr.uidLayerPanelStore = self\n` +
` ApplyPrivateServerText(self)\n` +
` ScheduleDebugOverlayClear()\n` +
`end\n\n` +
`M.OnShow = function(self, panelId, data)\n` +
` ApplyPrivateServerText(self)\n` +
`end\n\n` +
`M.OnClose = function(self) end\n\n` +
`M.OnDestroy = function(self)\n` +
` self.ClearMessageEvents(self)\n` +
` gLuaUIMgr.uidLayerPanelStore = nil\n` +
`end\n\n` +
`M.OnActiveDeviceChange = function(self, device) end\n\n` +
`M.ShowPauseInfo = function(self, serveSpeed)\n` +
` if not gGameManager.Env.isEditor or not gCS.PauseManager.showPauseTip then\n` +
` self.bindData.pauseLabel = ""\n` +
` return\n` +
` end\n` +
` local clientSpeed = CSPauseManager.Instance.PauseSpeed\n` +
` local text = ""\n` +
` if clientSpeed then\n` +
` if clientSpeed ~= 0 then\n` +
` text = text .. "客户端暂停 "\n` +
` elseif clientSpeed >= 1 then\n` +
` text = text .. "客户端时缓:" .. gString.Format("%.2f", clientSpeed) .. " "\n` +
` end\n` +
` end\n` +
` if serveSpeed then text = text .. "服务端暂停" else text = "" end\n` +
` self.bindData.pauseLabel = text\n` +
`end\n\n` +
`M.RefreshUID = function(self) ApplyPrivateServerText(self) end\n` +
`M.RefreshVersion = function(self) ApplyPrivateServerText(self) end\n` +
`M.RefreshUIDDisplay = function(self, show)\n` +
` if self and self.bindData then self.bindData.showUID = 0 end\n` +
`end\n\n` +
`M.OnBeforeSwitchScene = function(self, eventId, switchSceneEventParams)\n` +
` ApplyPrivateServerText(self)\n` +
`end\n\n` +
`M.OnLanguageChange = function(self, lang) ApplyPrivateServerText(self) end\n`;
const L = lauxlib.luaL_newstate();
const luaBytes = to_luastring(luaSource);
const status = lauxlib.luaL_loadbuffer(L, luaBytes, luaBytes.length, to_luastring(fileName));
if (status !== lua.LUA_OK) throw new Error("generated UidLayerPanelStore.lua failed Lua syntax validation");
fs.writeFileSync(path.join(fastPatchRoot, fileName), luaSource, "utf8");
// GameSwitch defaults: the private server has no GameSwitch RPC, so the client's
// gGameSwitch table would stay empty and every switch-gated phone app/panel would
// report "This feature is temporarily unavailable". Pre-seed all retail switches
// to open (real-money charge stays closed). Server-side SyncGameSwitchToClient
// still wins whenever it arrives, because M.Sync overwrites these defaults.
const forceSwitches = config.ui?.forceEnableGameSwitches !== false;
const switchFileName = "LuaFiles#LX6#Manager#ClientGameSwitch.lua";
// NOTE: EnableCharge is intentionally absent (real-money flow).
const gameSwitchDefaults = [
"DisableImageWatermark", "NoWatermark",
"EnableBuzzCenter", "EnableMall", "EnableMallBundle", "EnableMallRecommend",
"EnableMallDirectSale", "EnableCheckIn", "EnableTime", "EnableDossier",
"EnableRadiantChest", "EnableCloset", "EnableGachaSystem", "EnableSeasonalBattlePass",
"EnableBBChat", "EnableScope", "EnableParty", "EnableSpiritTalent",
"EnablePhoto", "EnableMail", "EnablePhone", "EnableFriends",
"EnableAchievement", "EnableTutorial", "EnableCityPedia", "EnableNotices",
"EnableCustom", "EnableInteractionAction", "EnableDutyTerminal", "EnableCatExpress",
"EnableEonBug", "EnableJanitor", "EnableRadioStation", "EnableBubble",
"EnableFashionStore", "Enable4SStore", "EnableProfile", "EnableClub",
"EnableRanking", "EnableAkashicSystem",
];
let switchNote = "GameSwitch defaults: skipped (ui.forceEnableGameSwitches=false).\n";
const debugNote = forceDebugOff
? `Debug overlays: forcing 坐标信息/水印 class debug toggles to false (clearAll=${debugClearAll}, names=[${debugClearNames.join(", ")}]).\n`
: "Debug overlays: untouched (ui.forceDisableDebugBools=false).\n";
if (forceSwitches) {
const switchSource = `-- DRMK private-server fastpatch for client ${clientVersion}\n` +
`-- GameSwitch defaults only. Original ClientGameSwitch.lua logic is unchanged.\n\n` +
`local M = {}\n\n` +
`M.Sync = function(key, value)\n` +
` M[key] = value\n\n` +
` gMessageManager:SendMessage(gEventConstants.ON_GM_GAME_SWITCH_CHANGE)\n` +
`end\n\n` +
gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") +
`M.EnableImageWatermark = false\n` +
`\n` +
`gGameSwitch = M\n`;
const switchBytes = to_luastring(switchSource);
const switchStatus = lauxlib.luaL_loadbuffer(L, switchBytes, switchBytes.length, to_luastring(switchFileName));
if (switchStatus !== lua.LUA_OK) throw new Error("generated ClientGameSwitch.lua failed Lua syntax validation");
fs.writeFileSync(path.join(fastPatchRoot, switchFileName), switchSource, "utf8");
switchNote = `GameSwitch defaults: ${gameSwitchDefaults.length} switches pre-seeded open (EnableCharge stays closed).\n`;
}
fs.writeFileSync(
path.join(fastPatchRoot, "changelog.txt"),
`DRMK PRIVATE SERVER FASTPATCH (client ${clientVersion})\n` +
`UID label: ${label}\n` +
"Stock development/confidential and version-mismatch captions are suppressed.\n" +
switchNote +
debugNote +
"No gameplay Lua overrides are included.\n",
"utf8",
);