diff --git a/Zennysoft.Game.Ma.Implementation/Game/GameLogic.Output.cs b/Zennysoft.Game.Ma.Implementation/Game/GameLogic.Output.cs index 84b9f296..d15878f9 100644 --- a/Zennysoft.Game.Ma.Implementation/Game/GameLogic.Output.cs +++ b/Zennysoft.Game.Ma.Implementation/Game/GameLogic.Output.cs @@ -42,8 +42,6 @@ public partial class GameLogic public readonly record struct SaveGame; - public readonly record struct AnnounceMessage(string Message); - public readonly record struct DoubleExpTimeStart(int lengthOfTimeInSeconds); } } diff --git a/Zennysoft.Game.Ma.Implementation/Game/GameLogic.State.cs b/Zennysoft.Game.Ma.Implementation/Game/GameLogic.State.cs index 4c731af3..4caca1cb 100644 --- a/Zennysoft.Game.Ma.Implementation/Game/GameLogic.State.cs +++ b/Zennysoft.Game.Ma.Implementation/Game/GameLogic.State.cs @@ -16,7 +16,6 @@ public partial class GameLogic gameRepo.IsPaused.Sync += OnIsPaused; gameRepo.OpenInventory += OnOpenInventory; gameRepo.CloseInventory += OnCloseInventory; - gameRepo.AnnounceMessage += OnAnnounceMessage; gameRepo.DoubleExpTimeStart += OnDoubleExpTimeStart; }); OnDetach(() => @@ -25,7 +24,6 @@ public partial class GameLogic gameRepo.IsPaused.Sync -= OnIsPaused; gameRepo.OpenInventory -= OnOpenInventory; gameRepo.CloseInventory -= OnCloseInventory; - gameRepo.AnnounceMessage -= OnAnnounceMessage; gameRepo.DoubleExpTimeStart -= OnDoubleExpTimeStart; }); } @@ -34,8 +32,6 @@ public partial class GameLogic private void OnCloseInventory() => Output(new Output.CloseInventory()); - private void OnAnnounceMessage(string message) => Output(new Output.AnnounceMessage(message)); - private void OnDoubleExpTimeStart(int lengthOfTimeInSeconds) => Output(new Output.DoubleExpTimeStart(lengthOfTimeInSeconds)); public void OnIsPaused(bool isPaused) => Output(new Output.SetPauseMode(isPaused)); diff --git a/Zennysoft.Game.Ma.Implementation/Game/GameRepo.cs b/Zennysoft.Game.Ma.Implementation/Game/GameRepo.cs index 10467191..380a8f42 100644 --- a/Zennysoft.Game.Ma.Implementation/Game/GameRepo.cs +++ b/Zennysoft.Game.Ma.Implementation/Game/GameRepo.cs @@ -27,6 +27,8 @@ public interface IGameRepo : IDisposable public void EndDoubleExp(); + public void AnnounceMessageOnMainScreen(string message); + public double ExpRate { get; } } @@ -67,17 +69,22 @@ public class GameRepo : IGameRepo public void StartDoubleEXP(TimeSpan lengthOfEffect) { CloseInventory?.Invoke(); - AnnounceMessage?.Invoke("Experience points temporarily doubled."); + AnnounceMessageOnMainScreen("Experience points temporarily doubled."); DoubleExpTimeStart?.Invoke(lengthOfEffect.Seconds); ExpRate = 2; } public void EndDoubleExp() { - AnnounceMessage?.Invoke("Experience points effect wore off."); + AnnounceMessageOnMainScreen("Experience points effect wore off."); ExpRate = 1; } + public void AnnounceMessageOnMainScreen(string message) + { + AnnounceMessage?.Invoke(message); + } + public void OnGameEnded() { Pause(); diff --git a/Zennysoft.Game.Ma.Implementation/UI/InGameUI/InGameUILogic.State.cs b/Zennysoft.Game.Ma.Implementation/UI/InGameUI/InGameUILogic.State.cs new file mode 100644 index 00000000..8eefbb10 --- /dev/null +++ b/Zennysoft.Game.Ma.Implementation/UI/InGameUI/InGameUILogic.State.cs @@ -0,0 +1,30 @@ +using Chickensoft.Introspection; +using Chickensoft.LogicBlocks; + +namespace Zennysoft.Game.Ma.Implementation; + +public partial class InGameUILogic +{ + [Meta] + public abstract partial record State : StateLogic + { + protected State() + { + OnAttach(() => + { + var gameRepo = Get(); + gameRepo.AnnounceMessage += OnAnnounceMessage; + }); + OnDetach(() => + { + var gameRepo = Get(); + gameRepo.AnnounceMessage -= OnAnnounceMessage; + }); + } + + private void OnAnnounceMessage(string message) + { + Output(new Output.AnnounceMessage(message)); + } + } +} diff --git a/Zennysoft.Game.Ma.Implementation/UI/InGameUI/InGameUILogic.cs b/Zennysoft.Game.Ma.Implementation/UI/InGameUI/InGameUILogic.cs new file mode 100644 index 00000000..003460e8 --- /dev/null +++ b/Zennysoft.Game.Ma.Implementation/UI/InGameUI/InGameUILogic.cs @@ -0,0 +1,13 @@ +using Chickensoft.Introspection; +using Chickensoft.LogicBlocks; + +namespace Zennysoft.Game.Ma.Implementation; + +public interface IInGameUILogic : ILogicBlock; + +[Meta] +[LogicBlock(typeof(State), Diagram = true)] +public partial class InGameUILogic : LogicBlock, IInGameUILogic +{ + public override Transition GetInitialState() => To(); +} diff --git a/Zennysoft.Game.Ma.Implementation/UI/InGameUI/state/InGameUILogic.Output.cs b/Zennysoft.Game.Ma.Implementation/UI/InGameUI/state/InGameUILogic.Output.cs new file mode 100644 index 00000000..ed66125f --- /dev/null +++ b/Zennysoft.Game.Ma.Implementation/UI/InGameUI/state/InGameUILogic.Output.cs @@ -0,0 +1,8 @@ +namespace Zennysoft.Game.Ma.Implementation; +public partial class InGameUILogic +{ + public static class Output + { + public readonly record struct AnnounceMessage(string Message); + } +} diff --git a/Zennysoft.Game.Ma.Implementation/UI/InGameUI/state/States/InGameUI.State.Active.cs b/Zennysoft.Game.Ma.Implementation/UI/InGameUI/state/States/InGameUI.State.Active.cs new file mode 100644 index 00000000..c18d4753 --- /dev/null +++ b/Zennysoft.Game.Ma.Implementation/UI/InGameUI/state/States/InGameUI.State.Active.cs @@ -0,0 +1,15 @@ +using Chickensoft.Introspection; + +namespace Zennysoft.Game.Ma.Implementation; + +public partial class InGameUILogic +{ + public partial record State + { + [Meta] + public partial record Active : State + { + + } + } +} diff --git a/Zennysoft.Game.Ma/src/game/Game.cs b/Zennysoft.Game.Ma/src/game/Game.cs index ccfee439..33aebe92 100644 --- a/Zennysoft.Game.Ma/src/game/Game.cs +++ b/Zennysoft.Game.Ma/src/game/Game.cs @@ -97,6 +97,7 @@ public partial class Game : Node3D, IGame GameLogic.Set(GameEventDepot); GameLogic.Set(Player); GameLogic.Set(Map); + GameLogic.Set(InGameUI); Instantiator = new Instantiator(GetTree()); RescuedItems = new RescuedItemDatabase(); @@ -185,10 +186,10 @@ public partial class Game : Node3D, IGame Input.MouseMode = Input.MouseModeEnum.Visible; PauseMenu.SetProcessUnhandledInput(true); }) - .Handle((in GameLogic.Output.LoadNextFloor _) => { Map.SpawnNextFloor(); }) - .Handle((in GameLogic.Output.LoadMap _) => { Map.LoadMap(); }) .Handle((in GameLogic.Output.HidePauseMenu _) => { PauseMenu.Hide(); }) .Handle((in GameLogic.Output.ExitPauseMenu _) => { PauseMenu.FadeOut(); Input.MouseMode = Input.MouseModeEnum.Visible; PauseMenu.SetProcessUnhandledInput(false); }) + .Handle((in GameLogic.Output.LoadNextFloor _) => { Map.SpawnNextFloor(); }) + .Handle((in GameLogic.Output.LoadMap _) => { Map.LoadMap(); }) .Handle((in GameLogic.Output.ShowFloorClearMenu _) => { FloorClearMenu.Show(); FloorClearMenu.FadeIn(); }) .Handle((in GameLogic.Output.ExitFloorClearMenu _) => { FloorClearMenu.FadeOut(); }) .Handle((in GameLogic.Output.OpenInventory _) => { InGameUI.ShowInventoryScreen(); InGameUI.InventoryMenu.SetProcessInput(true); }) @@ -199,7 +200,6 @@ public partial class Game : Node3D, IGame .Handle((in GameLogic.Output.HideAskForTeleport _) => { GameRepo.Resume(); InGameUI.UseTeleportPrompt.FadeOut(); InGameUI.SetProcessInput(false); }) .Handle((in GameLogic.Output.ShowLostScreen _) => { DeathMenu.Show(); DeathMenu.FadeIn(); }) .Handle((in GameLogic.Output.ExitLostScreen _) => { DeathMenu.FadeOut(); }) - .Handle((in GameLogic.Output.AnnounceMessage output) => { AnnounceMessageOnMainScreen(output.Message); }) .Handle((in GameLogic.Output.DoubleExpTimeStart output) => { DoubleEXPTimer.WaitTime = output.lengthOfTimeInSeconds; DoubleEXPTimer.Start(); }) .Handle((in GameLogic.Output.SaveGame _) => { @@ -364,11 +364,6 @@ public partial class Game : Node3D, IGame InGameUI.InventoryMenu.ShowMessage(message); } - public void AnnounceMessageOnMainScreen(string message) - { - InGameUI.PlayerInfoUI.DisplayMessage(message); - } - public IDungeonFloor CurrentFloor => Map.CurrentFloor; public void EnemyDefeated(Vector3 defeatedLocation, EnemyStatResource resource) diff --git a/Zennysoft.Game.Ma/src/game/IGame.cs b/Zennysoft.Game.Ma/src/game/IGame.cs index 0564b886..71c740ab 100644 --- a/Zennysoft.Game.Ma/src/game/IGame.cs +++ b/Zennysoft.Game.Ma/src/game/IGame.cs @@ -5,7 +5,6 @@ using Chickensoft.AutoInject; using Chickensoft.GodotNodeInterfaces; using Chickensoft.SaveFileBuilder; using Godot; -using System; using Zennysoft.Game.Ma.Implementation; public interface IGame : IProvide, IProvide, IProvide, IProvide, IProvide>, INode3D @@ -32,8 +31,6 @@ public interface IGame : IProvide, IProvide, IProvid public void AnnounceMessageOnInventoryScreen(string message); - public void AnnounceMessageOnMainScreen(string message); - public void FloorExitReached(); public void NextFloorLoaded(); diff --git a/Zennysoft.Game.Ma/src/player/Player.cs b/Zennysoft.Game.Ma/src/player/Player.cs index 2afc5d19..02cdab4c 100644 --- a/Zennysoft.Game.Ma/src/player/Player.cs +++ b/Zennysoft.Game.Ma/src/player/Player.cs @@ -19,6 +19,8 @@ public partial class Player : CharacterBody3D, IPlayer public override void _Notification(int what) => this.Notify(what); private PlayerLogic.IBinding PlayerBinding { get; set; } = default!; + + [Dependency] private IGameRepo _gameRepo => this.DependOn(); #endregion #region Save @@ -233,22 +235,22 @@ public partial class Player : CharacterBody3D, IPlayer var isAdded = Inventory.TryAdd(inventoryItem); if (isAdded) { - Game.AnnounceMessageOnMainScreen($"{inventoryItem.ItemName} picked up."); + _gameRepo.AnnounceMessageOnMainScreen($"{inventoryItem.ItemName} picked up."); inventoryItem.QueueFree(); } else - Game.AnnounceMessageOnMainScreen($"Could not pick up {inventoryItem.ItemName}."); + _gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {inventoryItem.ItemName}."); } if (area.GetParent() is DroppedItem droppedItem) { var isAdded = Inventory.TryAdd(droppedItem.Item); if (isAdded) { - Game.AnnounceMessageOnMainScreen($"{droppedItem.Item.ItemName} picked up."); + _gameRepo.AnnounceMessageOnMainScreen($"{droppedItem.Item.ItemName} picked up."); droppedItem.QueueFree(); } else - Game.AnnounceMessageOnMainScreen($"Could not pick up {droppedItem.Item.ItemName}."); + _gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {droppedItem.Item.ItemName}."); } } diff --git a/Zennysoft.Game.Ma/src/ui/in_game_ui/InGameUI.cs b/Zennysoft.Game.Ma/src/ui/in_game_ui/InGameUI.cs index 796c674a..7f7d6a15 100644 --- a/Zennysoft.Game.Ma/src/ui/in_game_ui/InGameUI.cs +++ b/Zennysoft.Game.Ma/src/ui/in_game_ui/InGameUI.cs @@ -2,6 +2,8 @@ using Chickensoft.AutoInject; using Chickensoft.GodotNodeInterfaces; using Chickensoft.Introspection; using Godot; +using Renci.SshNet.Messages; +using Zennysoft.Game.Ma.Implementation; namespace Zennysoft.Game.Ma; @@ -31,9 +33,34 @@ public partial class InGameUI : Control, IInGameUI [Node] public IUseTeleportPrompt UseTeleportPrompt { get; set; } = default!; + [Dependency] private IGameRepo _gameRepo => this.DependOn(); + + public IInGameUILogic InGameUILogic { get; set; } = default!; + + public InGameUILogic.IBinding InGameUILogicBinding { get; set; } = default!; + [Signal] public delegate void MinimapButtonReleasedEventHandler(); + public void Setup() + { + InGameUILogic = new InGameUILogic(); + InGameUILogic.Set(_gameRepo); + } + + public void OnResolved() + { + InGameUILogicBinding = InGameUILogic.Bind(); + + InGameUILogicBinding + .Handle((in InGameUILogic.Output.AnnounceMessage output) => + { + PlayerInfoUI.DisplayMessage(output.Message); + }); + + InGameUILogic.Start(); + } + public override void _UnhandledInput(InputEvent @event) { if (@event.IsActionReleased(GameInputs.MiniMap))