hch
2026-01-26 aa84cb62bebb9c8a4e586bcc1ec28eb7a16a8860
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using UnityEngine;
using System;
 
/// <summary>
/// PackageRegedit的扩展类
/// 提供新的包分发接口,支持将包分发到RecordAction的内部RecordPlayer
/// 不修改原有的PackageRegedit.Distribute接口,采用新接口绕过
/// </summary>
public class PackageRegeditEx
{
    /// <summary>
    /// 将包分发到指定RecordAction的内部RecordPlayer
    /// 这个方法用于处理RecordAction内部产生的包(如技能内部的Buff添加、子技能等)
    /// 
    /// 使用场景:
    /// 1. SkillBase中通过PackageRegedit.Distribute产生的包,应该使用SkillRecordAction的innerRecordPlayer
    /// 2. 确保这些包的生命周期与父RecordAction绑定
    /// 3. ForceFinish时可以一并处理
    /// </summary>
    /// <param name="pack">要分发的包</param>
    /// <param name="parentRecordAction">父RecordAction,包应该由它的innerRecordPlayer管理</param>
    public static void DistributeToRecordAction(GameNetPackBasic pack, RecordAction parentRecordAction)
    {
        if (pack == null)
        {
            Debug.LogError("PackageRegeditEx.DistributeToRecordAction: pack is null");
            return;
        }
 
        if (parentRecordAction == null)
        {
            // 如果没有父RecordAction,使用原有的分发逻辑(会使用BattleField的主RecordPlayer)
            Debug.LogWarning("PackageRegeditEx.DistributeToRecordAction: parentRecordAction is null, 使用默认分发");
            PackageRegedit.Distribute(pack);
            return;
        }
 
        // 标记这个包是在RecordAction内部处理的
        // 这样可以在PackageRegedit的处理逻辑中识别并使用正确的RecordPlayer
        pack.commonMark = true;
 
        // 临时保存当前正在处理的RecordAction上下文
        // 这样在DTC处理类中可以获取到父RecordAction,从而使用正确的RecordPlayer
        CurrentRecordActionContext.Push(parentRecordAction);
 
        try
        {
            // 调用原有的分发逻辑
            PackageRegedit.Distribute(pack);
        }
        finally
        {
            // 恢复上下文
            CurrentRecordActionContext.Pop();
        }
    }
 
    /// <summary>
    /// 获取当前应该使用的RecordPlayer
    /// 
    /// 判断逻辑:
    /// 1. 如果有当前RecordAction上下文,使用RecordAction.innerRecordPlayer(RecordAction内部产生的)
    /// 2. 否则使用BattleField.recordPlayer(顶层包,直接从服务器来的)
    /// </summary>
    /// <param name="battleField">战场</param>
    /// <returns>应该使用的RecordPlayer</returns>
    public static RecordPlayer GetTargetRecordPlayer(BattleField battleField)
    {
        if (battleField == null)
        {
            Debug.LogError("PackageRegeditEx.GetTargetRecordPlayer: battleField is null");
            return null;
        }
 
        // 检查是否在RecordAction上下文中
        var currentRecordAction = CurrentRecordActionContext.Current;
        if (currentRecordAction != null)
        {
            // 使用RecordAction的innerRecordPlayer
            // 原因:这个包是在RecordAction内部产生的,应该由RecordAction管理
            var innerPlayer = currentRecordAction.GetInnerRecordPlayer();
            if (innerPlayer != null)
            {
                return innerPlayer;
            }
            else
            {
                Debug.LogWarning($"PackageRegeditEx.GetTargetRecordPlayer: RecordAction {currentRecordAction.GetType().Name} 的 innerRecordPlayer 为 null,使用 BattleField.recordPlayer");
            }
        }
 
        // 使用BattleField的主RecordPlayer
        // 原因:这是顶层包,直接从服务器来的,或者没有RecordAction上下文
        return battleField.recordPlayer;
    }
}
 
/// <summary>
/// 当前RecordAction上下文
/// 使用栈结构管理嵌套的RecordAction上下文
/// 这样可以在包分发过程中知道当前处于哪个RecordAction内部
/// </summary>
public static class CurrentRecordActionContext
{
    private static System.Collections.Generic.Stack<RecordAction> contextStack = 
        new System.Collections.Generic.Stack<RecordAction>();
 
    public static RecordAction Current
    {
        get
        {
            if (contextStack.Count > 0)
            {
                return contextStack.Peek();
            }
            return null;
        }
    }
 
    public static void Push(RecordAction recordAction)
    {
        if (recordAction != null)
        {
            contextStack.Push(recordAction);
        }
    }
 
    public static void Pop()
    {
        if (contextStack.Count > 0)
        {
            contextStack.Pop();
        }
    }
 
    public static void Clear()
    {
        contextStack.Clear();
    }
 
    public static int Depth
    {
        get { return contextStack.Count; }
    }
}