feat(event): 实现延迟事件的持久化

重构 `DelayedActionManager` 以支持游戏存档和读档。

`DelayedAction` 类现在存储 `eventDefName` 字符串,而不是无法序列化的 `Action` 委托。通过实现 `IExposable` 接口,延迟动作列表现在可以被正确保存和加载,确保计划中的事件不会因重新加载游戏而丢失。
This commit is contained in:
2025-08-08 17:39:26 +08:00
parent 6fcfa5f02c
commit bb156f3fac
3 changed files with 46 additions and 12 deletions

Binary file not shown.

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using RimWorld;
using RimWorld.Planet; using RimWorld.Planet;
using Verse; using Verse;
@@ -7,10 +8,26 @@ namespace WulaFallenEmpire
{ {
public class DelayedActionManager : WorldComponent public class DelayedActionManager : WorldComponent
{ {
private class DelayedAction // Nested class must be public to be accessible for serialization
public class DelayedAction : IExposable
{ {
public int TicksRemaining; public int TicksRemaining;
public Action Action; public string eventDefName;
// Parameterless constructor for Scribe
public DelayedAction() { }
public DelayedAction(string eventDefName, int ticks)
{
this.eventDefName = eventDefName;
this.TicksRemaining = ticks;
}
public void ExposeData()
{
Scribe_Values.Look(ref TicksRemaining, "ticksRemaining", 0);
Scribe_Values.Look(ref eventDefName, "eventDefName");
}
} }
private List<DelayedAction> actions = new List<DelayedAction>(); private List<DelayedAction> actions = new List<DelayedAction>();
@@ -19,13 +36,13 @@ namespace WulaFallenEmpire
{ {
} }
public void AddAction(Action action, int delayTicks) public void AddAction(string eventDefName, int delayTicks)
{ {
if (action == null || delayTicks <= 0) if (string.IsNullOrEmpty(eventDefName) || delayTicks <= 0)
{ {
return; return;
} }
actions.Add(new DelayedAction { TicksRemaining = delayTicks, Action = action }); actions.Add(new DelayedAction(eventDefName, delayTicks));
} }
public override void WorldComponentTick() public override void WorldComponentTick()
@@ -39,23 +56,40 @@ namespace WulaFallenEmpire
{ {
try try
{ {
delayedAction.Action(); ExecuteAction(delayedAction.eventDefName);
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error($"[WulaFallenEmpire] Error executing delayed action: {ex}"); Log.Error($"[WulaFallenEmpire] Error executing delayed action for event '{delayedAction.eventDefName}': {ex}");
} }
actions.RemoveAt(i); actions.RemoveAt(i);
} }
} }
} }
private void ExecuteAction(string defName)
{
EventDef nextDef = DefDatabase<EventDef>.GetNamed(defName, false);
if (nextDef != null)
{
// This logic is simplified from Effect_OpenCustomUI.OpenUI
// It assumes delayed actions always open a new dialog.
Find.WindowStack.Add(new Dialog_CustomDisplay(nextDef));
}
else
{
Log.Error($"[WulaFallenEmpire] DelayedActionManager could not find EventDef named '{defName}'");
}
}
public override void ExposeData() public override void ExposeData()
{ {
// This simple manager does not save scheduled actions across game loads.
// If you need actions to persist, you would need a more complex system
// to serialize the action's target and parameters.
base.ExposeData(); base.ExposeData();
Scribe_Collections.Look(ref actions, "delayedActions", LookMode.Deep);
if (actions == null)
{
actions = new List<DelayedAction>();
}
} }
} }
} }

View File

@@ -24,7 +24,7 @@ namespace WulaFallenEmpire
var actionManager = Find.World.GetComponent<DelayedActionManager>(); var actionManager = Find.World.GetComponent<DelayedActionManager>();
if (actionManager != null) if (actionManager != null)
{ {
actionManager.AddAction(() => OpenUI(), delayTicks); actionManager.AddAction(defName, delayTicks);
} }
else else
{ {