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;
/// <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
{
/// <summary>
/// Gets or sets the collection of action templates available to this action set.
/// </summary>
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);
}

View File

@@ -3,17 +3,34 @@ using Polonium.Resources;
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
{
/// <summary>
/// Gets or sets the knowledge component that manages the agent's information state.
/// </summary>
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; }
/// <summary>
/// Virtual method called during agent initialization. Override to provide custom initialization logic.
/// </summary>
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()
{
Knowledge = GetNode<Knowledge>("Knowledge");
@@ -22,6 +39,11 @@ public abstract partial class Agent : Node
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)
where TAction : AgentAction
{
@@ -33,6 +55,4 @@ public abstract partial class Agent : Node
act.SetParameter(parameter);
act.Execute();
}
}

View File

@@ -2,33 +2,73 @@ using Godot;
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
{
/// <summary>
/// Abstract base class for action parameters.
/// </summary>
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)
{
}
/// <summary>
/// Executes the action logic.
/// </summary>
public abstract void Execute();
/// <summary>
/// Finishes the action execution and performs cleanup.
/// </summary>
public abstract void Finish();
/// <summary>
/// Resets the action to its initial state.
/// </summary>
public abstract void Reset();
/// <summary>
/// Abstract base class for agent action templates.
/// </summary>
public abstract class Template : PoloniumTemplate<AgentAction>
{
/// <summary>
/// Gets the name of the action.
/// </summary>
public abstract string ActionName { get; }
/// <summary>
/// Gets a copy of this template.
/// </summary>
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
where TAction : AgentAction
{
/// <summary>
/// Gets the name of the action from the registry.
/// </summary>
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
{
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)
{
if (obj is not TAction act)
@@ -47,10 +91,21 @@ public abstract partial class AgentAction : Node
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);
/// <summary>
/// Gets a copy of this template.
/// </summary>
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)
{
}

View File

@@ -1,4 +1,10 @@
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)]
public class AutoPatch : Attribute
{

View File

@@ -1,4 +1,10 @@
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)]
public class RegistryEntity : Attribute
{

View File

@@ -3,8 +3,16 @@ using FileAccess = Godot.FileAccess;
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
{
/// <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)
{
Normal = LoadTexture($"{path}/Normal");
@@ -13,12 +21,37 @@ public class TextureSet
Hover = LoadTexture($"{path}/Hover");
Focused = LoadTexture($"{path}/Focused");
}
/// <summary>
/// Gets the texture for the normal button state.
/// </summary>
public Texture2D Normal { get; init; }
/// <summary>
/// Gets the texture for the pressed button state.
/// </summary>
public Texture2D Pressed { get; init; }
/// <summary>
/// Gets the texture for the hover button state.
/// </summary>
public Texture2D Hover { get; init; }
/// <summary>
/// Gets the texture for the disabled button state.
/// </summary>
public Texture2D Disabled { get; init; }
/// <summary>
/// Gets the texture for the focused button state.
/// </summary>
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)
{
Texture2D res = new();
@@ -28,6 +61,4 @@ public class TextureSet
res = Utils.LoadAnimatedTextureFromDirectory($"{path}.at_dir");
return res;
}
}

View File

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

View File

@@ -3,13 +3,36 @@ using Polonium.MessageManager;
namespace Polonium.Interfaces;
/// <summary>
/// Interface for message clients that can send and receive messages through the message bus.
/// </summary>
public interface IMessageClient
{
/// <summary>
/// Gets or sets the post code used for message routing.
/// </summary>
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);
/// <summary>
/// Delegate for message sent events.
/// </summary>
/// <param name="msg">The message that was sent.</param>
delegate void MessageSentEventHandler(PoloniumMessage msg);
/// <summary>
/// Event raised when a message is sent by this client.
/// </summary>
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);
}

View File

@@ -3,12 +3,27 @@ using Polonium.Interfaces;
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
{
/// <summary>
/// Dictionary mapping post codes to sets of message clients.
/// </summary>
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();
/// <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)
{
if(!Clients.ContainsKey(client.PostCode))
@@ -16,16 +31,37 @@ public abstract partial class MessageBus : Node
Clients[client.PostCode].Add(client);
client.MessageSent += Collect;
}
/// <summary>
/// Queue of messages waiting to be processed.
/// </summary>
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();
/// <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);
/// <summary>
/// Initializes the message bus and registers it with the PoloniumRegistry.
/// </summary>
public override void _Ready()
{
PoloniumRegistry.Instance.MessageBus = this;
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)
{
if(DeadMessages.Count > 0)

View File

@@ -7,60 +7,140 @@ using Polonium.Resources;
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
{
/// <summary>
/// Internal singleton instance holder.
/// </summary>
private static PoloniumRegistry InternalInstance { get; set; }
/// <summary>
/// Gets the singleton instance of the PoloniumRegistry.
/// </summary>
public static PoloniumRegistry Instance => InternalInstance ??= new PoloniumRegistry();
/// <summary>
/// Global configuration settings for the application.
/// </summary>
[RegistryPassThrough]
public Config Config { get; set; }
/// <summary>
/// Global save data for the application.
/// </summary>
[RegistryPassThrough]
public Save Save { get; set; }
/// <summary>
/// The currently active world in the agent system.
/// </summary>
[RegistryPassThrough]
public World CurrentWorld { get; set; }
/// <summary>
/// Factory for creating Polonium-specific objects.
/// </summary>
[RegistryPassThrough]
public IPoloniumFactory PoloniumFactory { get; set; }
/// <summary>
/// Message bus for pub-sub communication between components.
/// </summary>
[RegistryPassThrough]
public MessageBus MessageBus { get; set; }
/// <summary>
/// Prepares the registry by creating necessary directories and initializing resources.
/// </summary>
public static void Prepare()
{
DirAccess.MakeDirAbsolute("user://saves");
}
/// <summary>
/// Collection of all registered agents in the system.
/// </summary>
// ReSharper disable once CollectionNeverQueried.Global
[RegistryPassThrough(true)]
public Dictionary<string, Agent> Agents { get; } = new();
/// <summary>
/// Collection of all objects that consume time in the system.
/// </summary>
// ReSharper disable once CollectionNeverQueried.Global
[RegistryPassThrough(true)]
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>
where TAction : AgentAction
{
/// <summary>
/// Gets or sets the name of the action type.
/// </summary>
// ReSharper disable once StaticMemberInGenericType
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>
where TSkin : Polonium.SkinManagers.Skin
{
/// <summary>
/// Gets or sets the root colors for the palette.
/// </summary>
// ReSharper disable once StaticMemberInGenericType
public static Color[] PaletteRoots { get; set; }
/// <summary>
/// Gets or sets the color mapping dictionary for palette transformations.
/// </summary>
// ReSharper disable once StaticMemberInGenericType
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>
where TAsset : Node
{
/// <summary>
/// Object pool for reusing instances to improve performance.
/// </summary>
private static readonly Queue<TAsset> Pool = new();
/// <summary>
/// Gets or sets the packed scene for instantiation.
/// </summary>
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>();
/// <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;
/// <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)
{
if (Pool.Count < 10)

View File

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