296 lines
15 KiB
JavaScript
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",
|
|
);
|