This commit is contained in:
SoulliesOfficial
2025-10-24 09:11:22 -04:00
parent 61a397dd4c
commit 76157e3cb1
329 changed files with 8609 additions and 4549 deletions

View File

@@ -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;
}
}

View File

@@ -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) 会自动应用到这里返回的流上,所以无需重复添加。
}

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View 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);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 84b1c40e60420ad47b31aef43bc98901

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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";

View File

@@ -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;
}