继续
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SLSFramework.General
|
||||
{
|
||||
@@ -17,15 +18,16 @@ namespace SLSFramework.General
|
||||
context = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public CommandContext(string key, object value)
|
||||
public CommandContext((string, object)[] pairs)
|
||||
{
|
||||
context = new Dictionary<string, object>
|
||||
context = new Dictionary<string, object>();
|
||||
foreach ((string, object) pair in pairs)
|
||||
{
|
||||
{ key, value }
|
||||
};
|
||||
context[pair.Item1] = pair.Item2;
|
||||
}
|
||||
}
|
||||
|
||||
public CommandContext(List<KeyValuePair<string, object>> initialInfo)
|
||||
|
||||
public CommandContext(Dictionary<string, object> initialInfo)
|
||||
{
|
||||
context = new Dictionary<string, object>();
|
||||
foreach (var pair in initialInfo)
|
||||
@@ -33,7 +35,7 @@ namespace SLSFramework.General
|
||||
context[pair.Key] = pair.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public CommandContext Clone()
|
||||
{
|
||||
var newContext = new CommandContext();
|
||||
@@ -43,6 +45,15 @@ namespace SLSFramework.General
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
public CommandContext Merge(CommandContext other)
|
||||
{
|
||||
foreach (var pair in other.context)
|
||||
{
|
||||
this.context[pair.Key] = pair.Value;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public T GetInfo<T>(string key)
|
||||
{
|
||||
@@ -50,6 +61,8 @@ namespace SLSFramework.General
|
||||
{
|
||||
return typedValue;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"CommandContext 中不存在键 '{key}',或其类型不匹配。返回默认值。");
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,23 @@ namespace SLSFramework.General
|
||||
{
|
||||
public readonly List<CommandBase> commands = new List<CommandBase>();
|
||||
public readonly ExecutionMode mode;
|
||||
|
||||
/// <summary>
|
||||
/// 包含了指令组执行过程中产生的所有上下文信息。不论是内部还是外部的上下文皆可获取。
|
||||
/// </summary>
|
||||
public readonly CommandContext groupContext;
|
||||
|
||||
public CommandGroup(ExecutionMode mode, params CommandBase[] commands)
|
||||
{
|
||||
this.mode = mode;
|
||||
this.groupContext = new CommandContext();
|
||||
this.commands.AddRange(commands);
|
||||
}
|
||||
|
||||
public CommandGroup(ExecutionMode mode, CommandContext groupContext, params CommandBase[] commands)
|
||||
{
|
||||
this.mode = mode;
|
||||
this.groupContext = groupContext;
|
||||
this.commands.AddRange(commands);
|
||||
}
|
||||
|
||||
@@ -42,7 +55,13 @@ namespace SLSFramework.General
|
||||
// 而是创建一个“延迟执行”的 Observable 序列。
|
||||
// Defer 会将对 Execute 的调用推迟到 Concat/WhenAll 真正订阅它的时候。
|
||||
var lazyCommandObservables = commands.Select(cmd =>
|
||||
Observable.Defer(() => cmd.Execute(outerContext))
|
||||
Observable.Defer(() =>
|
||||
{
|
||||
IObservable<Unit> result = cmd.Execute(outerContext);
|
||||
groupContext.Merge(outerContext);
|
||||
groupContext.Merge(cmd.selfContext);
|
||||
return result;
|
||||
})
|
||||
);
|
||||
|
||||
IObservable<Unit> executionFlow;
|
||||
@@ -58,6 +77,7 @@ namespace SLSFramework.General
|
||||
executionFlow = Observable.WhenAll(lazyCommandObservables).AsUnitObservable();
|
||||
}
|
||||
|
||||
|
||||
return executionFlow;
|
||||
// 注意:基类中的 TakeUntil(forceCompleteSubject) 会自动应用到这里返回的流上,所以无需重复添加。
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace SLSFramework.General
|
||||
*/
|
||||
}
|
||||
|
||||
public void AddCommand(CommandBase command, CommandContext context = null)
|
||||
public CommandBase AddCommand(CommandBase command, CommandContext context = null)
|
||||
{
|
||||
context ??= new CommandContext();
|
||||
// 将指令和其上下文入队
|
||||
@@ -80,6 +80,8 @@ namespace SLSFramework.General
|
||||
// 如果队列当前不忙,这个调用会立即开始处理我们刚刚添加的指令。
|
||||
// 如果队列正忙,这个调用什么也不做,因为当前指令完成后会自动处理下一个。
|
||||
ProcessNextInQueue();
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -123,18 +123,4 @@ namespace SLSFramework.General
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实现该接口的类可以根据优先级进行比较和排序。
|
||||
/// 数字越大优先级越高。
|
||||
/// </summary>
|
||||
public interface IPrioritized : IComparable<IPrioritized>
|
||||
{
|
||||
int Priority { get; }
|
||||
|
||||
int IComparable<IPrioritized>.CompareTo(IPrioritized other)
|
||||
{
|
||||
return other.Priority.CompareTo(Priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/Scripts/ScriptExtensions/General/IPrioritized.cs
Normal file
18
Assets/Scripts/ScriptExtensions/General/IPrioritized.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace SLSFramework.General
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现该接口的类可以根据优先级进行比较和排序。
|
||||
/// 数字越大优先级越高。
|
||||
/// </summary>
|
||||
public interface IPrioritized : IComparable<IPrioritized>
|
||||
{
|
||||
int Priority { get; }
|
||||
|
||||
int IComparable<IPrioritized>.CompareTo(IPrioritized other)
|
||||
{
|
||||
return other.Priority.CompareTo(Priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84b1c40e60420ad47b31aef43bc98901
|
||||
@@ -6,7 +6,7 @@ using Random = UnityEngine.Random;
|
||||
|
||||
namespace SLSFramework.General
|
||||
{
|
||||
public static class ListExtension
|
||||
public static partial class ListExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 对列表中的每个元素执行指定的操作
|
||||
@@ -116,4 +116,44 @@ namespace SLSFramework.General
|
||||
return filters.All(filter => filter(item));
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class ListExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据优先级将新项插入到已排序的列表中,保持列表按优先级从高到低排序(二分查找)。
|
||||
/// 数字越大优先级越高。
|
||||
/// </summary>
|
||||
public static void AddByPriority<T>(this List<T> list, T newItem) where T : IPrioritized
|
||||
{
|
||||
// 优化:检查是否可以直接添加到末尾
|
||||
if (list.Count == 0 || newItem.Priority <= list[list.Count - 1].Priority)
|
||||
{
|
||||
list.Add(newItem);
|
||||
return;
|
||||
}
|
||||
|
||||
int low = 0;
|
||||
int high = list.Count;
|
||||
|
||||
while (low < high)
|
||||
{
|
||||
int mid = low + (high - low) / 2;
|
||||
|
||||
// 规则:数字越大,优先级越高,越靠前
|
||||
// 如果中间项的优先级 >= 新项的优先级,
|
||||
// 说明新项应该在它后面
|
||||
if (list[mid].Priority >= newItem.Priority)
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 中间项的优先级 < 新项,说明新项应该在它前面(或就是这个位置)
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
|
||||
list.Insert(low, newItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace SLSFramework.UModAssistance
|
||||
/// <param name="namespaceToRemove">可选参数,用于从路径中移除特定的命名空间部分 (例如 ".Cards")</param>
|
||||
/// <returns>如果值被用户改变,则返回true</returns>
|
||||
protected bool DrawTypeSelectorGUI(SerializedProperty classNameProp, string label, Type baseType,
|
||||
string namespacePrefix = null, string namespaceToRemove = null)
|
||||
out Type returnedType, string namespacePrefix = null, string namespaceToRemove = null)
|
||||
{
|
||||
// --- 核心修改 2:使用包含 namespaceToRemove 的复合键 ---
|
||||
var cacheKey = new Tuple<Type, string>(baseType, namespaceToRemove ?? string.Empty);
|
||||
@@ -179,9 +179,12 @@ namespace SLSFramework.UModAssistance
|
||||
classNameProp.stringValue = (newIndex >= 0 && newIndex < types.Length)
|
||||
? types[newIndex].Name
|
||||
: string.Empty;
|
||||
|
||||
returnedType = types[newIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
returnedType = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace SLSFramework.UModAssistance
|
||||
ModManager.RegisterTypesFromMod(host, typeof(CharacterBase));
|
||||
ModManager.RegisterTypesFromMod(host, typeof(CardLogicBase));
|
||||
ModManager.RegisterTypesFromMod(host, typeof(EquipmentBase));
|
||||
ModManager.RegisterTypesFromMod(host,typeof(Continentis.MainGame.Card.CombatBuffBase));
|
||||
ModManager.RegisterTypesFromMod(host,typeof(Continentis.MainGame.Character.CombatBuffBase));
|
||||
ModManager.RegisterTypesFromMod(host,typeof(CardCombatBuffBase));
|
||||
ModManager.RegisterTypesFromMod(host,typeof(CharacterCombatBuffBase));
|
||||
ModManager.RegisterTypesFromMod(host, typeof(RulesCollectionBase));
|
||||
|
||||
string manifestName = host.CurrentMod.NameInfo.ModName + "_Manifest";
|
||||
|
||||
@@ -27,6 +27,18 @@ namespace SLSFramework.UModAssistance
|
||||
{
|
||||
public static readonly SerializableDictionary<string, ModHost> LoadedMods = new SerializableDictionary<string, ModHost>();
|
||||
public static readonly Dictionary<Type, Dictionary<string, ScriptableObject>> Database = new Dictionary<Type, Dictionary<string, ScriptableObject>>();
|
||||
|
||||
/// <summary>
|
||||
/// Get the standardized class name for a mod class, combining its class name and mod name.
|
||||
/// Format: "ModName_ClassName"
|
||||
/// </summary>
|
||||
public static string GetModClassName(Type type)
|
||||
{
|
||||
string modName = type.Namespace!.Replace("Continentis.Mods.", "").Split('.')[0];
|
||||
string className = type.Name;
|
||||
return $"{modName}_{className}";
|
||||
}
|
||||
|
||||
public static bool IsValidAssetName(string assetName) => Regex.IsMatch(assetName, @"^\w+_\w+_.+$");
|
||||
|
||||
/// <summary>
|
||||
@@ -120,6 +132,15 @@ namespace SLSFramework.UModAssistance
|
||||
public partial class ModManager
|
||||
{
|
||||
public static readonly Dictionary<string, Type> TypeRegistry = new Dictionary<string, Type>();
|
||||
public static string GetTypeID(Type type)
|
||||
{
|
||||
return type.Namespace!.Replace("Continentis.Mods.", "") + "." + type.Name;
|
||||
}
|
||||
|
||||
public static string GetTypeID(string modName, string classification, string className)
|
||||
{
|
||||
return $"{modName}.{classification}.{className}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从一个已加载的Mod中,查找所有指定基类的子类,并将其注册到全局字典中。
|
||||
@@ -144,15 +165,16 @@ namespace SLSFramework.UModAssistance
|
||||
|
||||
foreach (var type in typesInAssembly)
|
||||
{
|
||||
if (!TypeRegistry.ContainsKey(type.Name))
|
||||
string typeID = GetTypeID(type);
|
||||
|
||||
if (TypeRegistry.TryAdd(typeID, type))
|
||||
{
|
||||
TypeRegistry.Add(type.Name, type);
|
||||
Debug.Log($"Registered script type '{type.FullName}' from mod '{host.CurrentMod.NameInfo.ModName}'.");
|
||||
Debug.Log($"Registered script type '{typeID}' from mod '{host.CurrentMod.NameInfo.ModName}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 处理命名冲突:如果不同Mod中存在同名的类,后加载的会被忽略
|
||||
Debug.LogWarning($"Duplicate script type name found: '{type.Name}'. The existing type from assembly '{TypeRegistry[type.Name].Assembly.FullName}' will be kept.");
|
||||
Debug.LogWarning($"Duplicate script type name found: '{typeID}'. The existing type from assembly '{TypeRegistry[type.Name].Assembly.FullName}' will be kept.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,13 +186,13 @@ namespace SLSFramework.UModAssistance
|
||||
}
|
||||
}
|
||||
|
||||
public static Type GetType(string typeName)
|
||||
public static Type GetType(string typeID)
|
||||
{
|
||||
if (TypeRegistry.TryGetValue(typeName, out Type type))
|
||||
if (TypeRegistry.TryGetValue(typeID, out Type type))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
Debug.LogWarning($"Type '{typeName}' not found in TypeRegistry.");
|
||||
Debug.LogWarning($"Type '{typeID}' not found in TypeRegistry.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user