Initial set up for item use

This commit is contained in:
2025-01-10 11:11:50 +01:00
parent 85ea31f7cd
commit 0518499a4c
23 changed files with 305 additions and 59 deletions

View File

@@ -0,0 +1,20 @@
using JetBrains.Annotations;
using PkmnLib.Static.Utils;
namespace PkmnLib.Dynamic.ScriptHandling.Registry;
[AttributeUsage(AttributeTargets.Class)]
[MeansImplicitUse]
public class ItemScriptAttribute : Attribute
{
/// <summary>
/// The name of the script.
/// </summary>
public StringKey Name { get; }
/// <inheritdoc cref="ItemScriptAttribute"/>
public ItemScriptAttribute(string name)
{
Name = name;
}
}

View File

@@ -13,6 +13,7 @@ namespace PkmnLib.Dynamic.ScriptHandling.Registry;
public class ScriptRegistry
{
private readonly Dictionary<(ScriptCategory category, StringKey name), Func<Script>> _scriptTypes = new();
private readonly Dictionary<StringKey, Func<ItemScript>> _itemScriptTypes = new();
private IBattleStatCalculator? _battleStatCalculator;
private IDamageCalculator? _damageCalculator;
private IMiscLibrary? _miscLibrary;
@@ -32,6 +33,15 @@ public class ScriptRegistry
RegisterScriptType(attribute.Category, attribute.Name, type);
}
var itemBaseType = typeof(ItemScript);
foreach (var type in assembly.GetTypes().Where(t => itemBaseType.IsAssignableFrom(t)))
{
var attribute = type.GetCustomAttribute<ItemScriptAttribute>();
if (attribute == null)
continue;
RegisterItemScriptType(attribute.Name, type);
}
}
/// <summary>
@@ -52,6 +62,25 @@ public class ScriptRegistry
// This is more performant than using Activator.CreateInstance.
_scriptTypes[(category, name)] = Expression.Lambda<Func<Script>>(Expression.New(constructor)).Compile();
}
/// <summary>
/// Register an item script type with the given name.
/// </summary>
[PublicAPI]
public void RegisterItemScriptType(StringKey name, Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
var constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null, Type.EmptyTypes, null);
if (constructor == null)
throw new ArgumentException($"Type {type} does not have a parameterless constructor.");
// We create a lambda that creates a new instance of the script type.
// This is more performant than using Activator.CreateInstance.
_itemScriptTypes[name] = Expression.Lambda<Func<ItemScript>>(Expression.New(constructor)).Compile();
}
/// <summary>
/// Register a battle stat calculator.
@@ -71,7 +100,8 @@ public class ScriptRegistry
public void RegisterMiscLibrary<T>(T miscLibrary) where T : IMiscLibrary
=> _miscLibrary = miscLibrary;
internal Dictionary<(ScriptCategory category, StringKey name), Func<Script>> ScriptTypes => _scriptTypes;
internal IReadOnlyDictionary<(ScriptCategory category, StringKey name), Func<Script>> ScriptTypes => _scriptTypes;
internal IReadOnlyDictionary<StringKey, Func<ItemScript>> ItemScriptTypes => _itemScriptTypes;
internal IBattleStatCalculator? BattleStatCalculator => _battleStatCalculator;
internal IDamageCalculator? DamageCalculator => _damageCalculator;
internal IMiscLibrary? MiscLibrary => _miscLibrary;