2026-03-20 11:56:50 -04:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
2026-04-17 12:01:50 -04:00
|
|
|
|
namespace SLSUtilities.General
|
2026-03-20 11:56:50 -04:00
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 指令上下文 (Command Context)
|
|
|
|
|
|
/// 以强类型键值对存储指令执行时传递的游戏状态信息。
|
|
|
|
|
|
/// outerContext 由 CommandQueueManager 创建并传递给每条顶层指令;
|
|
|
|
|
|
/// selfContext 是每条指令自身私有的上下文,可携带局部参数。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class CommandContext
|
|
|
|
|
|
{
|
|
|
|
|
|
// 保留公开字段以兼容尚未迁移的调用点,后续步骤中逐一移除直接访问
|
|
|
|
|
|
public readonly Dictionary<string, object> context;
|
|
|
|
|
|
|
|
|
|
|
|
public CommandContext()
|
|
|
|
|
|
{
|
|
|
|
|
|
context = new Dictionary<string, object>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public CommandContext((string, object)[] pairs)
|
|
|
|
|
|
{
|
|
|
|
|
|
context = new Dictionary<string, object>();
|
|
|
|
|
|
foreach ((string key, object value) in pairs)
|
|
|
|
|
|
context[key] = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public CommandContext(Dictionary<string, object> initialInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
context = new Dictionary<string, object>();
|
|
|
|
|
|
foreach (var pair in initialInfo)
|
|
|
|
|
|
context[pair.Key] = pair.Value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── 强类型访问 API ────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>以强类型写入一个值。</summary>
|
|
|
|
|
|
public void Set<T>(string key, T value)
|
|
|
|
|
|
{
|
|
|
|
|
|
context[key] = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 以强类型读取一个值。
|
|
|
|
|
|
/// 找不到 key 或类型不匹配时抛出 <see cref="KeyNotFoundException"/>。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public T Get<T>(string key)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (context.TryGetValue(key, out object raw) && raw is T typed)
|
|
|
|
|
|
return typed;
|
|
|
|
|
|
|
|
|
|
|
|
throw new KeyNotFoundException(
|
|
|
|
|
|
$"CommandContext 中不存在键 '{key}',或其类型与 {typeof(T).Name} 不匹配。");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 以强类型尝试读取一个值。
|
|
|
|
|
|
/// 找不到 key 或类型不匹配时返回 false,result 为默认值。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool TryGet<T>(string key, out T result)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (context.TryGetValue(key, out object raw) && raw is T typed)
|
|
|
|
|
|
{
|
|
|
|
|
|
result = typed;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = default;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── 旧 API(向后兼容,后续步骤迁移完成后移除) ──────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 以强类型读取一个值。找不到或类型不匹配时返回默认值并写日志警告。
|
|
|
|
|
|
/// 新代码请改用 <see cref="Get{T}"/> 或 <see cref="TryGet{T}"/>。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Obsolete("请改用 Get<T>(key) 或 TryGet<T>(key, out result)。")]
|
|
|
|
|
|
public T GetInfo<T>(string key)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (TryGet<T>(key, out T result))
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
|
|
UnityEngine.Debug.LogWarning(
|
|
|
|
|
|
$"CommandContext 中不存在键 '{key}',或其类型不匹配。返回默认值。");
|
|
|
|
|
|
return default;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── 工具方法 ──────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>返回一个拥有相同键值对副本的新上下文(浅拷贝)。</summary>
|
|
|
|
|
|
public CommandContext Clone()
|
|
|
|
|
|
{
|
|
|
|
|
|
var copy = new CommandContext();
|
|
|
|
|
|
foreach (var pair in context)
|
|
|
|
|
|
copy.context[pair.Key] = pair.Value;
|
|
|
|
|
|
return copy;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>将 other 的所有键值合并到当前上下文(同键覆盖),返回自身以支持链式调用。</summary>
|
|
|
|
|
|
public CommandContext Merge(CommandContext other)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var pair in other.context)
|
|
|
|
|
|
context[pair.Key] = pair.Value;
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|