PkmnLib.NET/PkmnLib.Dynamic/ScriptHandling/ScriptSet.cs

162 lines
4.7 KiB
C#
Raw Normal View History

2024-07-28 12:00:26 +00:00
using System.Collections;
2024-12-22 10:24:01 +00:00
using PkmnLib.Dynamic.ScriptHandling.Registry;
2024-07-28 10:52:17 +00:00
using PkmnLib.Static.Utils;
2024-07-27 14:26:45 +00:00
namespace PkmnLib.Dynamic.ScriptHandling;
2024-07-28 10:52:17 +00:00
/// <summary>
/// A script set is a collection of scripts that can be accessed by a key.
/// We can add, remove, and clear scripts from the set.
/// This is generally used for volatile scripts.
/// </summary>
2024-07-27 14:26:45 +00:00
public interface IScriptSet : IEnumerable<ScriptContainer>
{
2024-07-28 10:52:17 +00:00
/// <summary>
/// Adds a script to the set. If the script with that name already exists in this set, this
/// makes that script stack instead. The return value here is that script.
/// </summary>
ScriptContainer Add(Script script);
/// <summary>
/// Adds a script with a name to the set. If the script with that name already exists in this
/// set, this makes that script stack instead. The return value here is that script.
/// </summary>
2024-07-28 12:00:26 +00:00
ScriptContainer? StackOrAdd(StringKey scriptKey, Func<Script> instantiation);
2024-07-28 10:52:17 +00:00
/// <summary>
/// Gets a script from the set using its unique name.
/// </summary>
ScriptContainer? Get(StringKey scriptKey);
2024-12-22 10:24:01 +00:00
/// <summary>
/// Gets a script from the set using its type.
/// </summary>
T? Get<T>() where T : Script;
2025-01-26 10:55:13 +00:00
2024-07-28 10:52:17 +00:00
/// <summary>
/// Removes a script from the set using its unique name.
/// </summary>
void Remove(StringKey scriptKey);
/// <summary>
/// Clears all scripts from the set.
/// </summary>
2024-07-27 14:26:45 +00:00
void Clear();
2024-07-28 10:52:17 +00:00
2025-01-26 10:55:13 +00:00
/// <summary>
/// Checks if the set has a script with the given type.
/// </summary>
bool Contains<T>() where T : Script => Contains(ScriptUtils.ResolveName<T>());
2024-07-28 10:52:17 +00:00
/// <summary>
/// Checks if the set has a script with the given name.
/// </summary>
2024-07-28 12:00:26 +00:00
bool Contains(StringKey scriptKey);
2024-07-28 10:52:17 +00:00
/// <summary>
/// Gets a script from the set at a specific index.
/// </summary>
2024-07-27 14:26:45 +00:00
ScriptContainer At(int index);
2024-07-28 10:52:17 +00:00
/// <summary>
/// Gets the number of scripts in the set.
/// </summary>
2024-07-27 14:26:45 +00:00
int Count { get; }
2024-07-28 10:52:17 +00:00
/// <summary>
/// Gets the names of all scripts in the set.
/// </summary>
IEnumerable<StringKey> GetScriptNames();
2024-07-28 12:00:26 +00:00
}
/// <inheritdoc cref="IScriptSet"/>
public class ScriptSet : IScriptSet
{
private readonly List<ScriptContainer> _scripts = [];
/// <inheritdoc />
public IEnumerator<ScriptContainer> GetEnumerator() => _scripts.GetEnumerator();
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <inheritdoc />
public ScriptContainer Add(Script script)
{
var existing = _scripts.FirstOrDefault(s => s.Script?.Name == script.Name);
if (existing != null)
{
existing.Script!.Stack();
return existing;
}
2024-11-02 11:59:55 +00:00
script.OnRemoveEvent += s => Remove(s.Name);
2024-07-28 12:00:26 +00:00
var container = new ScriptContainer(script);
_scripts.Add(container);
return container;
}
/// <inheritdoc />
public ScriptContainer? StackOrAdd(StringKey scriptKey, Func<Script?> instantiation)
{
var existing = _scripts.FirstOrDefault(s => s.Script?.Name == scriptKey);
if (existing != null)
{
existing.Script!.Stack();
return existing;
}
var script = instantiation();
if (script is null)
return null;
2024-11-02 11:59:55 +00:00
script.OnRemoveEvent += s => Remove(s.Name);
2024-07-28 12:00:26 +00:00
var container = new ScriptContainer(script);
_scripts.Add(container);
return container;
}
/// <inheritdoc />
public ScriptContainer? Get(StringKey scriptKey) => _scripts.FirstOrDefault(s => s.Script?.Name == scriptKey);
2024-12-22 10:24:01 +00:00
/// <inheritdoc />
public T? Get<T>() where T : Script => Get(ScriptUtils.ResolveName<T>())?.Script as T;
2024-07-28 12:00:26 +00:00
/// <inheritdoc />
public void Remove(StringKey scriptKey)
{
var script = _scripts.FirstOrDefault(s => s.Script?.Name == scriptKey);
if (script is null)
return;
2024-11-02 11:59:55 +00:00
script.Script?.OnRemove();
2024-07-28 12:00:26 +00:00
_scripts.Remove(script);
}
/// <inheritdoc />
public void Clear()
{
foreach (var script in _scripts)
{
if (!script.IsEmpty)
{
script.Script.OnRemove();
}
}
_scripts.Clear();
}
2024-07-28 12:00:26 +00:00
/// <inheritdoc />
public bool Contains(StringKey scriptKey) => _scripts.Any(s => s.Script?.Name == scriptKey);
/// <inheritdoc />
public ScriptContainer At(int index) => _scripts[index];
/// <inheritdoc />
public int Count => _scripts.Count;
/// <inheritdoc />
public IEnumerable<StringKey> GetScriptNames() =>
_scripts
.Select(x => x.Script)
.WhereNotNull()
.Select(s => s.Name);
2024-07-27 14:26:45 +00:00
}