mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-25 23:18:44 -07:00
Refactor database bootstrap: enhance primary key constraint handling for LeaderboardChannelMeta table to ensure correct schema migration
This commit is contained in:
@@ -1071,23 +1071,54 @@ internal static class DevMenuProbe
|
|||||||
_frame++;
|
_frame++;
|
||||||
if (_frame < 120) return; // ~2s — let MelonLoader/game boot
|
if (_frame < 120) return; // ~2s — let MelonLoader/game boot
|
||||||
if ((_frame % 60) != 0) return; // then check ~once per second
|
if ((_frame % 60) != 0) return; // then check ~once per second
|
||||||
// Wait until the watch's HomeScreenFlow is actually instantiated
|
// Only fire once a REAL, in-scene HomeScreenFlow exists with its
|
||||||
// (only happens once you're in-game with the watch up), so the
|
// UIBase wired (it gets assigned when the watch StackedUI initialises
|
||||||
// devMenuPanel/devButtonPrefab fields are meaningful. Give up and
|
// in the dorm). The earlier version fired during boot on the loaded
|
||||||
// dump whatever exists after ~60s so we still get a report.
|
// PREFAB (Resources.FindObjectsOfTypeAll returns prefabs/inactive,
|
||||||
|
// whose runtime UIBase is null) and, being one-shot, captured nothing
|
||||||
|
// and never retried. NO timeout now — we wait until the watch is up.
|
||||||
var homeType = Mod.ResolveType("AGUI.StackedUI.HomeScreenFlow") ?? Mod.ResolveType("HomeScreenFlow");
|
var homeType = Mod.ResolveType("AGUI.StackedUI.HomeScreenFlow") ?? Mod.ResolveType("HomeScreenFlow");
|
||||||
var homeLive = homeType != null && FindOne(homeType) != null;
|
var home = homeType != null ? FindLiveHome(homeType) : null;
|
||||||
if (!homeLive && _frame < 3600) return;
|
if (home == null)
|
||||||
|
{
|
||||||
|
if ((_frame % 600) == 0)
|
||||||
|
Mod.Log.Msg("[devmenu-probe] waiting for an in-scene HomeScreenFlow — enter your dorm / open the watch…");
|
||||||
|
return;
|
||||||
|
}
|
||||||
_done = true;
|
_done = true;
|
||||||
try { Run(); }
|
try { Run(homeType!, home); }
|
||||||
catch (Exception ex) { Mod.Log.Warning($"[devmenu-probe] failed: {ex}"); }
|
catch (Exception ex) { Mod.Log.Warning($"[devmenu-probe] failed: {ex}"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Run()
|
// The live HomeScreenFlow (UIBase wired), skipping the prefab/inactive
|
||||||
|
// copies FindObjectsOfTypeAll also returns.
|
||||||
|
private static object? FindLiveHome(Type homeType)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var il2 = ToIl2CppType(homeType);
|
||||||
|
if (il2 is null) return null;
|
||||||
|
var resources = Mod.ResolveType("UnityEngine.Resources");
|
||||||
|
var all = OneArgMethod(resources, "FindObjectsOfTypeAll", il2)?.Invoke(null, new[] { il2 });
|
||||||
|
int n = ArrLen(all);
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
var o = ArrItem(all, i);
|
||||||
|
if (o is null) continue;
|
||||||
|
if (GetMemberValue(homeType, o, "UIBase", "get_UIBase") != null) return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Run(Type homeType, object homeInst)
|
||||||
{
|
{
|
||||||
Mod.Log.Msg("=== [devmenu-probe] runtime dev-UI state ===");
|
Mod.Log.Msg("=== [devmenu-probe] runtime dev-UI state ===");
|
||||||
ProbeType("RecRoom.Core.WatchUI", "WatchUI", DumpWatchUi);
|
ProbeType("RecRoom.Core.WatchUI", "WatchUI", DumpWatchUi);
|
||||||
ProbeType("AGUI.StackedUI.HomeScreenFlow", "HomeScreenFlow", DumpHomeScreen);
|
Mod.Log.Msg($"[devmenu-probe] HomeScreenFlow: type={homeType.FullName}, liveInstance=FOUND (UIBase wired)");
|
||||||
|
try { DumpHomeScreen(homeType, homeInst); }
|
||||||
|
catch (Exception ex) { Mod.Log.Warning($"[devmenu-probe] HomeScreenFlow dump failed: {ex.Message}"); }
|
||||||
ProbeType("RecRoom.Debugging.DebugConsole", "DebugConsole", DumpDebugConsole);
|
ProbeType("RecRoom.Debugging.DebugConsole", "DebugConsole", DumpDebugConsole);
|
||||||
Mod.Log.Msg("=== [devmenu-probe] done ===");
|
Mod.Log.Msg("=== [devmenu-probe] done ===");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -337,7 +337,22 @@ public static class DatabaseBootstrap
|
|||||||
DO $$
|
DO $$
|
||||||
DECLARE
|
DECLARE
|
||||||
pk_cols text[];
|
pk_cols text[];
|
||||||
|
pk record;
|
||||||
BEGIN
|
BEGIN
|
||||||
|
FOR pk IN
|
||||||
|
SELECT c.conname, array_agg(a.attname ORDER BY x.ordinality) AS cols
|
||||||
|
FROM pg_constraint c
|
||||||
|
JOIN unnest(c.conkey) WITH ORDINALITY AS x(attnum, ordinality) ON true
|
||||||
|
JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = x.attnum
|
||||||
|
WHERE c.conrelid = '"LeaderboardChannelMeta"'::regclass
|
||||||
|
AND c.contype = 'p'
|
||||||
|
GROUP BY c.conname
|
||||||
|
LOOP
|
||||||
|
IF pk.cols IS DISTINCT FROM ARRAY['RoomId', 'Channel'] THEN
|
||||||
|
EXECUTE format('ALTER TABLE %I DROP CONSTRAINT %I', 'LeaderboardChannelMeta', pk.conname);
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
SELECT array_agg(a.attname ORDER BY x.ordinality)
|
SELECT array_agg(a.attname ORDER BY x.ordinality)
|
||||||
INTO pk_cols
|
INTO pk_cols
|
||||||
FROM pg_constraint c
|
FROM pg_constraint c
|
||||||
@@ -347,7 +362,6 @@ public static class DatabaseBootstrap
|
|||||||
AND c.contype = 'p';
|
AND c.contype = 'p';
|
||||||
|
|
||||||
IF pk_cols IS DISTINCT FROM ARRAY['RoomId', 'Channel'] THEN
|
IF pk_cols IS DISTINCT FROM ARRAY['RoomId', 'Channel'] THEN
|
||||||
ALTER TABLE "LeaderboardChannelMeta" DROP CONSTRAINT IF EXISTS "PK_LeaderboardChannelMeta";
|
|
||||||
ALTER TABLE "LeaderboardChannelMeta"
|
ALTER TABLE "LeaderboardChannelMeta"
|
||||||
ADD CONSTRAINT "PK_LeaderboardChannelMeta" PRIMARY KEY ("RoomId", "Channel");
|
ADD CONSTRAINT "PK_LeaderboardChannelMeta" PRIMARY KEY ("RoomId", "Channel");
|
||||||
END IF;
|
END IF;
|
||||||
|
|||||||
Reference in New Issue
Block a user