documents

This commit is contained in:
h z
2025-07-15 00:15:56 +01:00
parent c3b57d84a6
commit 6640b9613f
11 changed files with 290 additions and 10 deletions

View File

@@ -3,10 +3,21 @@ using Polonium.Resources;
namespace Polonium.Agents; namespace Polonium.Agents;
/// <summary>
/// Abstract base class for managing a collection of agent actions.
/// Provides functionality to store and learn action templates.
/// </summary>
public abstract partial class ActionSet : Node public abstract partial class ActionSet : Node
{ {
/// <summary>
/// Gets or sets the collection of action templates available to this action set.
/// </summary>
public HashSet<AgentAction.Template> Templates { get; set; } = new(); public HashSet<AgentAction.Template> Templates { get; set; } = new();
/// <summary>
/// Learns a new action template by adding it to the templates collection.
/// </summary>
/// <param name="template">The action template to learn.</param>
public virtual void Learn(AgentAction.Template template) => Templates.Add(template); public virtual void Learn(AgentAction.Template template) => Templates.Add(template);
} }

View File

@@ -3,17 +3,34 @@ using Polonium.Resources;
namespace Polonium.Agents; namespace Polonium.Agents;
/// <summary>
/// Abstract base class for all agents in the AI system.
/// Provides knowledge management and action execution capabilities.
/// </summary>
public abstract partial class Agent : Node public abstract partial class Agent : Node
{ {
/// <summary>
/// Gets or sets the knowledge component that manages the agent's information state.
/// </summary>
public Knowledge Knowledge { get; set; } public Knowledge Knowledge { get; set; }
/// <summary>
/// Gets or sets the action set that defines the available actions for this agent.
/// </summary>
public ActionSet ActionSet { get; set; } public ActionSet ActionSet { get; set; }
/// <summary>
/// Virtual method called during agent initialization. Override to provide custom initialization logic.
/// </summary>
public virtual void __Ready() public virtual void __Ready()
{ {
} }
/// <summary>
/// Initializes the agent by setting up knowledge and action set components.
/// This method is sealed to ensure consistent initialization behavior.
/// </summary>
public sealed override void _Ready() public sealed override void _Ready()
{ {
Knowledge = GetNode<Knowledge>("Knowledge"); Knowledge = GetNode<Knowledge>("Knowledge");
@@ -22,6 +39,11 @@ public abstract partial class Agent : Node
base._Ready(); base._Ready();
} }
/// <summary>
/// Executes a specific action with the given parameters.
/// </summary>
/// <typeparam name="TAction">The type of action to execute.</typeparam>
/// <param name="parameter">The parameters for the action.</param>
public void Act<TAction>(AgentAction.Parameter parameter) public void Act<TAction>(AgentAction.Parameter parameter)
where TAction : AgentAction where TAction : AgentAction
{ {
@@ -33,6 +55,4 @@ public abstract partial class Agent : Node
act.SetParameter(parameter); act.SetParameter(parameter);
act.Execute(); act.Execute();
} }
} }

View File

