using System; using EinSoftworks.Events; using EinSoftworks.Input; using EinSoftworks.StateManagement; using EinSoftworks.Utilities; using Godot; namespace Voider; public partial class LibraryTest : Node { private StateMachine _stateMachine; private HierarchicalStateMachine _hierarchicalSM; private EventBus _eventBus; private int _frameCount = 0; private IdlePlayerState _idleState; private RunningPlayerState _runningState; private JumpingPlayerState _jumpingState; public override void _Ready() { GD.Print("=== EinSoftworks Library Integration Test ===\n"); TestUtilities(); TestEvents(); TestInput(); TestStateMachine(); TestHierarchicalStateMachine(); GD.Print("\n=== All Tests Initialized Successfully ==="); GD.Print("Watch console for runtime behavior...\n"); } public override void _Process(double delta) { _frameCount++; // Update state machines _stateMachine?.Update((float)delta); _hierarchicalSM?.Update((float)delta); // Test transitions every 60 frames if (_frameCount == 60) { GD.Print("\n[Frame 60] Testing state transitions..."); _stateMachine?.ChangeState(_runningState); } else if (_frameCount == 120) { GD.Print("\n[Frame 120] Testing event-triggered transition..."); _stateMachine?.TriggerEvent("jump"); } else if (_frameCount == 180) { GD.Print("\n[Frame 180] Testing hierarchical state change..."); _hierarchicalSM?.ChangeState("Combat"); } } private void TestUtilities() { GD.Print("--- Testing EinSoftworks.Utilities ---"); // Test MathUtils float angle = 90f; float radians = MathUtils.DegreesToRadians(angle); GD.Print($"✓ DegreesToRadians: {angle}° = {radians} rad"); float backToDegrees = MathUtils.RadiansToDegrees(radians); GD.Print($"✓ RadiansToDegrees: {radians} rad = {backToDegrees}°"); float value = 1.5f; float clamped = MathUtils.Clamp01(value); GD.Print($"✓ Clamp01: {value} clamped to {clamped}"); bool approx = MathUtils.Approximately(0.1f + 0.2f, 0.3f); GD.Print($"✓ Approximately: 0.1 + 0.2 ≈ 0.3 = {approx}"); GD.Print(""); } private void TestEvents() { GD.Print("--- Testing EinSoftworks.Events ---"); _eventBus = new EventBus(); // Subscribe to events _eventBus.Subscribe(OnTestEvent); GD.Print($"✓ EventBus created with {_eventBus.SubscriberCount} subscriber"); // Publish an event _eventBus.Publish(new TestEvent("Initialization", 42)); GD.Print(""); } private void TestInput() { GD.Print("--- Testing EinSoftworks.Input ---"); // Create input contexts var gameplayContext = new InputContext( "Gameplay", 10, InputContext.ContextMode.AllowList, false ); gameplayContext.AllowAction("move_left"); gameplayContext.AllowAction("move_right"); gameplayContext.AllowAction("jump"); var menuContext = new InputContext("Menu", 20, InputContext.ContextMode.BlockList, true); menuContext.BlockAction("move_left"); menuContext.BlockAction("move_right"); GD.Print( $"✓ Created InputContext: {gameplayContext.Name} (Priority: {gameplayContext.Priority})" ); GD.Print($"✓ Created InputContext: {menuContext.Name} (Priority: {menuContext.Priority})"); GD.Print(" (InputManager is a Node singleton - add to scene tree for full functionality)"); // Test InputBuffer var inputBuffer = new InputBuffer(0.15f); inputBuffer.BufferInput("jump"); bool hasJump = inputBuffer.IsInputBuffered("jump"); GD.Print($"✓ InputBuffer: Buffered 'jump' action, has buffered = {hasJump}"); GD.Print(""); } private void TestStateMachine() { GD.Print("--- Testing EinSoftworks.StateManagement (Basic) ---"); _stateMachine = new StateMachine(); // Create states _idleState = new IdlePlayerState(); _runningState = new RunningPlayerState(); _jumpingState = new JumpingPlayerState(); // Subscribe to state changes _stateMachine.StateChanged += (from, to) => { GD.Print( $" → State changed: {from?.GetType().Name ?? "null"} → {to?.GetType().Name ?? "null"}" ); }; // Add transitions _stateMachine.AddTransition(_idleState, _runningState, () => false); // Won't trigger automatically _stateMachine.AddTransition(_runningState, _jumpingState, "jump"); // Set initial state _stateMachine.ChangeState(_idleState); GD.Print( $"✓ StateMachine created with initial state: {_stateMachine.CurrentState?.GetType().Name}" ); GD.Print(""); } private void TestHierarchicalStateMachine() { GD.Print("--- Testing EinSoftworks.StateManagement (Hierarchical) ---"); _hierarchicalSM = new HierarchicalStateMachine(); // Create parent states var exploration = "Exploration"; var combat = "Combat"; // Create sub-state machine for combat var combatSubStates = new StateMachine(); combatSubStates.ChangeState("Attacking"); _hierarchicalSM.AddSubStateMachine(combat, combatSubStates); // Subscribe to state changes _hierarchicalSM.StateChanged += (from, to) => { GD.Print($" → Hierarchical state changed: {from ?? "null"} → {to ?? "null"}"); }; // Set initial state _hierarchicalSM.ChangeState(exploration); GD.Print($"✓ HierarchicalStateMachine created with state: {_hierarchicalSM.CurrentState}"); GD.Print(""); } private void OnTestEvent(TestEvent evt) { GD.Print($" → Event received: {evt.Message} (Value: {evt.Value})"); } public override void _ExitTree() { // Cleanup _eventBus?.Unsubscribe(OnTestEvent); _stateMachine?.Clear(); _hierarchicalSM?.Clear(); } } // Test event class public class TestEvent { public string Message { get; } public int Value { get; } public TestEvent(string message, int value) { Message = message; Value = value; } } // Player state classes for testing public abstract class PlayerState : State { protected string StateName; public override void Enter() { GD.Print($" → Entering {StateName}"); } public override void Update(float delta) { } public override void FixedUpdate(float fixedDelta) { } public override void Exit() { GD.Print($" → Exiting {StateName}"); } } public class IdlePlayerState : PlayerState { public IdlePlayerState() { StateName = "Idle"; } } public class RunningPlayerState : PlayerState { public RunningPlayerState() { StateName = "Running"; } } public class JumpingPlayerState : PlayerState { public JumpingPlayerState() { StateName = "Jumping"; } }