refactor(UXAssist): safe GameEvent wrapper and XML docs

This commit is contained in:
2026-06-23 08:17:08 +08:00
parent 439d74c817
commit d843090622
2 changed files with 57 additions and 21 deletions
+27
View File
@@ -0,0 +1,27 @@
using System;
using BepInEx.Logging;
namespace UXAssist.Common;
/// <summary>
/// Provides safe invocation helpers for game events.
/// </summary>
public static class GameEvent
{
/// <summary>
/// Invokes each handler in the action's invocation list individually,
/// logging a warning if any handler throws an exception.
/// </summary>
/// <param name="action">The action to invoke.</param>
/// <param name="logger">The logger to use for warnings.</param>
/// <param name="name">The name of the event for diagnostic messages.</param>
public static void InvokeSafe(this Action action, ManualLogSource logger, string name)
{
if (action == null) return;
foreach (var d in action.GetInvocationList())
{
try { d.DynamicInvoke(); }
catch (Exception ex) { logger?.LogWarning($"GameEvent '{name}' handler failed: {ex}"); }
}
}
}
+30 -21
View File
@@ -1,49 +1,58 @@
using System; using System;
using HarmonyLib; using HarmonyLib;
using UnityEngine;
namespace UXAssist.Common; namespace UXAssist.Common;
/// <summary>
/// Provides game lifecycle events for UXAssist and dependent mods.
/// </summary>
public class GameLogic : PatchImpl<GameLogic> public class GameLogic : PatchImpl<GameLogic>
{ {
/// <summary>
/// Raised after game data has finished loading.
/// </summary>
public static Action OnDataLoaded; public static Action OnDataLoaded;
/// <summary>
/// Raised when a game session begins.
/// </summary>
public static Action OnGameBegin; public static Action OnGameBegin;
/// <summary>
/// Raised when a game session ends.
/// </summary>
public static Action OnGameEnd; public static Action OnGameEnd;
private static void InvokeSafe(Action action) /// <summary>
{ /// Harmony postfix for <see cref="VFPreload.InvokeOnLoadWorkEnded"/>.
if (action == null) return; /// Raises <see cref="OnDataLoaded"/>.
foreach (var handler in action.GetInvocationList()) /// </summary>
{
try
{
((Action)handler)();
}
catch (Exception ex)
{
Debug.LogException(ex);
}
}
}
[HarmonyPostfix] [HarmonyPostfix]
[HarmonyPatch(typeof(VFPreload), nameof(VFPreload.InvokeOnLoadWorkEnded))] [HarmonyPatch(typeof(VFPreload), nameof(VFPreload.InvokeOnLoadWorkEnded))]
public static void VFPreload_InvokeOnLoadWorkEnded_Postfix() public static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
{ {
InvokeSafe(OnDataLoaded); OnDataLoaded.InvokeSafe(UXAssist.Logger, nameof(OnDataLoaded));
} }
/// <summary>
/// Harmony postfix for <see cref="GameMain.Begin"/>.
/// Raises <see cref="OnGameBegin"/>.
/// </summary>
[HarmonyPostfix, HarmonyPriority(Priority.First)] [HarmonyPostfix, HarmonyPriority(Priority.First)]
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))] [HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
public static void GameMain_Begin_Postfix() public static void GameMain_Begin_Postfix()
{ {
InvokeSafe(OnGameBegin); OnGameBegin.InvokeSafe(UXAssist.Logger, nameof(OnGameBegin));
} }
/// <summary>
/// Harmony postfix for <see cref="GameMain.End"/>.
/// Raises <see cref="OnGameEnd"/>.
/// </summary>
[HarmonyPostfix, HarmonyPriority(Priority.Last)] [HarmonyPostfix, HarmonyPriority(Priority.Last)]
[HarmonyPatch(typeof(GameMain), nameof(GameMain.End))] [HarmonyPatch(typeof(GameMain), nameof(GameMain.End))]
public static void GameMain_End_Postfix() public static void GameMain_End_Postfix()
{ {
InvokeSafe(OnGameEnd); OnGameEnd.InvokeSafe(UXAssist.Logger, nameof(OnGameEnd));
} }
} }