@@ -2,33 +2,73 @@ using Godot;
namespace Polonium.Agents; namespace Polonium.Agents;
/// <summary>
/// Abstract base class for all agent actions in the system.
/// Provides the foundation for executable actions that can be performed by agents.
/// </summary>
public abstract partial class AgentAction : Node public abstract partial class AgentAction : Node
{ {
/// <summary>
/// Abstract base class for action parameters.
/// </summary>
public abstract class Parameter public abstract class Parameter
{ {
} }
/// <summary>
/// Sets the parameter for this action.
/// </summary>
/// <param name="p">The parameter to set.</param>
public virtual void SetParameter(Parameter p) public virtual void SetParameter(Parameter p)
{ {
} }
/// <summary>
/// Executes the action logic.
/// </summary>
public abstract void Execute(); public abstract void Execute();
/// <summary>
/// Finishes the action execution and performs cleanup.
/// </summary>
public abstract void Finish(); public abstract void Finish();
/// <summary>
/// Resets the action to its initial state.
/// </summary>
public abstract void Reset(); public abstract void Reset();
/// <summary>
/// Abstract base class for agent action templates.
/// </summary>
public abstract class Template : PoloniumTemplate<AgentAction> public abstract class Template : PoloniumTemplate<AgentAction>
{ {
/// <summary>
/// Gets the name of the action.
/// </summary>
public abstract string ActionName { get; } public abstract string ActionName { get; }
/// <summary>
/// Gets a copy of this template.
/// </summary>
public abstract Template Copy { get; } public abstract Template Copy { get; }
} }
/// <summary>
/// Generic template class for specific agent action types.
/// </summary>
/// <typeparam name="TAction">The type of agent action.</typeparam>
public class Template<TAction> : Template public class Template<TAction> : Template
where TAction : AgentAction where TAction : AgentAction
{ {
/// <summary>
/// Gets the name of the action from the registry.
/// </summary>
public override string ActionName => PoloniumRegistry.Action<TAction>.Name; public override string ActionName => PoloniumRegistry.Action<TAction>.Name;
/// <summary>
/// Gets an instance of the action from the registry, resets it, and applies modifications.
/// </summary>
public override TAction Get public override TAction Get
{ {
get get
@@ -40,6 +80,10 @@ public abstract partial class AgentAction : Node
} }
} }
/// <summary>
/// Modifies the given agent action object if it's of the correct type.
/// </summary>
/// <param name="obj">The agent action object to modify.</param>
public override void Modify(AgentAction obj) public override void Modify(AgentAction obj)
{ {
if (obj is not TAction act) if (obj is not TAction act)
@@ -47,10 +91,21 @@ public abstract partial class AgentAction : Node
Modify(act); Modify(act);
} }
/// <summary>
/// Returns the action instance to the registry for reuse.
/// </summary>
/// <param name="res">The action instance to return.</param>
public void Return(TAction res) => PoloniumRegistry.Asset<TAction>.Return(res); public void Return(TAction res) => PoloniumRegistry.Asset<TAction>.Return(res);
/// <summary>
/// Gets a copy of this template.
/// </summary>
public override Template Copy => new Template<TAction> { }; public override Template Copy => new Template<TAction> { };
/// <summary>
/// Virtual method to modify the action instance. Override to customize behavior.
/// </summary>
/// <param name="action">The action instance to modify.</param>
public virtual void Modify(TAction action) public virtual void Modify(TAction action)
{ {
} }

View File

@@ -1,4 +1,10 @@
namespace Polonium.Attributes; namespace Polonium.Attributes;
/// <summary>
/// Attribute that marks an interface for automatic patch class generation.
/// When applied to an interface containing a single property marked with <see cref="PatchableProperty"/>,
/// the source generator will create a corresponding patch class for updating implementations.
/// </summary>
[AttributeUsage(AttributeTargets.Interface)] [AttributeUsage(AttributeTargets.Interface)]
public class AutoPatch : Attribute public class AutoPatch : Attribute
{ {

View File

@@ -1,4 +1,10 @@
namespace Polonium.Attributes; namespace Polonium.Attributes;
/// <summary>
/// Attribute that marks a class for automatic registry property generation.
/// When applied to a class, the source generator will create a corresponding property
/// in the GlobalRegistry for easy, game-wide access to instances of this class.
/// </summary>
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]
public class RegistryEntity : Attribute public class RegistryEntity : Attribute
{ {

View File

@@ -3,8 +3,16 @@ using FileAccess = Godot.FileAccess;
namespace Polonium.DataStructures; namespace Polonium.DataStructures;
/// <summary>
/// Represents a complete set of textures for UI button states.
/// Automatically loads textures for Normal, Pressed, Disabled, Hover, and Focused states from a directory.
/// </summary>
public class TextureSet public class TextureSet
{ {
/// <summary>
/// Initializes a new instance of the <see cref="TextureSet"/> class by loading textures from the specified path.
/// </summary>
/// <param name="path">The base path where texture files are located.</param>
public TextureSet(string path) public TextureSet(string path)
{ {
Normal = LoadTexture($"{path}/Normal"); Normal = LoadTexture($"{path}/Normal");
@@ -13,12 +21,37 @@ public class TextureSet
Hover = LoadTexture($"{path}/Hover"); Hover = LoadTexture($"{path}/Hover");
Focused = LoadTexture($"{path}/Focused"); Focused = LoadTexture($"{path}/Focused");
} }
/// <summary>
/// Gets the texture for the normal button state.
/// </summary>
public Texture2D Normal { get; init; } public Texture2D Normal { get; init; }
/// <summary>
/// Gets the texture for the pressed button state.
/// </summary>
public Texture2D Pressed { get; init; } public Texture2D Pressed { get; init; }
/// <summary>
/// Gets the texture for the hover button state.
/// </summary>
public Texture2D Hover { get; init; } public Texture2D Hover { get; init; }
/// <summary>
/// Gets the texture for the disabled button state.
/// </summary>
public Texture2D Disabled { get; init; } public Texture2D Disabled { get; init; }
/// <summary>
/// Gets the texture for the focused button state.
/// </summary>
public Texture2D Focused { get; init; } public Texture2D Focused { get; init; }
/// <summary>
/// Loads a texture from the specified path, supporting both static PNG files and animated texture directories.
/// </summary>
/// <param name="path">The path to the texture file or directory.</param>
/// <returns>The loaded texture, or an empty texture if not found.</returns>
private static Texture2D LoadTexture(string path) private static Texture2D LoadTexture(string path)
{ {
Texture2D res = new(); Texture2D res = new();
@@ -28,6 +61,4 @@ public class TextureSet
res = Utils.LoadAnimatedTextureFromDirectory($"{path}.at_dir"); res = Utils.LoadAnimatedTextureFromDirectory($"{path}.at_dir");
return res; return res;
} }
} }

View File

@@ -1,8 +1,22 @@
namespace Polonium.Interfaces; namespace Polonium.Interfaces;
/// <summary>
/// Interface for global registry implementations that manage application-wide state and lifecycle.
/// </summary>
public interface IGlobalRegistry public interface IGlobalRegistry
{ {
/// <summary>
/// Gets or sets a value indicating whether the registry is in a paused state.
/// </summary>
public bool Paused { get; set; } public bool Paused { get; set; }
/// <summary>
/// Starts the registry and begins processing.
/// </summary>
public void Start(); public void Start();
/// <summary>
/// Prepares the registry for operation, initializing necessary resources.
/// </summary>
public void Prepare(); public void Prepare();
} }

View File

@@ -3,13 +3,36 @@ using Polonium.MessageManager;
namespace Polonium.Interfaces; namespace Polonium.Interfaces;
/// <summary>
/// Interface for message clients that can send and receive messages through the message bus.
/// </summary>
public interface IMessageClient public interface IMessageClient
{ {
/// <summary>
/// Gets or sets the post code used for message routing.
/// </summary>
string PostCode { get; set; } string PostCode { get; set; }
/// <summary>
/// Receives a message from the message bus.
/// </summary>
/// <param name="msg">The message to receive.</param>
void ReceiveMessage(PoloniumMessage msg); void ReceiveMessage(PoloniumMessage msg);
/// <summary>
/// Delegate for message sent events.
/// </summary>
/// <param name="msg">The message that was sent.</param>
delegate void MessageSentEventHandler(PoloniumMessage msg); delegate void MessageSentEventHandler(PoloniumMessage msg);
/// <summary>
/// Event raised when a message is sent by this client.
/// </summary>
event MessageSentEventHandler MessageSent; event MessageSentEventHandler MessageSent;
/// <summary>
/// Sends a message through the message bus.
/// </summary>
/// <param name="msg">The message to send.</param>
public void SendMessage(PoloniumMessage msg); public void SendMessage(PoloniumMessage msg);
} }

View File

@@ -3,12 +3,27 @@ using Polonium.Interfaces;
namespace Polonium.MessageManager; namespace Polonium.MessageManager;
/// <summary>
/// Abstract base class for message bus implementations that handle publish-subscribe communication.
/// Manages message clients, routes messages, and handles delivery failures with retry logic.
/// </summary>
public abstract partial class MessageBus : Node public abstract partial class MessageBus : Node
{ {
/// <summary>
/// Dictionary mapping post codes to sets of message clients.
/// </summary>
public Dictionary<string, HashSet<IMessageClient>> Clients { get; } = new(); public Dictionary<string, HashSet<IMessageClient>> Clients { get; } = new();
/// <summary>
/// Generates a new unique post code for message routing.
/// </summary>
/// <returns>A unique post code string.</returns>
public abstract string NewPostCode(); public abstract string NewPostCode();
/// <summary>
/// Registers a message client with the bus and subscribes to its message events.
/// </summary>
/// <param name="client">The message client to register.</param>
public void Register(IMessageClient client) public void Register(IMessageClient client)
{ {
if(!Clients.ContainsKey(client.PostCode)) if(!Clients.ContainsKey(client.PostCode))
@@ -16,16 +31,37 @@ public abstract partial class MessageBus : Node
Clients[client.PostCode].Add(client); Clients[client.PostCode].Add(client);
client.MessageSent += Collect; client.MessageSent += Collect;
} }
/// <summary>
/// Queue of messages waiting to be processed.
/// </summary>
public Queue<PoloniumMessage> Messages { get; } = new(); public Queue<PoloniumMessage> Messages { get; } = new();
/// <summary>
/// Queue of messages that failed delivery and need to be retried.
/// </summary>
public Queue<PoloniumMessage> DeadMessages { get; } = new(); public Queue<PoloniumMessage> DeadMessages { get; } = new();
/// <summary>
/// Collects a message into the processing queue.
/// </summary>
/// <param name="message">The message to collect.</param>
public void Collect(PoloniumMessage message) => Messages.Enqueue(message); public void Collect(PoloniumMessage message) => Messages.Enqueue(message);
/// <summary>
/// Initializes the message bus and registers it with the PoloniumRegistry.
/// </summary>
public override void _Ready() public override void _Ready()
{ {
PoloniumRegistry.Instance.MessageBus = this; PoloniumRegistry.Instance.MessageBus = this;
base._Ready(); base._Ready();
} }
/// <summary>
/// Processes messages from the queue, delivering them to registered clients.
/// Handles delivery failures and implements retry logic.
/// </summary>
/// <param name="delta">The time elapsed since the last frame.</param>
public override void _Process(double delta) public override void _Process(double delta)
{ {
if(DeadMessages.Count > 0) if(DeadMessages.Count > 0)

View File

@@ -7,60 +7,140 @@ using Polonium.Resources;
namespace Polonium; namespace Polonium;
/// <summary>
/// Central registry for managing global state, resources, and shared objects in the Polonium framework.
/// Provides singleton access to configuration, saves, agents, and asset management systems.
/// </summary>
public class PoloniumRegistry public class PoloniumRegistry
{ {
/// <summary>
/// Internal singleton instance holder.
/// </summary>
private static PoloniumRegistry InternalInstance { get; set; } private static PoloniumRegistry InternalInstance { get; set; }
/// <summary>
/// Gets the singleton instance of the PoloniumRegistry.
/// </summary>
public static PoloniumRegistry Instance => InternalInstance ??= new PoloniumRegistry(); public static PoloniumRegistry Instance => InternalInstance ??= new PoloniumRegistry();
/// <summary>
/// Global configuration settings for the application.
/// </summary>
[RegistryPassThrough] [RegistryPassThrough]
public Config Config { get; set; } public Config Config { get; set; }
/// <summary>
/// Global save data for the application.
/// </summary>
[RegistryPassThrough] [RegistryPassThrough]
public Save Save { get; set; } public Save Save { get; set; }
/// <summary>
/// The currently active world in the agent system.
/// </summary>
[RegistryPassThrough] [RegistryPassThrough]
public World CurrentWorld { get; set; } public World CurrentWorld { get; set; }
/// <summary>
/// Factory for creating Polonium-specific objects.
/// </summary>
[RegistryPassThrough] [RegistryPassThrough]
public IPoloniumFactory PoloniumFactory { get; set; } public IPoloniumFactory PoloniumFactory { get; set; }
/// <summary>
/// Message bus for pub-sub communication between components.
/// </summary>
[RegistryPassThrough] [RegistryPassThrough]
public MessageBus MessageBus { get; set; } public MessageBus MessageBus { get; set; }
/// <summary>
/// Prepares the registry by creating necessary directories and initializing resources.
/// </summary>
public static void Prepare() public static void Prepare()
{ {
DirAccess.MakeDirAbsolute("user://saves"); DirAccess.MakeDirAbsolute("user://saves");
} }
/// <summary>
/// Collection of all registered agents in the system.
/// </summary>
// ReSharper disable once CollectionNeverQueried.Global // ReSharper disable once CollectionNeverQueried.Global
[RegistryPassThrough(true)] [RegistryPassThrough(true)]
public Dictionary<string, Agent> Agents { get; } = new(); public Dictionary<string, Agent> Agents { get; } = new();
/// <summary>
/// Collection of all objects that consume time in the system.
/// </summary>
// ReSharper disable once CollectionNeverQueried.Global // ReSharper disable once CollectionNeverQueried.Global
[RegistryPassThrough(true)] [RegistryPassThrough(true)]
public HashSet<ITimeConsumer> TimeConsumers { get; } = new(); public HashSet<ITimeConsumer> TimeConsumers { get; } = new();
/// <summary>
/// Generic registry for agent actions, providing type-safe access to action names.
/// </summary>
/// <typeparam name="TAction">The type of agent action.</typeparam>
public static class Action<TAction> public static class Action<TAction>
where TAction : AgentAction where TAction : AgentAction
{ {
/// <summary>
/// Gets or sets the name of the action type.
/// </summary>
// ReSharper disable once StaticMemberInGenericType // ReSharper disable once StaticMemberInGenericType
public static string Name { get; set; } public static string Name { get; set; }
} }
/// <summary>
/// Generic registry for skin palette management, providing color mapping and palette roots.
/// </summary>
/// <typeparam name="TSkin">The type of skin.</typeparam>
public static class SkinRegistry<TSkin> public static class SkinRegistry<TSkin>
where TSkin : Polonium.SkinManagers.Skin where TSkin : Polonium.SkinManagers.Skin
{ {
/// <summary>
/// Gets or sets the root colors for the palette.
/// </summary>
// ReSharper disable once StaticMemberInGenericType // ReSharper disable once StaticMemberInGenericType
public static Color[] PaletteRoots { get; set; } public static Color[] PaletteRoots { get; set; }
/// <summary>
/// Gets or sets the color mapping dictionary for palette transformations.
/// </summary>
// ReSharper disable once StaticMemberInGenericType // ReSharper disable once StaticMemberInGenericType
public static Dictionary<Color, Color[]> PaletteMap { get; set; } public static Dictionary<Color, Color[]> PaletteMap { get; set; }
} }
/// <summary>
/// Generic asset registry providing pooled instantiation and management of Godot nodes.
/// </summary>
/// <typeparam name="TAsset">The type of node asset.</typeparam>
public static class Asset<TAsset> public static class Asset<TAsset>
where TAsset : Node where TAsset : Node
{ {
/// <summary>
/// Object pool for reusing instances to improve performance.
/// </summary>
private static readonly Queue<TAsset> Pool = new(); private static readonly Queue<TAsset> Pool = new();
/// <summary>
/// Gets or sets the packed scene for instantiation.
/// </summary>
public static PackedScene Scene { get; set; } public static PackedScene Scene { get; set; }
/// <summary>
/// Creates a new instance of the asset from the scene.
/// </summary>
private static TAsset Instance => Scene.Instantiate<TAsset>(); private static TAsset Instance => Scene.Instantiate<TAsset>();
/// <summary>
/// Gets an instance from the pool or creates a new one if the pool is empty.
/// </summary>
/// <returns>An instance of the asset.</returns>
public static TAsset Get() => Pool.Count > 0 ? Pool.Dequeue() : Instance; public static TAsset Get() => Pool.Count > 0 ? Pool.Dequeue() : Instance;
/// <summary>
/// Returns an asset instance to the pool for reuse or frees it if the pool is full.
/// </summary>
/// <param name="asset">The asset instance to return.</param>
public static void Return(TAsset asset) public static void Return(TAsset asset)
{ {
if (Pool.Count < 10) if (Pool.Count < 10)

View File

@@ -38,6 +38,4 @@ public abstract partial class SkinPacker : Node2D
SyncPlayer = GetNode<AnimationPlayer>("AnimationPlayer"); SyncPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
SkinCollector = GetNode<Node2D>("SkinCollector"); SkinCollector = GetNode<Node2D>("SkinCollector");
} }
} }