From a041ccbce0a1378f2ddb385651d528982328bbbd Mon Sep 17 00:00:00 2001 From: Ed Kolis Date: Sun, 20 Oct 2024 12:14:10 -0400 Subject: [PATCH] 322 dependency injection and inversion of control (#323) * Add basic DI framework * Add ITurnProcessor interface * Delete some obsolete comments * Apply DI to the TurnProcessor in the TechnologyTest * Implement DI for the TurnProcessor instances used in the game itself * Reorganize some comments * Move TurnProcessor to a new FrEee.Processes project * Put DI configuration code in its own root project * Make IModObject actually implement IDisposable * Add IAI interface for the AIs, but I'm not sure what to do about C# vs. Python scripts so I'l leave it at that for now * Move Configuration class where it belongs * DI the battles * Order commands are now in DI * DI for notes commands * Fix incorrect name for IAddOrderCommand * DI for design commands * Add DIRoot for easier access to common services * Fleet commands get DI'd * Actually use the DI for fleet commands * Remove access to implementation details of game features from the Blazor UI, just to be safe. Prepare to do so for the WinForms UI but we can't do that quite yet; have to clean some stuff up first. * DI the waypoint commands * Use DI for message commands * Minister commands; fix copypasta namespaces * Remove PrivateAssets="all" from root project reference since it didn't seem to do anything * Make private assets restriction more granular * Update DI framework package * Get rid of overarching disable transitive referencves for Blazor project too, it's now in the individual feature projects * Actually inject the minister command factory * Extract more properties into IBattle interface * Remove dependencies on concrete classes for fleet commands rom UI --- .../Extensions/ChecksExtensions.cs | 4 +- .../Extensions/CommonExtensions.cs | 9 +- FrEee.Core.Domain/FrEee.Core.Domain.csproj | 2 +- .../Gameplay/Commands/Command.cs | 66 ++++++++++++ .../Commands/Designs}/ICreateDesignCommand.cs | 2 +- .../Commands/Designs/IDesignCommandFactory.cs | 21 ++++ .../Designs/ISetObsoleteFlagCommand.cs | 25 +++++ .../Commands/EditStrategyCommand.cs | 0 .../Commands/Fleets/ICreateFleetCommand.cs | 17 +++ .../Commands/Fleets/IDisbandFleetCommand.cs | 8 ++ .../Commands/Fleets/IFleetCommandFactory.cs | 24 +++++ .../Commands/Fleets/IJoinFleetCommand.cs | 16 +++ .../Commands/Fleets/ILeaveFleetCommand.cs | 8 ++ .../Commands/ICommand.cs | 2 +- .../Gameplay/Commands/ICommandFactory.cs | 16 +++ .../Gameplay/Commands/IToggleCommand.cs | 21 ++++ .../Messages/IDeleteMessageCommand.cs | 11 ++ .../Commands/Messages/IMessageCommand.cs | 15 +++ .../Messages/IMessageCommandFactory.cs | 19 ++++ .../Commands/Messages/ISendMessageCommand.cs | 11 ++ .../Ministers/IMinisterCommandFactory.cs | 16 +++ .../Ministers/IToggleMinistersCommand.cs | 15 +++ .../Commands/Notes/INoteCommandFactory.cs | 27 +++++ .../Commands/Notes/ISetPlayerInfoCommnad.cs | 18 ++++ .../Commands/Orders/IAddOrderCommand.cs | 17 +++ .../Commands/Orders}/IOrderCommand.cs | 2 +- .../Commands/Orders/IOrderCommandFactory.cs | 26 +++++ .../Commands/Orders/IRemoveOrderCommand.cs | 17 +++ .../Orders/IToggleOrdersOnHoldCommand.cs | 17 +++ .../Orders/IToggleRepeatOrdersCommand.cs | 17 +++ .../Gameplay/Commands/ResearchCommand.cs | 57 ++++++++++ .../Waypoints/IWaypointCommandFactory.cs | 20 ++++ FrEee.Core.Domain/Modding/DamageType.cs | 5 + FrEee.Core.Domain/Modding/EventTemplate.cs | 5 + FrEee.Core.Domain/Modding/EventType.cs | 5 + FrEee.Core.Domain/Modding/IModObject.cs | 3 +- .../Modding/Scripts/PythonScript.cs | 1 + .../Diplomacy/Actions/DiplomaticAction.cs | 2 +- .../Diplomacy/Clauses/AllianceClause.cs | 7 +- .../Diplomacy/Messages/Message.cs | 7 +- .../Civilization/Diplomacy/Proposal.cs | 4 +- .../Objects/Civilization/Empire.cs | 9 +- .../Objects/Civilization/Waypoint.cs | 2 +- .../Commands/ClearPlayerNoteCommand.cs | 26 ----- FrEee.Core.Domain/Objects/Commands/Command.cs | 66 ------------ .../Objects/Commands/CreateDesignCommand.cs | 42 -------- .../Objects/Commands/ResearchCommand.cs | 56 ---------- .../Commands/SetObsoleteFlagCommand.cs | 76 ------------- .../Commands/ToggleOrdersOnHoldCommand.cs | 19 ---- .../Commands/ToggleRepeatOrdersCommand.cs | 19 ---- FrEee.Core.Domain/Objects/GameState/Game.cs | 29 +++-- FrEee.Core.Domain/Objects/Vehicles/Design.cs | 6 +- FrEee.Core.Domain/Objects/Vehicles/IDesign.cs | 2 +- FrEee.Core.Domain/Processes/AI/AI.cs | 101 ++++++++---------- FrEee.Core.Domain/Processes/AI/IAI.cs | 33 ++++++ .../Combat/{Grid => Events}/BattleEvent.cs | 7 +- .../Combat/Events/CombatantAppearsEvent.cs | 15 +++ .../Combat/Events/CombatantDestroyedEvent.cs | 11 ++ .../Combat/Events/CombatantDisappearsEvent.cs | 14 +++ .../Combat/Events/CombatantLaunchedEvent.cs | 25 +++++ .../Combat/Events/CombatantMovesEvent.cs | 10 ++ .../Combat/Events/CombatantsCollideEvent.cs | 39 +++++++ .../Combat/Events/WeaponFiresEvent.cs | 49 +++++++++ .../Combat/Grid/CombatantAppearsEvent.cs | 15 --- .../Combat/Grid/CombatantDestroyedEvent.cs | 11 -- .../Combat/Grid/CombatantDisappearsEvent.cs | 14 --- .../Combat/Grid/CombatantLaunchedEvent.cs | 25 ----- .../Combat/Grid/CombatantMovesEvent.cs | 10 -- .../Combat/Grid/CombatantsCollideEvent.cs | 39 ------- .../Processes/Combat/Grid/WeaponFiresEvent.cs | 49 --------- FrEee.Core.Domain/Processes/Combat/IBattle.cs | 7 +- .../Combat/{Grid => }/IBattleEvent.cs | 3 +- .../Processes/Combat/IBattleFactory.cs | 28 +++++ FrEee.Core.Domain/Processes/ITurnProcessor.cs | 20 ++++ FrEee.Core.Domain/Utility/DIRoot.cs | 67 ++++++++++++ FrEee.Core.Utility/FrEee.Core.Utility.csproj | 1 + FrEee.Core.Utility/Utility/DI.cs | 99 +++++++++++++++++ .../Commands/Designs/CreateDesignCommand.cs | 44 ++++++++ .../Commands/Designs/DesignCommandFactory.cs | 26 +++++ .../Designs/SetObsoleteFlagCommand.cs | 67 ++++++++++++ .../Commands/Fleets}/CreateFleetCommand.cs | 10 +- .../Commands/Fleets}/DisbandFleetCommand.cs | 4 +- .../Commands/Fleets/FleetCommandFactory.cs | 42 ++++++++ .../Commands/Fleets}/JoinFleetCommand.cs | 15 +-- .../Commands/Fleets}/LeaveFleetCommand.cs | 7 +- .../Messages}/DeleteMessageCommand.cs | 5 +- .../Messages/MessageCommandFactory.cs | 28 +++++ .../Commands/Messages}/SendMessageCommand.cs | 8 +- .../Ministers/MinisterCommandFactory.cs | 24 +++++ .../Ministers/ToggleMinistersCommand.cs | 31 ++++++ .../Commands/Notes/ClearPlayerNoteCommand.cs | 2 +- .../Notes}/ClearPrivateNameCommand.cs | 2 +- .../Commands/Notes/NoteCommandFactory.cs | 43 ++++++++ .../Commands/Notes}/SetPlayerInfoCommand.cs | 8 +- .../Commands/Notes}/SetPlayerNoteCommand.cs | 2 +- .../Commands/Notes}/SetPrivateNameCommand.cs | 2 +- .../Commands/Notes}/SetPublicNameCommand.cs | 2 +- .../Commands/Orders}/AddOrderCommand.cs | 5 +- .../Commands/Orders}/OrderCommand.cs | 2 +- .../Commands/Orders/OrderCommandFactory.cs | 37 +++++++ .../Orders}/RearrangeOrdersCommand.cs | 2 +- .../Commands/Orders}/RemoveOrderCommand.cs | 5 +- .../Orders/ToggleOrdersOnHoldCommand.cs | 23 ++++ .../Orders/ToggleRepeatOrdersCommand.cs | 23 ++++ .../Waypoints}/CreateWaypointCommand.cs | 2 +- .../Waypoints}/DeleteWaypointCommand.cs | 7 +- .../Waypoints}/HotkeyWaypointCommand.cs | 7 +- .../Waypoints/WaypointCommandFactory.cs | 32 ++++++ FrEee.Gameplay/FrEee.Gameplay.csproj | 22 ++++ .../Combat/Grid/Battle.cs | 3 +- FrEee.Processes/Combat/Grid/BattleFactory.cs | 25 +++++ .../Combat/Grid/Extensions.cs | 0 .../Combat/Grid/GroundBattle.cs | 0 .../Combat/Grid/SpaceBattle.cs | 0 FrEee.Processes/FrEee.Processes.csproj | 22 ++++ .../TurnProcessor.cs | 34 ++---- FrEee.Root/Configuration.cs | 46 ++++++++ FrEee.Root/FrEee.Root.csproj | 29 +++++ FrEee.Tests/FrEee.Tests.csproj | 1 + .../Objects/Technology/TechnologyTest.cs | 13 ++- FrEee.UI.WinForms/Controls/BattleView.cs | 6 +- FrEee.UI.WinForms/Controls/FleetReport.cs | 32 +++--- FrEee.UI.WinForms/Controls/PlanetReport.cs | 14 +-- .../Controls/SearchBox.Designer.cs | 51 ++++----- FrEee.UI.WinForms/Controls/SearchBox.resx | 54 +++++----- .../Controls/SpaceVehicleReport.cs | 34 +++--- .../Forms/ActivateAbilityForm.cs | 5 +- FrEee.UI.WinForms/Forms/BattleReplayForm.cs | 10 +- FrEee.UI.WinForms/Forms/BattleResultsForm.cs | 9 +- .../Forms/CombatSimulatorForm.cs | 6 +- .../Forms/ConstructionQueueForm.cs | 40 +++---- FrEee.UI.WinForms/Forms/DesignListForm.cs | 11 +- FrEee.UI.WinForms/Forms/DiplomacyForm.cs | 4 +- FrEee.UI.WinForms/Forms/EmpireListForm.cs | 15 ++- FrEee.UI.WinForms/Forms/FleetTransferForm.cs | 35 +++--- FrEee.UI.WinForms/Forms/HostConsoleForm.cs | 2 +- FrEee.UI.WinForms/Forms/MainGameForm.cs | 16 +-- FrEee.UI.WinForms/Forms/MinistersForm.cs | 9 +- FrEee.UI.WinForms/Forms/RecycleForm.cs | 16 +-- FrEee.UI.WinForms/Forms/ResearchForm.cs | 2 +- FrEee.UI.WinForms/FrEee.UI.WinForms.csproj | 5 +- FrEee.UI.WinForms/Program.cs | 6 +- .../Utility/Extensions/GuiExtensions.cs | 3 + FrEee.sln | 42 ++++++++ 144 files changed, 1945 insertions(+), 823 deletions(-) create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Command.cs rename FrEee.Core.Domain/{Objects/Commands => Gameplay/Commands/Designs}/ICreateDesignCommand.cs (84%) create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Designs/IDesignCommandFactory.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Designs/ISetObsoleteFlagCommand.cs rename FrEee.Core.Domain/{Objects => Gameplay}/Commands/EditStrategyCommand.cs (100%) create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Fleets/ICreateFleetCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Fleets/IDisbandFleetCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Fleets/IFleetCommandFactory.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Fleets/IJoinFleetCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Fleets/ILeaveFleetCommand.cs rename FrEee.Core.Domain/{Objects => Gameplay}/Commands/ICommand.cs (96%) create mode 100644 FrEee.Core.Domain/Gameplay/Commands/ICommandFactory.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/IToggleCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Messages/IDeleteMessageCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Messages/IMessageCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Messages/IMessageCommandFactory.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Messages/ISendMessageCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Ministers/IMinisterCommandFactory.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Ministers/IToggleMinistersCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Notes/INoteCommandFactory.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Notes/ISetPlayerInfoCommnad.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Orders/IAddOrderCommand.cs rename FrEee.Core.Domain/{Objects/Commands => Gameplay/Commands/Orders}/IOrderCommand.cs (87%) create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Orders/IOrderCommandFactory.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Orders/IRemoveOrderCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Orders/IToggleOrdersOnHoldCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Orders/IToggleRepeatOrdersCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/ResearchCommand.cs create mode 100644 FrEee.Core.Domain/Gameplay/Commands/Waypoints/IWaypointCommandFactory.cs delete mode 100644 FrEee.Core.Domain/Objects/Commands/ClearPlayerNoteCommand.cs delete mode 100644 FrEee.Core.Domain/Objects/Commands/Command.cs delete mode 100644 FrEee.Core.Domain/Objects/Commands/CreateDesignCommand.cs delete mode 100644 FrEee.Core.Domain/Objects/Commands/ResearchCommand.cs delete mode 100644 FrEee.Core.Domain/Objects/Commands/SetObsoleteFlagCommand.cs delete mode 100644 FrEee.Core.Domain/Objects/Commands/ToggleOrdersOnHoldCommand.cs delete mode 100644 FrEee.Core.Domain/Objects/Commands/ToggleRepeatOrdersCommand.cs create mode 100644 FrEee.Core.Domain/Processes/AI/IAI.cs rename FrEee.Core.Domain/Processes/Combat/{Grid => Events}/BattleEvent.cs (80%) create mode 100644 FrEee.Core.Domain/Processes/Combat/Events/CombatantAppearsEvent.cs create mode 100644 FrEee.Core.Domain/Processes/Combat/Events/CombatantDestroyedEvent.cs create mode 100644 FrEee.Core.Domain/Processes/Combat/Events/CombatantDisappearsEvent.cs create mode 100644 FrEee.Core.Domain/Processes/Combat/Events/CombatantLaunchedEvent.cs create mode 100644 FrEee.Core.Domain/Processes/Combat/Events/CombatantMovesEvent.cs create mode 100644 FrEee.Core.Domain/Processes/Combat/Events/CombatantsCollideEvent.cs create mode 100644 FrEee.Core.Domain/Processes/Combat/Events/WeaponFiresEvent.cs delete mode 100644 FrEee.Core.Domain/Processes/Combat/Grid/CombatantAppearsEvent.cs delete mode 100644 FrEee.Core.Domain/Processes/Combat/Grid/CombatantDestroyedEvent.cs delete mode 100644 FrEee.Core.Domain/Processes/Combat/Grid/CombatantDisappearsEvent.cs delete mode 100644 FrEee.Core.Domain/Processes/Combat/Grid/CombatantLaunchedEvent.cs delete mode 100644 FrEee.Core.Domain/Processes/Combat/Grid/CombatantMovesEvent.cs delete mode 100644 FrEee.Core.Domain/Processes/Combat/Grid/CombatantsCollideEvent.cs delete mode 100644 FrEee.Core.Domain/Processes/Combat/Grid/WeaponFiresEvent.cs rename FrEee.Core.Domain/Processes/Combat/{Grid => }/IBattleEvent.cs (83%) create mode 100644 FrEee.Core.Domain/Processes/Combat/IBattleFactory.cs create mode 100644 FrEee.Core.Domain/Processes/ITurnProcessor.cs create mode 100644 FrEee.Core.Domain/Utility/DIRoot.cs create mode 100644 FrEee.Core.Utility/Utility/DI.cs create mode 100644 FrEee.Gameplay/Commands/Designs/CreateDesignCommand.cs create mode 100644 FrEee.Gameplay/Commands/Designs/DesignCommandFactory.cs create mode 100644 FrEee.Gameplay/Commands/Designs/SetObsoleteFlagCommand.cs rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Fleets}/CreateFleetCommand.cs (84%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Fleets}/DisbandFleetCommand.cs (77%) create mode 100644 FrEee.Gameplay/Commands/Fleets/FleetCommandFactory.cs rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Fleets}/JoinFleetCommand.cs (81%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Fleets}/LeaveFleetCommand.cs (77%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Messages}/DeleteMessageCommand.cs (85%) create mode 100644 FrEee.Gameplay/Commands/Messages/MessageCommandFactory.cs rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Messages}/SendMessageCommand.cs (87%) create mode 100644 FrEee.Gameplay/Commands/Ministers/MinisterCommandFactory.cs create mode 100644 FrEee.Gameplay/Commands/Ministers/ToggleMinistersCommand.cs rename FrEee.Core.Domain/Objects/Commands/MinisterToggleCommand.cs => FrEee.Gameplay/Commands/Notes/ClearPlayerNoteCommand.cs (93%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Notes}/ClearPrivateNameCommand.cs (94%) create mode 100644 FrEee.Gameplay/Commands/Notes/NoteCommandFactory.cs rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Notes}/SetPlayerInfoCommand.cs (69%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Notes}/SetPlayerNoteCommand.cs (94%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Notes}/SetPrivateNameCommand.cs (94%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Notes}/SetPublicNameCommand.cs (90%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Orders}/AddOrderCommand.cs (94%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Orders}/OrderCommand.cs (96%) create mode 100644 FrEee.Gameplay/Commands/Orders/OrderCommandFactory.cs rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Orders}/RearrangeOrdersCommand.cs (95%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Orders}/RemoveOrderCommand.cs (92%) create mode 100644 FrEee.Gameplay/Commands/Orders/ToggleOrdersOnHoldCommand.cs create mode 100644 FrEee.Gameplay/Commands/Orders/ToggleRepeatOrdersCommand.cs rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Waypoints}/CreateWaypointCommand.cs (95%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Waypoints}/DeleteWaypointCommand.cs (75%) rename {FrEee.Core.Domain/Objects/Commands => FrEee.Gameplay/Commands/Waypoints}/HotkeyWaypointCommand.cs (92%) create mode 100644 FrEee.Gameplay/Commands/Waypoints/WaypointCommandFactory.cs create mode 100644 FrEee.Gameplay/FrEee.Gameplay.csproj rename {FrEee.Core.Domain/Processes => FrEee.Processes}/Combat/Grid/Battle.cs (99%) create mode 100644 FrEee.Processes/Combat/Grid/BattleFactory.cs rename {FrEee.Core.Domain/Processes => FrEee.Processes}/Combat/Grid/Extensions.cs (100%) rename {FrEee.Core.Domain/Processes => FrEee.Processes}/Combat/Grid/GroundBattle.cs (100%) rename {FrEee.Core.Domain/Processes => FrEee.Processes}/Combat/Grid/SpaceBattle.cs (100%) create mode 100644 FrEee.Processes/FrEee.Processes.csproj rename {FrEee.Core.Domain/Processes => FrEee.Processes}/TurnProcessor.cs (95%) create mode 100644 FrEee.Root/Configuration.cs create mode 100644 FrEee.Root/FrEee.Root.csproj diff --git a/FrEee.Core.Domain/Extensions/ChecksExtensions.cs b/FrEee.Core.Domain/Extensions/ChecksExtensions.cs index 23d4d72c9..b534ed9e3 100644 --- a/FrEee.Core.Domain/Extensions/ChecksExtensions.cs +++ b/FrEee.Core.Domain/Extensions/ChecksExtensions.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using System; using System.Collections; @@ -11,6 +10,7 @@ using FrEee.Objects.GameState; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands.Orders; namespace FrEee.Extensions; public static class ChecksExtensions @@ -154,7 +154,7 @@ from subcloak in gj.DefaultIfEmpty() /// public static bool IsNew(this IOrder order) { - return Game.Current.Referrables.OfType().Where(cmd => cmd.Order == order).Any(); + return Game.Current.Referrables.OfType().Where(cmd => cmd.Order == order).Any(); } public static bool IsPointDefense(this WeaponTypes wt) diff --git a/FrEee.Core.Domain/Extensions/CommonExtensions.cs b/FrEee.Core.Domain/Extensions/CommonExtensions.cs index 3fe50136d..aa5f05373 100644 --- a/FrEee.Core.Domain/Extensions/CommonExtensions.cs +++ b/FrEee.Core.Domain/Extensions/CommonExtensions.cs @@ -10,7 +10,6 @@ using System.Threading.Tasks; using FrEee.Objects.Civilization; using FrEee.Processes.Combat; -using FrEee.Objects.Commands; using FrEee.Objects.LogMessages; using FrEee.Objects.Space; using FrEee.Objects.Technology; @@ -23,6 +22,8 @@ using FrEee.Objects.GameState; using System.Numerics; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Orders; namespace FrEee.Extensions; @@ -970,15 +971,15 @@ public static ResourceQuantity RemoteMiningIncome(this IIncomeProducer o) /// The object from which to remove an order. /// The order to remove. /// The remove-order command created, if any. - public static RemoveOrderCommand RemoveOrderClientSide(this IOrderable obj, IOrder order) + public static IRemoveOrderCommand RemoveOrderClientSide(this IOrderable obj, IOrder order) { if (Empire.Current == null) throw new InvalidOperationException("RemoveOrderClientSide is intended for client side use."); - var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); + var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); if (addCmd == null) { // not a newly added order, so create a remove command to take it off the server - var remCmd = new RemoveOrderCommand(obj, order); + var remCmd = DIRoot.OrderCommands.RemoveOrder(obj, order); Empire.Current.Commands.Add(remCmd); obj.RemoveOrder(order); return remCmd; diff --git a/FrEee.Core.Domain/FrEee.Core.Domain.csproj b/FrEee.Core.Domain/FrEee.Core.Domain.csproj index 18d87323a..86fd74f87 100644 --- a/FrEee.Core.Domain/FrEee.Core.Domain.csproj +++ b/FrEee.Core.Domain/FrEee.Core.Domain.csproj @@ -26,7 +26,7 @@ - + diff --git a/FrEee.Core.Domain/Gameplay/Commands/Command.cs b/FrEee.Core.Domain/Gameplay/Commands/Command.cs new file mode 100644 index 000000000..ac89f8e0e --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Command.cs @@ -0,0 +1,66 @@ +using FrEee.Objects.Civilization; +using FrEee.Objects.GameState; +using FrEee.Serialization; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FrEee.Gameplay.Commands; + +/// +/// A generic command. +/// +/// +[Serializable] +public abstract class Command : ICommand + where T : IReferrable +{ + protected Command(T target) + { + Issuer = Empire.Current; + Executor = target; + } + + [DoNotSerialize] + public T Executor { get { return executor; } set { executor = value; } } + + IReferrable ICommand.Executor + { + get { return Executor; } + } + + public long ExecutorID { get { return executor.ID; } } + + public bool IsDisposed { get; set; } + + [DoNotSerialize] + public Empire Issuer { get { return issuer; } set { issuer = value; } } + + public virtual IEnumerable NewReferrables + { + get + { + yield break; + } + } + + protected GameReference executor { get; set; } + + private GameReference issuer { get; set; } + + public abstract void Execute(); + + public virtual void ReplaceClientIDs(IDictionary idmap, ISet done = null) + { + if (done == null) + done = new HashSet(); + if (!done.Contains(this)) + { + done.Add(this); + issuer.ReplaceClientIDs(idmap, done); + executor.ReplaceClientIDs(idmap, done); + foreach (var r in NewReferrables.OfType()) + r.ReplaceClientIDs(idmap, done); + } + } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/ICreateDesignCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Designs/ICreateDesignCommand.cs similarity index 84% rename from FrEee.Core.Domain/Objects/Commands/ICreateDesignCommand.cs rename to FrEee.Core.Domain/Gameplay/Commands/Designs/ICreateDesignCommand.cs index 38a1e7709..692cb692f 100644 --- a/FrEee.Core.Domain/Objects/Commands/ICreateDesignCommand.cs +++ b/FrEee.Core.Domain/Gameplay/Commands/Designs/ICreateDesignCommand.cs @@ -1,7 +1,7 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Vehicles; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Designs; /// /// A command for an empire to create a design. diff --git a/FrEee.Core.Domain/Gameplay/Commands/Designs/IDesignCommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/Designs/IDesignCommandFactory.cs new file mode 100644 index 000000000..48b8fffe2 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Designs/IDesignCommandFactory.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; +using FrEee.Objects.Vehicles; + +namespace FrEee.Gameplay.Commands.Designs; + +/// +/// Builds various types of commands used for managing vehicle designs. +public interface IDesignCommandFactory +{ + ICreateDesignCommand CreateDesign(IDesign design) + where T : IVehicle; + + ISetObsoleteFlagCommand SetObsoleteFlag(IDesign design, bool isObsolete); +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Designs/ISetObsoleteFlagCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Designs/ISetObsoleteFlagCommand.cs new file mode 100644 index 000000000..dc6de57d0 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Designs/ISetObsoleteFlagCommand.cs @@ -0,0 +1,25 @@ +using FrEee.Objects.Civilization; +using FrEee.Objects.Vehicles; + +namespace FrEee.Gameplay.Commands.Designs; + +/// +/// A command to mark a design as obsolete or not obsolete. +/// +public interface ISetObsoleteFlagCommand : ICommand +{ + /// + /// The design to set the flag on if it's already knwon by the server. + /// + IDesign Design { get; } + + /// + /// The design to set the flag on if it's only in the library and not in the game or it's a brand new design. + /// + IDesign NewDesign { get; set; } + + /// + /// The flag state to set. + /// + bool IsObsolete { get; set; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/EditStrategyCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/EditStrategyCommand.cs similarity index 100% rename from FrEee.Core.Domain/Objects/Commands/EditStrategyCommand.cs rename to FrEee.Core.Domain/Gameplay/Commands/EditStrategyCommand.cs diff --git a/FrEee.Core.Domain/Gameplay/Commands/Fleets/ICreateFleetCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Fleets/ICreateFleetCommand.cs new file mode 100644 index 000000000..d86b51cc3 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Fleets/ICreateFleetCommand.cs @@ -0,0 +1,17 @@ +using FrEee.Objects.Civilization; +using FrEee.Objects.Space; + +namespace FrEee.Gameplay.Commands.Fleets; +public interface ICreateFleetCommand + : ICommand +{ + /// + /// The fleet to create. + /// + Fleet Fleet { get; set; } + + /// + /// The sector to place the fleet in. + /// + Sector Sector { get; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Gameplay/Commands/Fleets/IDisbandFleetCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Fleets/IDisbandFleetCommand.cs new file mode 100644 index 000000000..3b138a837 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Fleets/IDisbandFleetCommand.cs @@ -0,0 +1,8 @@ +using FrEee.Objects.Civilization; +using FrEee.Objects.Space; + +namespace FrEee.Gameplay.Commands.Fleets; +public interface IDisbandFleetCommand + : ICommand +{ +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Gameplay/Commands/Fleets/IFleetCommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/Fleets/IFleetCommandFactory.cs new file mode 100644 index 000000000..5ff86e719 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Fleets/IFleetCommandFactory.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Space; + +namespace FrEee.Gameplay.Commands.Fleets; + +/// +/// Builds various types of commands used for managing fleets. +/// +public interface IFleetCommandFactory +{ + ICreateFleetCommand CreateFleet(Fleet fleet, Sector sector); + + IDisbandFleetCommand DisbandFleet(Fleet fleet); + + IJoinFleetCommand JoinFleet(IMobileSpaceObject vehicle, Fleet fleet); + + IJoinFleetCommand JoinFleet(IMobileSpaceObject vehicle, ICreateFleetCommand command); + + ILeaveFleetCommand LeaveFleet(IMobileSpaceObject vehicle); +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Gameplay/Commands/Fleets/IJoinFleetCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Fleets/IJoinFleetCommand.cs new file mode 100644 index 000000000..2b548cda0 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Fleets/IJoinFleetCommand.cs @@ -0,0 +1,16 @@ +using FrEee.Objects.Space; + +namespace FrEee.Gameplay.Commands.Fleets; +public interface IJoinFleetCommand + : ICommand +{ + /// + /// The command that creates the fleet to join (if the fleet is newly created on the client side). + /// + ICreateFleetCommand CreateFleetCommand { get; set; } + + /// + /// The fleet to join. + /// + Fleet Fleet { get; set; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Gameplay/Commands/Fleets/ILeaveFleetCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Fleets/ILeaveFleetCommand.cs new file mode 100644 index 000000000..57b494d87 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Fleets/ILeaveFleetCommand.cs @@ -0,0 +1,8 @@ +using FrEee.Objects.Civilization; +using FrEee.Objects.Space; + +namespace FrEee.Gameplay.Commands.Fleets; +public interface ILeaveFleetCommand + : ICommand +{ +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/ICommand.cs b/FrEee.Core.Domain/Gameplay/Commands/ICommand.cs similarity index 96% rename from FrEee.Core.Domain/Objects/Commands/ICommand.cs rename to FrEee.Core.Domain/Gameplay/Commands/ICommand.cs index cc71b825c..8aec99593 100644 --- a/FrEee.Core.Domain/Objects/Commands/ICommand.cs +++ b/FrEee.Core.Domain/Gameplay/Commands/ICommand.cs @@ -2,7 +2,7 @@ using FrEee.Objects.GameState; using System.Collections.Generic; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands; /// /// A command to some object. diff --git a/FrEee.Core.Domain/Gameplay/Commands/ICommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/ICommandFactory.cs new file mode 100644 index 000000000..f7da85f1f --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/ICommandFactory.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FrEee.Gameplay.Commands; + +/// +/// Builds various types of used by the game. +/// +public interface ICommandFactory +{ + // TODO: split these out into separate factories for each category and add parameters + ICommand Research(); +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Gameplay/Commands/IToggleCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/IToggleCommand.cs new file mode 100644 index 000000000..a6315e1a4 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/IToggleCommand.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; + +namespace FrEee.Gameplay.Commands; + +/// +/// A command which enables or disables something. +/// +public interface IToggleCommand + : ICommand +{ + /// + /// Is the toggle enabled or disabled? + /// + bool IsToggleEnabled { get; set; } +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Messages/IDeleteMessageCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Messages/IDeleteMessageCommand.cs new file mode 100644 index 000000000..04bd39310 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Messages/IDeleteMessageCommand.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FrEee.Gameplay.Commands.Messages; +public interface IDeleteMessageCommand + : IMessageCommand +{ +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Messages/IMessageCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Messages/IMessageCommand.cs new file mode 100644 index 000000000..178af166c --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Messages/IMessageCommand.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Diplomacy.Messages; + +namespace FrEee.Gameplay.Commands.Messages; + +public interface IMessageCommand + : ICommand +{ + IMessage Message { get; } +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Messages/IMessageCommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/Messages/IMessageCommandFactory.cs new file mode 100644 index 000000000..bf45da562 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Messages/IMessageCommandFactory.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Diplomacy.Messages; + +namespace FrEee.Gameplay.Commands.Messages; + +/// +/// Builds commands allowing players to manage diplomatic messages. +/// +public interface IMessageCommandFactory +{ + IDeleteMessageCommand DeleteMessage(IMessage message); + + ISendMessageCommand SendMessage(IMessage message); +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Gameplay/Commands/Messages/ISendMessageCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Messages/ISendMessageCommand.cs new file mode 100644 index 000000000..4a6561b02 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Messages/ISendMessageCommand.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FrEee.Gameplay.Commands.Messages; +public interface ISendMessageCommand + : IMessageCommand +{ +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Ministers/IMinisterCommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/Ministers/IMinisterCommandFactory.cs new file mode 100644 index 000000000..ebf3a76f6 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Ministers/IMinisterCommandFactory.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands.Messages; + +namespace FrEee.Gameplay.Commands.Ministers; + +/// +/// Builds commands used to manage AI ministers for an empire. +/// +public interface IMinisterCommandFactory +{ + IToggleMinistersCommand ToggleMinisters(); +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Gameplay/Commands/Ministers/IToggleMinistersCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Ministers/IToggleMinistersCommand.cs new file mode 100644 index 000000000..605d90688 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Ministers/IToggleMinistersCommand.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Utility; + +namespace FrEee.Gameplay.Commands.Ministers; + +public interface IToggleMinistersCommand + : ICommand +{ + SafeDictionary> EnabledMinisters { get; set; } +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Notes/INoteCommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/Notes/INoteCommandFactory.cs new file mode 100644 index 000000000..a7333346a --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Notes/INoteCommandFactory.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; + +namespace FrEee.Gameplay.Commands.Notes; + +/// +/// Builds various types of commands used for managing notes. +public interface INoteCommandFactory +{ + ICommand ClearPlayerNote(IReferrable target); + + ICommand ClearPrivateName(Empire empire, INameable target); + + ICommand SetPlayerInfo(Empire empire, PlayerInfo playerInfo); + + ICommand SetPlayerNote(IReferrable target, string note); + + ICommand SetPrivateName(Empire empire, INameable target, string name); + + ICommand SetPublicName(INameable target, string name); +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Notes/ISetPlayerInfoCommnad.cs b/FrEee.Core.Domain/Gameplay/Commands/Notes/ISetPlayerInfoCommnad.cs new file mode 100644 index 000000000..c1a2cdfee --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Notes/ISetPlayerInfoCommnad.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; + +namespace FrEee.Gameplay.Commands.Notes; + +/// +/// A command which sets the of an . +/// +public interface ISetPlayerInfoCommand + : ICommand +{ + PlayerInfo PlayerInfo { get; set; } +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Orders/IAddOrderCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Orders/IAddOrderCommand.cs new file mode 100644 index 000000000..e386a2b52 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Orders/IAddOrderCommand.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; + +namespace FrEee.Gameplay.Commands.Orders; + +/// +/// A command which adds an to an +/// +public interface IAddOrderCommand + : IOrderCommand +{ +} diff --git a/FrEee.Core.Domain/Objects/Commands/IOrderCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Orders/IOrderCommand.cs similarity index 87% rename from FrEee.Core.Domain/Objects/Commands/IOrderCommand.cs rename to FrEee.Core.Domain/Gameplay/Commands/Orders/IOrderCommand.cs index 822298006..953ff7d81 100644 --- a/FrEee.Core.Domain/Objects/Commands/IOrderCommand.cs +++ b/FrEee.Core.Domain/Gameplay/Commands/Orders/IOrderCommand.cs @@ -1,6 +1,6 @@ using FrEee.Objects.Civilization.Orders; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Orders; /// /// A command to manipulate an object's order queue. diff --git a/FrEee.Core.Domain/Gameplay/Commands/Orders/IOrderCommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/Orders/IOrderCommandFactory.cs new file mode 100644 index 000000000..1f875a9ee --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Orders/IOrderCommandFactory.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; + +namespace FrEee.Gameplay.Commands.Orders; + +/// +/// Builds various types of commands used for managing s. +/// +public interface IOrderCommandFactory +{ + IAddOrderCommand AddOrder(IOrderable target, IOrder order); + + IOrderCommand RearrangeOrders(T target, IOrder order, int deltaPosition) + where T : IOrderable; + + IRemoveOrderCommand RemoveOrder(IOrderable target, IOrder order); + + IToggleOrdersOnHoldCommand ToggleOrdersOnHold(IOrderable target, bool areOrdersOnHold); + + IToggleRepeatOrdersCommand ToggleRepeatOrders(IOrderable target, bool areRepeatOrdersEnabled); +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Orders/IRemoveOrderCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Orders/IRemoveOrderCommand.cs new file mode 100644 index 000000000..148d970ec --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Orders/IRemoveOrderCommand.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; + +namespace FrEee.Gameplay.Commands.Orders; + +/// +/// A command which removes an from an +/// +public interface IRemoveOrderCommand + : IOrderCommand +{ +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Orders/IToggleOrdersOnHoldCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Orders/IToggleOrdersOnHoldCommand.cs new file mode 100644 index 000000000..d56b3a9ee --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Orders/IToggleOrdersOnHoldCommand.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; + +namespace FrEee.Gameplay.Commands.Orders; + +/// +/// A command which enables or disables orders being on hold for an . +/// +public interface IToggleOrdersOnHoldCommand + : IToggleCommand +{ +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/Orders/IToggleRepeatOrdersCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/Orders/IToggleRepeatOrdersCommand.cs new file mode 100644 index 000000000..36ed7173f --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Orders/IToggleRepeatOrdersCommand.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; + +namespace FrEee.Gameplay.Commands.Orders; + +/// +/// A command which enables or disables repeat orders for an . +/// +public interface IToggleRepeatOrdersCommand + : IToggleCommand +{ +} diff --git a/FrEee.Core.Domain/Gameplay/Commands/ResearchCommand.cs b/FrEee.Core.Domain/Gameplay/Commands/ResearchCommand.cs new file mode 100644 index 000000000..f803db2b3 --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/ResearchCommand.cs @@ -0,0 +1,57 @@ +using FrEee.Objects.Civilization; +using FrEee.Extensions; +using System.Linq; +using Tech = FrEee.Objects.Technology.Technology; +using FrEee.Modding; +using FrEee.Objects.Technology; + +namespace FrEee.Gameplay.Commands; + +/// +/// Command to set an empire's research priorities. +/// +public class ResearchCommand : Command +{ + public ResearchCommand() + : base(Empire.Current) + { + Spending = new ModReferenceKeyedDictionary(); + Queue = new ModReferenceList(); + } + + public ModReferenceList Queue { get; private set; } + public ModReferenceKeyedDictionary Spending { get; private set; } + + public override void Execute() + { + // make sure spending is not over 100% + var totalSpending = Spending.Sum(kvp => kvp.Value); + if (totalSpending > 100) + { + foreach (var kvp in Spending.ToArray()) + { + Spending[kvp.Key] = kvp.Value / totalSpending / 100; + } + } + + // make sure no techs are prioritized or queued that the empire can't research + foreach (var kvp in Spending.ToArray()) + { + if (!Executor.HasUnlocked(kvp.Key)) + Spending[kvp.Key] = 0; + } + foreach (Technology tech in Queue.ToArray()) + { + if (!Executor.HasUnlocked(tech)) + Queue.Remove(tech); + } + + // save to empire + Executor.ResearchSpending.Clear(); + foreach (var kvp in Spending) + Executor.ResearchSpending.Add(kvp); + Executor.ResearchQueue.Clear(); + foreach (var tech in Queue) + Executor.ResearchQueue.Add(tech); + } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Gameplay/Commands/Waypoints/IWaypointCommandFactory.cs b/FrEee.Core.Domain/Gameplay/Commands/Waypoints/IWaypointCommandFactory.cs new file mode 100644 index 000000000..253b6e13b --- /dev/null +++ b/FrEee.Core.Domain/Gameplay/Commands/Waypoints/IWaypointCommandFactory.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; + +namespace FrEee.Gameplay.Commands.Waypoints; + +/// +/// Builds commands to manage waypoints. +/// +public interface IWaypointCommandFactory +{ + ICommand CreateWaypoint(Waypoint waypoint); + + ICommand DeleteWaypoint(Waypoint waypoint); + + ICommand HotkeyWaypoint(Waypoint waypoint, int hotkey, bool redirect); +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Modding/DamageType.cs b/FrEee.Core.Domain/Modding/DamageType.cs index 31ed638e2..7528c4c99 100644 --- a/FrEee.Core.Domain/Modding/DamageType.cs +++ b/FrEee.Core.Domain/Modding/DamageType.cs @@ -192,6 +192,11 @@ public string Name /// public IDictionary TemplateParameters { get; set; } + public void Dispose() + { + // nothing to do here + } + public override string ToString() { return Name; diff --git a/FrEee.Core.Domain/Modding/EventTemplate.cs b/FrEee.Core.Domain/Modding/EventTemplate.cs index 099a1e7be..c4ba01fa9 100644 --- a/FrEee.Core.Domain/Modding/EventTemplate.cs +++ b/FrEee.Core.Domain/Modding/EventTemplate.cs @@ -86,6 +86,11 @@ public Event Instantiate() return new Event(this); } + public void Dispose() + { + // nothing to do here + } + public override string ToString() { return Type.Name; diff --git a/FrEee.Core.Domain/Modding/EventType.cs b/FrEee.Core.Domain/Modding/EventType.cs index 194a01600..3430878b0 100644 --- a/FrEee.Core.Domain/Modding/EventType.cs +++ b/FrEee.Core.Domain/Modding/EventType.cs @@ -54,6 +54,11 @@ public EventType() /// public IDictionary TemplateParameters { get; set; } + public void Dispose() + { + // nothing to do here + } + public override string ToString() { return Name; diff --git a/FrEee.Core.Domain/Modding/IModObject.cs b/FrEee.Core.Domain/Modding/IModObject.cs index e2ca03c4f..7dc940f99 100644 --- a/FrEee.Core.Domain/Modding/IModObject.cs +++ b/FrEee.Core.Domain/Modding/IModObject.cs @@ -1,4 +1,5 @@ using FrEee.Objects.GameState; +using System; using System.Collections.Generic; namespace FrEee.Modding; @@ -6,7 +7,7 @@ namespace FrEee.Modding; /// /// An object which can be stored in mod files. /// -public interface IModObject : INamed +public interface IModObject : INamed, IDisposable { bool IsDisposed { get; } diff --git a/FrEee.Core.Domain/Modding/Scripts/PythonScript.cs b/FrEee.Core.Domain/Modding/Scripts/PythonScript.cs index bc60446c0..70df61a81 100644 --- a/FrEee.Core.Domain/Modding/Scripts/PythonScript.cs +++ b/FrEee.Core.Domain/Modding/Scripts/PythonScript.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; namespace FrEee.Modding.Scripts; diff --git a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Actions/DiplomaticAction.cs b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Actions/DiplomaticAction.cs index 5721d29f0..f2a9c2f63 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Actions/DiplomaticAction.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Actions/DiplomaticAction.cs @@ -1,4 +1,4 @@ -using FrEee.Objects.Commands; +using FrEee.Gameplay.Commands; using FrEee.Objects.GameState; using FrEee.Serialization; diff --git a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Clauses/AllianceClause.cs b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Clauses/AllianceClause.cs index d53f17589..d24ff9ea8 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Clauses/AllianceClause.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Clauses/AllianceClause.cs @@ -1,9 +1,10 @@ -using FrEee.Objects.Commands; -using FrEee.Extensions; +using FrEee.Extensions; using System.Collections.Generic; using System.Linq; using FrEee.Objects.Civilization.Diplomacy.Messages; using FrEee.Objects.Civilization.Diplomacy.Actions; +using FrEee.Gameplay.Commands; +using FrEee.Utility; namespace FrEee.Objects.Civilization.Diplomacy.Clauses; @@ -85,7 +86,7 @@ private void DeclareWar(Empire emp) response.Recipient = emp; response.Text = "Our allies have forced our hand. We must declare war!"; response.Action = new DeclareWarAction(emp); - var cmd = new SendMessageCommand(response); + var cmd = DIRoot.MessageCommands.SendMessage(response); Empire.Current.Commands.Add(cmd); Empire.Current.TriggerHappinessChange(hm => hm.TreatyWar); emp.TriggerHappinessChange(hm => hm.TreatyWar); diff --git a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Messages/Message.cs b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Messages/Message.cs index 2f417ea9e..8c6b1288f 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Messages/Message.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Messages/Message.cs @@ -1,10 +1,11 @@ -using FrEee.Objects.Commands; -using FrEee.Serialization; +using FrEee.Serialization; using FrEee.Extensions; using System.Collections.Generic; using System.Drawing; using System.Linq; using FrEee.Objects.GameState; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Messages; namespace FrEee.Objects.Civilization.Diplomacy.Messages; @@ -106,7 +107,7 @@ public void Dispose() if (Owner != null) { // HACK - how could a diplomatic message have no owner? - var cmd = Owner.Commands.OfType().SingleOrDefault(c => c.Message == this); + var cmd = Owner.Commands.OfType().SingleOrDefault(c => c.Message == this); if (cmd != null) Owner.Commands.Remove(cmd); } diff --git a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Proposal.cs b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Proposal.cs index e803bc8e6..ca73bda8d 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Proposal.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Diplomacy/Proposal.cs @@ -1,9 +1,9 @@ -using FrEee.Objects.Commands; -using FrEee.Serialization; +using FrEee.Serialization; using FrEee.Extensions; using System.Collections.Generic; using System.Linq; using FrEee.Objects.GameState; +using FrEee.Gameplay.Commands; namespace FrEee.Objects.Civilization.Diplomacy; diff --git a/FrEee.Core.Domain/Objects/Civilization/Empire.cs b/FrEee.Core.Domain/Objects/Civilization/Empire.cs index 97285af17..03fa144da 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Empire.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Empire.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization.Diplomacy.Clauses; -using FrEee.Objects.Commands; using FrEee.Objects.LogMessages; using FrEee.Objects.Space; using FrEee.Objects.Vehicles; @@ -22,6 +21,8 @@ using FrEee.Processes.AI; using FrEee.Modding.Abilities; using FrEee.Processes.Setup; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Orders; namespace FrEee.Objects.Civilization; @@ -98,7 +99,7 @@ public ModReferenceKeyedDictionary AccumulatedResearch /// /// Arbitrary data stored by the AI to maintain state between turns. /// - public DynamicDictionary AINotes { get; internal set; } + public DynamicDictionary AINotes { get; set; } /// /// The names of any ministers that are enabled, keyed by category. @@ -786,7 +787,7 @@ public void BelayOrder(T target, IOrder order) where T : IOrderable { target.RemoveOrder(order); - var cmd = new RemoveOrderCommand(target, order); + var cmd = DIRoot.OrderCommands.RemoveOrder(target, order); Commands.Add(cmd); } @@ -1038,7 +1039,7 @@ public void IssueOrder(T target, IOrder order) where T : IOrderable { target.AddOrder(order); - var cmd = new AddOrderCommand(target, order); + var cmd = DIRoot.OrderCommands.AddOrder(target, order); Commands.Add(cmd); } diff --git a/FrEee.Core.Domain/Objects/Civilization/Waypoint.cs b/FrEee.Core.Domain/Objects/Civilization/Waypoint.cs index cbd5ecd99..b74b57ab8 100644 --- a/FrEee.Core.Domain/Objects/Civilization/Waypoint.cs +++ b/FrEee.Core.Domain/Objects/Civilization/Waypoint.cs @@ -54,7 +54,7 @@ public double Timestamp /// Number of vehicles whose orders were altered when this waypoint was deleted. /// [DoNotSerialize] - internal int AlteredQueuesOnDelete { get; private set; } + public int AlteredQueuesOnDelete { get; private set; } private GameReference owner { get; set; } diff --git a/FrEee.Core.Domain/Objects/Commands/ClearPlayerNoteCommand.cs b/FrEee.Core.Domain/Objects/Commands/ClearPlayerNoteCommand.cs deleted file mode 100644 index 7697685f9..000000000 --- a/FrEee.Core.Domain/Objects/Commands/ClearPlayerNoteCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -using FrEee.Objects.Civilization; -using FrEee.Utility; -using System.Collections.Generic; - -namespace FrEee.Objects.Commands; - -/// -/// Toggles AI ministers. -/// -public class MinisterToggleCommand : Command -{ - public MinisterToggleCommand() - : base(Empire.Current) - { - } - - public SafeDictionary> EnabledMinisters { get; set; } - - public override void Execute() - { - if (Executor.AI == null) - Executor.RecordLog(Executor, $"Could not toggle AI ministers for {Executor} because there is no AI for this empire.", LogMessages.LogMessageType.Error); - else - Executor.EnabledMinisters = EnabledMinisters; - } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/Command.cs b/FrEee.Core.Domain/Objects/Commands/Command.cs deleted file mode 100644 index 5c1f76ac9..000000000 --- a/FrEee.Core.Domain/Objects/Commands/Command.cs +++ /dev/null @@ -1,66 +0,0 @@ -using FrEee.Objects.Civilization; -using FrEee.Objects.GameState; -using FrEee.Serialization; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace FrEee.Objects.Commands; - -/// -/// A generic command. -/// -/// -[Serializable] -public abstract class Command : ICommand - where T : IReferrable -{ - protected Command(T target) - { - Issuer = Empire.Current; - Executor = target; - } - - [DoNotSerialize] - public T Executor { get { return executor; } set { executor = value; } } - - IReferrable ICommand.Executor - { - get { return Executor; } - } - - public long ExecutorID { get { return executor.ID; } } - - public bool IsDisposed { get; set; } - - [DoNotSerialize] - public Empire Issuer { get { return issuer; } set { issuer = value; } } - - public virtual IEnumerable NewReferrables - { - get - { - yield break; - } - } - - protected GameReference executor { get; set; } - - private GameReference issuer { get; set; } - - public abstract void Execute(); - - public virtual void ReplaceClientIDs(IDictionary idmap, ISet done = null) - { - if (done == null) - done = new HashSet(); - if (!done.Contains(this)) - { - done.Add(this); - issuer.ReplaceClientIDs(idmap, done); - executor.ReplaceClientIDs(idmap, done); - foreach (var r in NewReferrables.OfType()) - r.ReplaceClientIDs(idmap, done); - } - } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/CreateDesignCommand.cs b/FrEee.Core.Domain/Objects/Commands/CreateDesignCommand.cs deleted file mode 100644 index 1eefe8f52..000000000 --- a/FrEee.Core.Domain/Objects/Commands/CreateDesignCommand.cs +++ /dev/null @@ -1,42 +0,0 @@ -using FrEee.Objects.Civilization; -using FrEee.Extensions; -using System; -using System.Collections.Generic; -using System.Linq; -using FrEee.Objects.Vehicles; -using FrEee.Objects.GameState; - -namespace FrEee.Objects.Commands; - -/// -/// A command to create a new vehicle design. -/// -[Serializable] -public class CreateDesignCommand : Command, ICreateDesignCommand where T : IVehicle -{ - public CreateDesignCommand(IDesign design) - : base(Empire.Current) - { - Design = design; - } - - IDesign ICreateDesignCommand.Design { get { return Design; } } - - public IDesign Design { get; set; } - - public override IEnumerable NewReferrables - { - get - { - yield return Design; - } - } - - public override void Execute() - { - Design.VehiclesBuilt = 0; // in case it was tested in the simulator - if (Design.Warnings.Any()) - Issuer.Log.Add(Design.CreateLogMessage("The " + Design.Name + " " + Design.VehicleTypeName + " design cannot be saved because it has warnings.", LogMessages.LogMessageType.Warning)); - Issuer.KnownDesigns.Add(Design); - } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/ResearchCommand.cs b/FrEee.Core.Domain/Objects/Commands/ResearchCommand.cs deleted file mode 100644 index 7d83be1b6..000000000 --- a/FrEee.Core.Domain/Objects/Commands/ResearchCommand.cs +++ /dev/null @@ -1,56 +0,0 @@ -using FrEee.Objects.Civilization; -using FrEee.Extensions; -using System.Linq; -using Tech = FrEee.Objects.Technology.Technology; -using FrEee.Modding; - -namespace FrEee.Objects.Commands; - -/// -/// Command to set an empire's research priorities. -/// -public class ResearchCommand : Command -{ - public ResearchCommand() - : base(Empire.Current) - { - Spending = new ModReferenceKeyedDictionary(); - Queue = new ModReferenceList(); - } - - public ModReferenceList Queue { get; private set; } - public ModReferenceKeyedDictionary Spending { get; private set; } - - public override void Execute() - { - // make sure spending is not over 100% - var totalSpending = Spending.Sum(kvp => kvp.Value); - if (totalSpending > 100) - { - foreach (var kvp in Spending.ToArray()) - { - Spending[kvp.Key] = kvp.Value / totalSpending / 100; - } - } - - // make sure no techs are prioritized or queued that the empire can't research - foreach (var kvp in Spending.ToArray()) - { - if (!Executor.HasUnlocked(kvp.Key)) - Spending[kvp.Key] = 0; - } - foreach (Technology.Technology tech in Queue.ToArray()) - { - if (!Executor.HasUnlocked(tech)) - Queue.Remove(tech); - } - - // save to empire - Executor.ResearchSpending.Clear(); - foreach (var kvp in Spending) - Executor.ResearchSpending.Add(kvp); - Executor.ResearchQueue.Clear(); - foreach (var tech in Queue) - Executor.ResearchQueue.Add(tech); - } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/SetObsoleteFlagCommand.cs b/FrEee.Core.Domain/Objects/Commands/SetObsoleteFlagCommand.cs deleted file mode 100644 index 507643cd0..000000000 --- a/FrEee.Core.Domain/Objects/Commands/SetObsoleteFlagCommand.cs +++ /dev/null @@ -1,76 +0,0 @@ -using FrEee.Serialization; -using FrEee.Extensions; -using System.Collections.Generic; -using FrEee.Objects.Vehicles; -using FrEee.Objects.GameState; - -namespace FrEee.Objects.Commands; - -/// -/// A command to enable or disable the obsolete flag on a design. -/// -public class SetObsoleteFlagCommand : Command -{ - public SetObsoleteFlagCommand(IDesign design, bool isObsolete) - : base(design) - { - if (design.IsNew) - NewDesign = design; - else - Design = design; - IsObsolete = isObsolete; - } - - /// - /// The design to set the flag on if it's already knwon by the server. - /// - [DoNotSerialize] - public IDesign Design { get { return design?.Value; } set { design = value.ReferViaGalaxy(); } } - - /// - /// The flag state to set. - /// - public bool IsObsolete { get; set; } - - /// - /// The design to set the flag on if it's only in the library and not in the game or it's a brand new design. - /// - public IDesign NewDesign { get; set; } - - public override IEnumerable NewReferrables - { - get - { - if (NewDesign != null) - yield return NewDesign; - } - } - - private GameReference design { get; set; } - - public override void Execute() - { - if (NewDesign != null) - { - // allows obsoleting designs that are on the library or newly created (not on the server yet) - Issuer.KnownDesigns.Add(NewDesign); - Design = NewDesign; - } - Design.IsObsolete = IsObsolete; - } - - public override void ReplaceClientIDs(IDictionary idmap, ISet done = null) - { - if (done == null) - done = new HashSet(); - if (!done.Contains(this)) - { - done.Add(this); - base.ReplaceClientIDs(idmap, done); - if (design != null) - design.ReplaceClientIDs(idmap, done); - if (NewDesign != null) - NewDesign.ReplaceClientIDs(idmap, done); - } - } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/ToggleOrdersOnHoldCommand.cs b/FrEee.Core.Domain/Objects/Commands/ToggleOrdersOnHoldCommand.cs deleted file mode 100644 index 36095c557..000000000 --- a/FrEee.Core.Domain/Objects/Commands/ToggleOrdersOnHoldCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using FrEee.Objects.Civilization; - -namespace FrEee.Objects.Commands; - -public class ToggleOrdersOnHoldCommand : Command -{ - public ToggleOrdersOnHoldCommand(IOrderable target, bool areOrdersOnHold) - : base(target) - { - AreOrdersOnHold = areOrdersOnHold; - } - - public bool AreOrdersOnHold { get; set; } - - public override void Execute() - { - Executor.AreOrdersOnHold = AreOrdersOnHold; - } -} diff --git a/FrEee.Core.Domain/Objects/Commands/ToggleRepeatOrdersCommand.cs b/FrEee.Core.Domain/Objects/Commands/ToggleRepeatOrdersCommand.cs deleted file mode 100644 index de67f1458..000000000 --- a/FrEee.Core.Domain/Objects/Commands/ToggleRepeatOrdersCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using FrEee.Objects.Civilization; - -namespace FrEee.Objects.Commands; - -public class ToggleRepeatOrdersCommand : Command -{ - public ToggleRepeatOrdersCommand(IOrderable target, bool areRepeatOrdersEnabled) - : base(target) - { - AreRepeatOrdersEnabled = areRepeatOrdersEnabled; - } - - public bool AreRepeatOrdersEnabled { get; set; } - - public override void Execute() - { - Executor.AreRepeatOrdersEnabled = AreRepeatOrdersEnabled; - } -} diff --git a/FrEee.Core.Domain/Objects/GameState/Game.cs b/FrEee.Core.Domain/Objects/GameState/Game.cs index 32813fdaf..88e4afb5c 100644 --- a/FrEee.Core.Domain/Objects/GameState/Game.cs +++ b/FrEee.Core.Domain/Objects/GameState/Game.cs @@ -1,14 +1,11 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Diplomacy.Clauses; -using FrEee.Processes.Combat.Grid; -using FrEee.Objects.Commands; using FrEee.Objects.Events; using FrEee.Objects.LogMessages; using FrEee.Modding; using FrEee.Utility; using FrEee.Serialization; using FrEee.Extensions; -using Microsoft.Scripting.Utils; using System; using System.Collections; using System.Collections.Generic; @@ -24,6 +21,8 @@ using FrEee.Processes.Setup; using FrEee.Modding.Scripts; using FrEee.Modding.Loaders; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Notes; namespace FrEee.Objects.GameState; @@ -158,7 +157,7 @@ public string ModPath /// /// The next tick size, for ship movement. /// - public double NextTickSize { get; internal set; } + public double NextTickSize { get; set; } /// /// Events which have been warned of and are pending execution. @@ -255,7 +254,7 @@ public int TurnsOfPeace /// Serialized string value of the game at the beginning of the turn. /// [DoNotSerialize] - internal string? StringValue + public string? StringValue { get { @@ -438,7 +437,7 @@ private void PopulatePropertyValues() /// /// Saves all empires' tech levels in the other empires for uniqueness calculations. /// - internal void SaveTechLevelsForUniqueness() + public void SaveTechLevelsForUniqueness() { if (Current.Setup.TechnologyUniqueness != 0) { @@ -795,7 +794,7 @@ public void MoveShips() && (!lastBattleTimestamps.ContainsKey(sector) || lastBattleTimestamps[sector] < Timestamp - (v.StrategicSpeed == 0 ? 1d : 1d / v.StrategicSpeed)))) // have we fought here too recently? { // resolve the battle - var battle = new SpaceBattle(sector); + var battle = DIRoot.Battles.BuildSpaceBattle(sector); battle.Resolve(); Battles.Add(battle); foreach (var emp in battle.Empires) @@ -883,9 +882,10 @@ public string SaveCommands() CleanGameState(); if (CurrentEmpire == null) throw new InvalidOperationException("Can't save commands without a current empire."); - foreach (var c in Empire.Current.Commands.OfType().ToArray()) + foreach (var c in Empire.Current.Commands.OfType().ToArray()) Empire.Current.Commands.Remove(c); - Empire.Current.Commands.Add(new SetPlayerInfoCommand(Empire.Current) { PlayerInfo = Empire.Current.PlayerInfo }); + var cmd = DIRoot.NoteCommands.SetPlayerInfo(Empire.Current, Empire.Current.PlayerInfo); + Empire.Current.Commands.Add(cmd); if (!Directory.Exists(FrEeeConstants.SaveGameDirectory)) Directory.CreateDirectory(FrEeeConstants.SaveGameDirectory); var filename = GetEmpireCommandsSavePath(CurrentEmpire); @@ -989,7 +989,7 @@ private static IList DeserializeCommands(Stream stream) return cmds; } - internal void LoadCommands(Empire emp, IList cmds) + public void LoadCommands(Empire emp, IList cmds) { cmds = cmds.Where(cmd => cmd != null).Distinct().ToList(); // HACK - why would we have null/duplicate commands in a plr file?! emp.Commands.Clear(); @@ -1091,4 +1091,13 @@ private void SpaceObjectCleanup() /// The game setup used to create this galaxy. /// public GameSetup Setup { get; set; } + + /// + /// Resets the treaty clause caches in this game. + /// + public void ResetTreatyClauseCaches() + { + GivenTreatyClauseCache = new SafeDictionary>(); + ReceivedTreatyClauseCache = new SafeDictionary>(); + } } diff --git a/FrEee.Core.Domain/Objects/Vehicles/Design.cs b/FrEee.Core.Domain/Objects/Vehicles/Design.cs index 4bb51f553..a5b4cf590 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/Design.cs +++ b/FrEee.Core.Domain/Objects/Vehicles/Design.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Technology; using FrEee.Modding; using FrEee.Modding.Templates; @@ -16,6 +15,9 @@ using FrEee.Objects.Civilization.CargoStorage; using FrEee.Objects.GameState; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Designs; +using FrEee.Gameplay.Commands.Orders; namespace FrEee.Objects.Vehicles; @@ -728,7 +730,7 @@ public IConstructionOrder CreateConstructionOrder(ConstructionQueue queue) public ICreateDesignCommand CreateCreationCommand() { - return new CreateDesignCommand(this); + return DIRoot.DesignCommands.CreateDesign(this); } public void Dispose() diff --git a/FrEee.Core.Domain/Objects/Vehicles/IDesign.cs b/FrEee.Core.Domain/Objects/Vehicles/IDesign.cs index fe08ddcef..08af87026 100644 --- a/FrEee.Core.Domain/Objects/Vehicles/IDesign.cs +++ b/FrEee.Core.Domain/Objects/Vehicles/IDesign.cs @@ -4,9 +4,9 @@ using FrEee.Utility; using System.Collections.Generic; using FrEee.Objects.Civilization.Construction; -using FrEee.Objects.Commands; using FrEee.Objects.GameState; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands.Designs; namespace FrEee.Objects.Vehicles; diff --git a/FrEee.Core.Domain/Processes/AI/AI.cs b/FrEee.Core.Domain/Processes/AI/AI.cs index 218d3a7f1..64d6a45e2 100644 --- a/FrEee.Core.Domain/Processes/AI/AI.cs +++ b/FrEee.Core.Domain/Processes/AI/AI.cs @@ -7,65 +7,54 @@ namespace FrEee.Processes.AI; /// -/// An AI script which has control over a domain. +/// Stock implementation of . /// -/// The type of domain. -/// The type of contextual data that the AI needs to be aware of. +/// +/// [Serializable] -public abstract class AI : IModObject +public abstract class AI + : IAI { - public AI(string name, IScript script, SafeDictionary> ministerNames) - { - Name = name; - Script = script; - MinisterNames = ministerNames; - } - - public bool IsDisposed { get; private set; } - - /// - /// The names of any ministers that the AI can use, keyed by category. - /// - public SafeDictionary> MinisterNames { get; private set; } - - - public string ModID { get; set; } - - public string Name - { - get; - private set; - } - - /// - /// The script to run. - /// - public IScript Script { get; protected set; } - - /// - /// Parameters from the mod meta templates. - /// - public IDictionary TemplateParameters { get; set; } - - /// - /// Allows the AI to act on its domain using information from its context. - /// - /// The AI's domain of control. - /// Contextual data that the AI needs to be aware of. - /// The names of any ministers that the player has enabled, keyed by category. - public abstract void Act(TDomain domain, TContext context, SafeDictionary> enabledMinisters); - - - public void Dispose() - { - // TODO - remove from mod? - IsDisposed = true; - } - - public override string ToString() - { - return Name; - } + public AI(string name, IScript script, SafeDictionary> ministerNames) + { + Name = name; + Script = script; + MinisterNames = ministerNames; + } + + public bool IsDisposed { get; private set; } + + public SafeDictionary> MinisterNames { get; private set; } + + + public string ModID { get; set; } + + public string Name + { + get; + private set; + } + + public IScript Script { get; protected set; } + + /// + /// Parameters from the mod meta templates. + /// + public IDictionary TemplateParameters { get; set; } + + public abstract void Act(TDomain domain, TContext context, SafeDictionary> enabledMinisters); + + + public void Dispose() + { + // TODO - remove from mod? + IsDisposed = true; + } + + public override string ToString() + { + return Name; + } diff --git a/FrEee.Core.Domain/Processes/AI/IAI.cs b/FrEee.Core.Domain/Processes/AI/IAI.cs new file mode 100644 index 000000000..6fa72fac5 --- /dev/null +++ b/FrEee.Core.Domain/Processes/AI/IAI.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using FrEee.Modding; +using FrEee.Modding.Scripts; +using FrEee.Utility; + +namespace FrEee.Processes.AI; + +/// +/// An AI script which has control over a domain. +/// +/// The type of domain. +/// The type of contextual data that the AI needs to be aware of. +public interface IAI + : IModObject +{ + /// + /// The names of any ministers that the AI can use, keyed by category. + /// + SafeDictionary> MinisterNames { get; } + + /// + /// The script to run. + /// + IScript Script { get; } + + /// + /// Allows the AI to act on its domain using information from its context. + /// + /// The AI's domain of control. + /// Contextual data that the AI needs to be aware of. + /// The names of any ministers that the player has enabled, keyed by category. + void Act(TDomain domain, TContext context, SafeDictionary> enabledMinisters); +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/BattleEvent.cs b/FrEee.Core.Domain/Processes/Combat/Events/BattleEvent.cs similarity index 80% rename from FrEee.Core.Domain/Processes/Combat/Grid/BattleEvent.cs rename to FrEee.Core.Domain/Processes/Combat/Events/BattleEvent.cs index 88b337bef..8f4465bdd 100644 --- a/FrEee.Core.Domain/Processes/Combat/Grid/BattleEvent.cs +++ b/FrEee.Core.Domain/Processes/Combat/Events/BattleEvent.cs @@ -3,8 +3,9 @@ using FrEee.Extensions; using FrEee.Objects.GameState; -namespace FrEee.Processes.Combat.Grid; +namespace FrEee.Processes.Combat.Events; +// TODO: make this and its subclassses records public abstract class BattleEvent : IBattleEvent { protected BattleEvent(IBattle battle, ICombatant combatant, Vector2 startPosition, Vector2 endPosition) @@ -27,7 +28,9 @@ public ICombatant Combatant set => combatant = value.ReferViaGalaxy(); } + // HACK: assumes 2D combat public Vector2 EndPosition { get; set; } - public Vector2 StartPosition { get; set; } + // HACK: assumes 2D combat + public Vector2 StartPosition { get; set; } } diff --git a/FrEee.Core.Domain/Processes/Combat/Events/CombatantAppearsEvent.cs b/FrEee.Core.Domain/Processes/Combat/Events/CombatantAppearsEvent.cs new file mode 100644 index 000000000..1931d8fbf --- /dev/null +++ b/FrEee.Core.Domain/Processes/Combat/Events/CombatantAppearsEvent.cs @@ -0,0 +1,15 @@ +using FrEee.Utility; +using System.Linq; + +namespace FrEee.Processes.Combat.Events; + +public class CombatantAppearsEvent : BattleEvent +{ + public CombatantAppearsEvent(IBattle battle, ICombatant combatant, Vector2 position) + : base(battle, combatant, position, position) + { + IsUnarmed = !(Combatant is Seeker) && !Combatant.Weapons.Any(); + } + + public bool IsUnarmed { get; set; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Events/CombatantDestroyedEvent.cs b/FrEee.Core.Domain/Processes/Combat/Events/CombatantDestroyedEvent.cs new file mode 100644 index 000000000..badf0f231 --- /dev/null +++ b/FrEee.Core.Domain/Processes/Combat/Events/CombatantDestroyedEvent.cs @@ -0,0 +1,11 @@ +using FrEee.Utility; +namespace FrEee.Processes.Combat.Events; + +public class CombatantDestroyedEvent : BattleEvent +{ + public CombatantDestroyedEvent(IBattle battle, ICombatant combatant, Vector2 position) + : base(battle, combatant, position, position) + { + } + +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Events/CombatantDisappearsEvent.cs b/FrEee.Core.Domain/Processes/Combat/Events/CombatantDisappearsEvent.cs new file mode 100644 index 000000000..27b994e04 --- /dev/null +++ b/FrEee.Core.Domain/Processes/Combat/Events/CombatantDisappearsEvent.cs @@ -0,0 +1,14 @@ +using FrEee.Utility; +using System; + +namespace FrEee.Processes.Combat.Events; + +[Obsolete("This class is deprecated; use CombatantDestroyedEvent if a combatant is destroyed.")] +public class CombatantDisappearsEvent : BattleEvent +{ + public CombatantDisappearsEvent(IBattle battle, ICombatant combatant, Vector2 position) + : base(battle, combatant, position, position) + { + } + +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Events/CombatantLaunchedEvent.cs b/FrEee.Core.Domain/Processes/Combat/Events/CombatantLaunchedEvent.cs new file mode 100644 index 000000000..6c0f707be --- /dev/null +++ b/FrEee.Core.Domain/Processes/Combat/Events/CombatantLaunchedEvent.cs @@ -0,0 +1,25 @@ +using FrEee.Utility; +using FrEee.Serialization; +using FrEee.Extensions; +using FrEee.Objects.GameState; + +namespace FrEee.Processes.Combat.Events; + +public class CombatantLaunchedEvent : BattleEvent +{ + public CombatantLaunchedEvent(IBattle battle, ICombatant launcher, ICombatant combatant, Vector2 position) + : base(battle, combatant, position, position) + { + Launcher = launcher; + } + + private GameReference launcher { get; set; } + + [DoNotSerialize] + public ICombatant Launcher + { + get => launcher?.Value ?? Battle?.StartCombatants?[launcher.ID]; + set => launcher = value.ReferViaGalaxy(); + } + +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Events/CombatantMovesEvent.cs b/FrEee.Core.Domain/Processes/Combat/Events/CombatantMovesEvent.cs new file mode 100644 index 000000000..0714f16c8 --- /dev/null +++ b/FrEee.Core.Domain/Processes/Combat/Events/CombatantMovesEvent.cs @@ -0,0 +1,10 @@ +using FrEee.Utility; +namespace FrEee.Processes.Combat.Events; + +public class CombatantMovesEvent : BattleEvent +{ + public CombatantMovesEvent(IBattle battle, ICombatant combatant, Vector2 here, Vector2 there) + : base(battle, combatant, here, there) + { + } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Events/CombatantsCollideEvent.cs b/FrEee.Core.Domain/Processes/Combat/Events/CombatantsCollideEvent.cs new file mode 100644 index 000000000..a921772d3 --- /dev/null +++ b/FrEee.Core.Domain/Processes/Combat/Events/CombatantsCollideEvent.cs @@ -0,0 +1,39 @@ +using FrEee.Utility; +using FrEee.Serialization; +using FrEee.Extensions; +using FrEee.Objects.GameState; + +namespace FrEee.Processes.Combat.Events; + +/// +/// When combatants collide - seeker detonation or ship ramming +/// +/// +public class CombatantsCollideEvent : BattleEvent +{ + public CombatantsCollideEvent(IBattle battle, ICombatant combatant, ICombatant target, Vector2 location, int combatantDamage, int targetDamage, bool wasCombatantDisarmed, bool wasTargetDisarmed) + : base(battle, combatant, location, location) + { + Target = target; + CombatantDamage = combatantDamage; + TargetDamage = targetDamage; + WasCombatantDisarmed = wasCombatantDisarmed; + WasTargetDisarmed = wasTargetDisarmed; + } + + + private GameReference target { get; set; } + + [DoNotSerialize] + public ICombatant Target + { + get => target?.Value ?? Battle?.StartCombatants?[target.ID]; + set => target = value.ReferViaGalaxy(); + } + + public int CombatantDamage { get; set; } + public int TargetDamage { get; set; } + + public bool WasCombatantDisarmed { get; set; } + public bool WasTargetDisarmed { get; set; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Events/WeaponFiresEvent.cs b/FrEee.Core.Domain/Processes/Combat/Events/WeaponFiresEvent.cs new file mode 100644 index 000000000..79fcf946f --- /dev/null +++ b/FrEee.Core.Domain/Processes/Combat/Events/WeaponFiresEvent.cs @@ -0,0 +1,49 @@ +using FrEee.Objects.Technology; +using FrEee.Utility; +using FrEee.Serialization; +using FrEee.Extensions; +using FrEee.Objects.GameState; + +namespace FrEee.Processes.Combat.Events; + +public class WeaponFiresEvent : BattleEvent +{ + public WeaponFiresEvent(IBattle battle, ICombatant attacker, Vector2 here, ICombatant target, Vector2 there, Component weapon, Hit hit, bool wasTargetDisarmed) + : base(battle, attacker, here, there) + { + Attacker = attacker; + Target = target; + Weapon = weapon; + Hit = hit; + IsHit = hit != null; + Damage = hit?.NominalDamage ?? 0; + WasTargetDisarmed = wasTargetDisarmed; + } + public bool IsHit { get; set; } + + private GameReference attacker { get; set; } + + private GameReference target { get; set; } + + [DoNotSerialize] + public ICombatant Attacker + { + get => attacker?.Value ?? Battle?.StartCombatants?[attacker.ID]; + set => attacker = value.ReferViaGalaxy(); + } + + [DoNotSerialize] + public ICombatant Target + { + get => target?.Value ?? Battle?.StartCombatants?[target.ID]; + set => target = value.ReferViaGalaxy(); + } + + // TODO - make this some sort of reference? + public Component Weapon { get; set; } + + public Hit Hit { get; set; } + public int Damage { get; set; } + + public bool WasTargetDisarmed { get; set; } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantAppearsEvent.cs b/FrEee.Core.Domain/Processes/Combat/Grid/CombatantAppearsEvent.cs deleted file mode 100644 index 1e9465072..000000000 --- a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantAppearsEvent.cs +++ /dev/null @@ -1,15 +0,0 @@ -using FrEee.Utility; -using System.Linq; - -namespace FrEee.Processes.Combat.Grid; - -public class CombatantAppearsEvent : BattleEvent -{ - public CombatantAppearsEvent(IBattle battle, ICombatant combatant, Vector2 position) - : base(battle, combatant, position, position) - { - IsUnarmed = !(Combatant is Seeker) && !Combatant.Weapons.Any(); - } - - public bool IsUnarmed { get; set; } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantDestroyedEvent.cs b/FrEee.Core.Domain/Processes/Combat/Grid/CombatantDestroyedEvent.cs deleted file mode 100644 index a212ec20c..000000000 --- a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantDestroyedEvent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using FrEee.Utility; -namespace FrEee.Processes.Combat.Grid; - -public class CombatantDestroyedEvent : BattleEvent -{ - public CombatantDestroyedEvent(IBattle battle, ICombatant combatant, Vector2 position) - : base(battle, combatant, position, position) - { - } - -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantDisappearsEvent.cs b/FrEee.Core.Domain/Processes/Combat/Grid/CombatantDisappearsEvent.cs deleted file mode 100644 index 4d4f58195..000000000 --- a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantDisappearsEvent.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FrEee.Utility; -using System; - -namespace FrEee.Processes.Combat.Grid; - -[Obsolete("This class is deprecated; use CombatantDestroyedEvent if a combatant is destroyed.")] -public class CombatantDisappearsEvent : BattleEvent -{ - public CombatantDisappearsEvent(IBattle battle, ICombatant combatant, Vector2 position) - : base(battle, combatant, position, position) - { - } - -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantLaunchedEvent.cs b/FrEee.Core.Domain/Processes/Combat/Grid/CombatantLaunchedEvent.cs deleted file mode 100644 index 6ac6784c3..000000000 --- a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantLaunchedEvent.cs +++ /dev/null @@ -1,25 +0,0 @@ -using FrEee.Utility; -using FrEee.Serialization; -using FrEee.Extensions; -using FrEee.Objects.GameState; - -namespace FrEee.Processes.Combat.Grid; - -public class CombatantLaunchedEvent : BattleEvent -{ - public CombatantLaunchedEvent(Battle battle, ICombatant launcher, ICombatant combatant, Vector2 position) - : base(battle, combatant, position, position) - { - Launcher = launcher; - } - - private GameReference launcher { get; set; } - - [DoNotSerialize] - public ICombatant Launcher - { - get => launcher?.Value ?? Battle?.StartCombatants?[launcher.ID]; - set => launcher = value.ReferViaGalaxy(); - } - -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantMovesEvent.cs b/FrEee.Core.Domain/Processes/Combat/Grid/CombatantMovesEvent.cs deleted file mode 100644 index 72def4263..000000000 --- a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantMovesEvent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using FrEee.Utility; -namespace FrEee.Processes.Combat.Grid; - -public class CombatantMovesEvent : BattleEvent -{ - public CombatantMovesEvent(Battle battle, ICombatant combatant, Vector2 here, Vector2 there) - : base(battle, combatant, here, there) - { - } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantsCollideEvent.cs b/FrEee.Core.Domain/Processes/Combat/Grid/CombatantsCollideEvent.cs deleted file mode 100644 index 28bbb001f..000000000 --- a/FrEee.Core.Domain/Processes/Combat/Grid/CombatantsCollideEvent.cs +++ /dev/null @@ -1,39 +0,0 @@ -using FrEee.Utility; -using FrEee.Serialization; -using FrEee.Extensions; -using FrEee.Objects.GameState; - -namespace FrEee.Processes.Combat.Grid; - -/// -/// When combatants collide - seeker detonation or ship ramming -/// -/// -public class CombatantsCollideEvent : BattleEvent -{ - public CombatantsCollideEvent(Battle battle, ICombatant combatant, ICombatant target, Vector2 location, int combatantDamage, int targetDamage, bool wasCombatantDisarmed, bool wasTargetDisarmed) - : base(battle, combatant, location, location) - { - Target = target; - CombatantDamage = combatantDamage; - TargetDamage = targetDamage; - WasCombatantDisarmed = wasCombatantDisarmed; - WasTargetDisarmed = wasTargetDisarmed; - } - - - private GameReference target { get; set; } - - [DoNotSerialize] - public ICombatant Target - { - get => target?.Value ?? Battle?.StartCombatants?[target.ID]; - set => target = value.ReferViaGalaxy(); - } - - public int CombatantDamage { get; set; } - public int TargetDamage { get; set; } - - public bool WasCombatantDisarmed { get; set; } - public bool WasTargetDisarmed { get; set; } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/WeaponFiresEvent.cs b/FrEee.Core.Domain/Processes/Combat/Grid/WeaponFiresEvent.cs deleted file mode 100644 index 36e1e39ca..000000000 --- a/FrEee.Core.Domain/Processes/Combat/Grid/WeaponFiresEvent.cs +++ /dev/null @@ -1,49 +0,0 @@ -using FrEee.Objects.Technology; -using FrEee.Utility; -using FrEee.Serialization; -using FrEee.Extensions; -using FrEee.Objects.GameState; - -namespace FrEee.Processes.Combat.Grid; - -public class WeaponFiresEvent : BattleEvent -{ - public WeaponFiresEvent(Battle battle, ICombatant attacker, Vector2 here, ICombatant target, Vector2 there, Component weapon, Hit hit, bool wasTargetDisarmed) - : base(battle, attacker, here, there) - { - Attacker = attacker; - Target = target; - Weapon = weapon; - Hit = hit; - IsHit = hit != null; - Damage = hit?.NominalDamage ?? 0; - WasTargetDisarmed = wasTargetDisarmed; - } - public bool IsHit { get; set; } - - private GameReference attacker { get; set; } - - private GameReference target { get; set; } - - [DoNotSerialize] - public ICombatant Attacker - { - get => attacker?.Value ?? Battle?.StartCombatants?[attacker.ID]; - set => attacker = value.ReferViaGalaxy(); - } - - [DoNotSerialize] - public ICombatant Target - { - get => target?.Value ?? Battle?.StartCombatants?[target.ID]; - set => target = value.ReferViaGalaxy(); - } - - // TODO - make this some sort of reference? - public Component Weapon { get; set; } - - public Hit Hit { get; set; } - public int Damage { get; set; } - - public bool WasTargetDisarmed { get; set; } -} \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/IBattle.cs b/FrEee.Core.Domain/Processes/Combat/IBattle.cs index f49306ffb..c6af5fdaf 100644 --- a/FrEee.Core.Domain/Processes/Combat/IBattle.cs +++ b/FrEee.Core.Domain/Processes/Combat/IBattle.cs @@ -16,6 +16,11 @@ public interface IBattle : INamed, IPictorial, ILocated double Timestamp { get; } IDictionary StartCombatants { get; } IDictionary EndCombatants { get; } + int GetDiameter(int round); + int Duration { get; } + IList> UpperLeft { get; } // HACK: this list data structure is specific to turn based battles + IList> LowerRight { get; } // HACK: this list data structure is specific to turn based battles + List> Events { get; } // HACK: this list data structure is specific to turn based battles - void Resolve(); + void Resolve(); } \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/IBattleEvent.cs b/FrEee.Core.Domain/Processes/Combat/IBattleEvent.cs similarity index 83% rename from FrEee.Core.Domain/Processes/Combat/Grid/IBattleEvent.cs rename to FrEee.Core.Domain/Processes/Combat/IBattleEvent.cs index 8830de21e..64410b131 100644 --- a/FrEee.Core.Domain/Processes/Combat/Grid/IBattleEvent.cs +++ b/FrEee.Core.Domain/Processes/Combat/IBattleEvent.cs @@ -1,5 +1,6 @@ using FrEee.Utility; -namespace FrEee.Processes.Combat.Grid; + +namespace FrEee.Processes.Combat; public interface IBattleEvent { diff --git a/FrEee.Core.Domain/Processes/Combat/IBattleFactory.cs b/FrEee.Core.Domain/Processes/Combat/IBattleFactory.cs new file mode 100644 index 000000000..c326a4038 --- /dev/null +++ b/FrEee.Core.Domain/Processes/Combat/IBattleFactory.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Space; + +namespace FrEee.Processes.Combat; + +/// +/// Builds battles. +/// +public interface IBattleFactory +{ + /// + /// Builds a space battle. + /// + /// + /// + IBattle BuildSpaceBattle(Sector location); + + /// + /// Builds a ground battle. + /// + /// + /// + IBattle BuildGroundBattle(Planet location); +} diff --git a/FrEee.Core.Domain/Processes/ITurnProcessor.cs b/FrEee.Core.Domain/Processes/ITurnProcessor.cs new file mode 100644 index 000000000..f1af381ac --- /dev/null +++ b/FrEee.Core.Domain/Processes/ITurnProcessor.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using FrEee.Objects.Civilization; +using FrEee.Objects.GameState; +using FrEee.Utility; + +namespace FrEee.Processes; + +/// +/// Processes turns. +/// +public interface ITurnProcessor +{ + /// + /// Processes the turn. + /// + /// Stop processing if PLR files are missing? + /// Player empires which did not submit commands and are not defeated. + /// if the current empire is not null, or this game is not the current game. + IEnumerable ProcessTurn(Game game, bool safeMode, Status? status = null, double desiredProgress = 1); +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Utility/DIRoot.cs b/FrEee.Core.Domain/Utility/DIRoot.cs new file mode 100644 index 000000000..f94728a57 --- /dev/null +++ b/FrEee.Core.Domain/Utility/DIRoot.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands.Designs; +using FrEee.Gameplay.Commands.Fleets; +using FrEee.Gameplay.Commands.Messages; +using FrEee.Gameplay.Commands.Ministers; +using FrEee.Gameplay.Commands.Notes; +using FrEee.Gameplay.Commands.Orders; +using FrEee.Gameplay.Commands.Waypoints; +using FrEee.Processes; +using FrEee.Processes.Combat; + +namespace FrEee.Utility; + +/// +/// Wrapper for that exposes various services used by FrEee. +/// +public static class DIRoot +{ + /// + /// Processes turns. + /// + public static ITurnProcessor TurnProcessor => DI.Get(); + + /// + /// Manages battles. + /// + public static IBattleFactory Battles => DI.Get(); + + /// + /// Allows players to manage designs. + /// + public static IDesignCommandFactory DesignCommands => DI.Get(); + + /// + /// Allows players to manage fleets. + /// + public static IFleetCommandFactory FleetCommands => DI.Get(); + + /// + /// Allows players to manage diplomatic messages. + /// + public static IMessageCommandFactory MessageCommands => DI.Get(); + + /// + /// Allows players to manage AI ministers. + /// + public static IMinisterCommandFactory MinisterCommands => DI.Get(); + + /// + /// Allows players to manage notes. + /// + public static INoteCommandFactory NoteCommands => DI.Get(); + + /// + /// Allows players to issue orders. + /// + public static IOrderCommandFactory OrderCommands => DI.Get(); + + /// + /// Allows players to manage waypoints. + /// + public static IWaypointCommandFactory WaypointCommands => DI.Get(); +} diff --git a/FrEee.Core.Utility/FrEee.Core.Utility.csproj b/FrEee.Core.Utility/FrEee.Core.Utility.csproj index cd07aa838..636563123 100644 --- a/FrEee.Core.Utility/FrEee.Core.Utility.csproj +++ b/FrEee.Core.Utility/FrEee.Core.Utility.csproj @@ -14,6 +14,7 @@ + diff --git a/FrEee.Core.Utility/Utility/DI.cs b/FrEee.Core.Utility/Utility/DI.cs new file mode 100644 index 000000000..b5a1e8958 --- /dev/null +++ b/FrEee.Core.Utility/Utility/DI.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace FrEee.Utility +{ + /// + /// Manages dependency injection for the game. + /// + public static class DI + { + private static readonly HostApplicationBuilder builder = Host.CreateApplicationBuilder(); + + private static IHost? host; + + /// + /// Registers a singleton service. + /// + /// + /// + /// + public static void RegisterSingleton() + where TInterface : class + where TImplementation : class, TInterface + { + Task.Run(async () => + { + if (host is not null) + { + await host.StopAsync(); + } + + builder.Services.AddSingleton(); + + if (host is not null) + { + await Run(); + } + }); + } + + /// + /// Registers a transient service. + /// + /// + /// + /// + public static void RegisterTransient() + where TInterface : class + where TImplementation : class, TInterface + { + Task.Run(async () => + { + if (host is not null) + { + await host.StopAsync(); + } + + builder.Services.AddTransient(); + + if (host is not null) + { + await Run(); + } + }); + } + + /// + /// Runs the dependency injection host. + /// + /// + public async static Task Run() + { + host = builder.Build(); + + await host.RunAsync(); + } + + /// + /// Gets an instance of a registered service. + /// + /// + /// + /// if DI is not yet running or no such service is registered. + public static TInterface Get() + { + if (host is null) + { + throw new InvalidOperationException("Can't get items from DI without first calling Run."); + } + var result = host.Services.GetService(); + return result ?? throw new InvalidOperationException($"No service of type {typeof(TInterface)} is registered."); + } + } +} diff --git a/FrEee.Gameplay/Commands/Designs/CreateDesignCommand.cs b/FrEee.Gameplay/Commands/Designs/CreateDesignCommand.cs new file mode 100644 index 000000000..048148805 --- /dev/null +++ b/FrEee.Gameplay/Commands/Designs/CreateDesignCommand.cs @@ -0,0 +1,44 @@ +using FrEee.Objects.Civilization; +using FrEee.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using FrEee.Objects.Vehicles; +using FrEee.Objects.GameState; +using FrEee.Objects.LogMessages; +using FrEee.Gameplay.Commands.Designs; + +namespace FrEee.Gameplay.Commands.Designs; + +/// +/// A command to create a new vehicle design. +/// +[Serializable] +public class CreateDesignCommand : Command, ICreateDesignCommand where T : IVehicle +{ + public CreateDesignCommand(IDesign design) + : base(Empire.Current) + { + Design = design; + } + + IDesign ICreateDesignCommand.Design { get { return Design; } } + + public IDesign Design { get; set; } + + public override IEnumerable NewReferrables + { + get + { + yield return Design; + } + } + + public override void Execute() + { + Design.VehiclesBuilt = 0; // in case it was tested in the simulator + if (Design.Warnings.Any()) + Issuer.Log.Add(Design.CreateLogMessage("The " + Design.Name + " " + Design.VehicleTypeName + " design cannot be saved because it has warnings.", LogMessageType.Warning)); + Issuer.KnownDesigns.Add(Design); + } +} \ No newline at end of file diff --git a/FrEee.Gameplay/Commands/Designs/DesignCommandFactory.cs b/FrEee.Gameplay/Commands/Designs/DesignCommandFactory.cs new file mode 100644 index 000000000..402676c9e --- /dev/null +++ b/FrEee.Gameplay/Commands/Designs/DesignCommandFactory.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands.Notes; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; +using FrEee.Objects.Vehicles; + +namespace FrEee.Gameplay.Commands.Designs; +public class DesignCommandFactory + : IDesignCommandFactory +{ + public ICreateDesignCommand CreateDesign(IDesign design) + where T : IVehicle + { + return new CreateDesignCommand(design); + } + + public ISetObsoleteFlagCommand SetObsoleteFlag(IDesign design, bool isObsolete) + { + return new SetObsoleteFlagCommand(design, isObsolete); + } +} diff --git a/FrEee.Gameplay/Commands/Designs/SetObsoleteFlagCommand.cs b/FrEee.Gameplay/Commands/Designs/SetObsoleteFlagCommand.cs new file mode 100644 index 000000000..759b81e2d --- /dev/null +++ b/FrEee.Gameplay/Commands/Designs/SetObsoleteFlagCommand.cs @@ -0,0 +1,67 @@ +using FrEee.Serialization; +using FrEee.Extensions; +using System.Collections.Generic; +using FrEee.Objects.Vehicles; +using FrEee.Objects.GameState; + +namespace FrEee.Gameplay.Commands.Designs; + +/// +/// A command to enable or disable the obsolete flag on a design. +/// +public class SetObsoleteFlagCommand : Command, ISetObsoleteFlagCommand +{ + public SetObsoleteFlagCommand(IDesign design, bool isObsolete) + : base(design) + { + if (design.IsNew) + NewDesign = design; + else + Design = design; + IsObsolete = isObsolete; + } + + [DoNotSerialize] + public IDesign Design { get { return design?.Value; } set { design = value.ReferViaGalaxy(); } } + + public bool IsObsolete { get; set; } + + public IDesign NewDesign { get; set; } + + public override IEnumerable NewReferrables + { + get + { + if (NewDesign != null) + yield return NewDesign; + } + } + + private GameReference design { get; set; } + + public override void Execute() + { + if (NewDesign != null) + { + // allows obsoleting designs that are on the library or newly created (not on the server yet) + Issuer.KnownDesigns.Add(NewDesign); + Design = NewDesign; + } + Design.IsObsolete = IsObsolete; + } + + public override void ReplaceClientIDs(IDictionary idmap, ISet done = null) + { + if (done == null) + done = new HashSet(); + if (!done.Contains(this)) + { + done.Add(this); + base.ReplaceClientIDs(idmap, done); + if (design != null) + design.ReplaceClientIDs(idmap, done); + if (NewDesign != null) + NewDesign.ReplaceClientIDs(idmap, done); + } + } +} \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/CreateFleetCommand.cs b/FrEee.Gameplay/Commands/Fleets/CreateFleetCommand.cs similarity index 84% rename from FrEee.Core.Domain/Objects/Commands/CreateFleetCommand.cs rename to FrEee.Gameplay/Commands/Fleets/CreateFleetCommand.cs index 730ec6ea5..a907274e0 100644 --- a/FrEee.Core.Domain/Objects/Commands/CreateFleetCommand.cs +++ b/FrEee.Gameplay/Commands/Fleets/CreateFleetCommand.cs @@ -3,12 +3,12 @@ using FrEee.Objects.Space; using System.Collections.Generic; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Fleets; /// /// A command to create a new fleet. /// -public class CreateFleetCommand : Command +public class CreateFleetCommand : Command, ICreateFleetCommand { public CreateFleetCommand(Fleet fleet, Sector sector) : base(Empire.Current) @@ -17,9 +17,6 @@ public CreateFleetCommand(Fleet fleet, Sector sector) Sector = sector; } - /// - /// The fleet to create. - /// public Fleet Fleet { get; set; } public override IEnumerable NewReferrables @@ -30,9 +27,6 @@ public override IEnumerable NewReferrables } } - /// - /// The sector to place the fleet in. - /// public Sector Sector { get; private set; } public override void Execute() diff --git a/FrEee.Core.Domain/Objects/Commands/DisbandFleetCommand.cs b/FrEee.Gameplay/Commands/Fleets/DisbandFleetCommand.cs similarity index 77% rename from FrEee.Core.Domain/Objects/Commands/DisbandFleetCommand.cs rename to FrEee.Gameplay/Commands/Fleets/DisbandFleetCommand.cs index 537304083..b23f9e8ea 100644 --- a/FrEee.Core.Domain/Objects/Commands/DisbandFleetCommand.cs +++ b/FrEee.Gameplay/Commands/Fleets/DisbandFleetCommand.cs @@ -1,12 +1,12 @@ using FrEee.Objects.Space; using System.Linq; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Fleets; /// /// A command to disband a fleet. /// -public class DisbandFleetCommand : Command +public class DisbandFleetCommand : Command, IDisbandFleetCommand { public DisbandFleetCommand(Fleet fleet) : base(fleet) diff --git a/FrEee.Gameplay/Commands/Fleets/FleetCommandFactory.cs b/FrEee.Gameplay/Commands/Fleets/FleetCommandFactory.cs new file mode 100644 index 000000000..d453a145a --- /dev/null +++ b/FrEee.Gameplay/Commands/Fleets/FleetCommandFactory.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands.Designs; +using FrEee.Gameplay.Commands.Notes; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; +using FrEee.Objects.Space; +using FrEee.Objects.Vehicles; + +namespace FrEee.Gameplay.Commands.Fleets; +public class FleetCommandFactory + : IFleetCommandFactory +{ + public ICreateFleetCommand CreateFleet(Fleet fleet, Sector sector) + { + return new CreateFleetCommand(fleet, sector); + } + + public IDisbandFleetCommand DisbandFleet(Fleet fleet) + { + return new DisbandFleetCommand(fleet); + } + + public IJoinFleetCommand JoinFleet(IMobileSpaceObject vehicle, Fleet fleet) + { + return new JoinFleetCommand(vehicle, fleet); + } + + public IJoinFleetCommand JoinFleet(IMobileSpaceObject vehicle, ICreateFleetCommand command) + { + return new JoinFleetCommand(vehicle, command); + } + + public ILeaveFleetCommand LeaveFleet(IMobileSpaceObject vehicle) + { + return new LeaveFleetCommand(vehicle); + } +} diff --git a/FrEee.Core.Domain/Objects/Commands/JoinFleetCommand.cs b/FrEee.Gameplay/Commands/Fleets/JoinFleetCommand.cs similarity index 81% rename from FrEee.Core.Domain/Objects/Commands/JoinFleetCommand.cs rename to FrEee.Gameplay/Commands/Fleets/JoinFleetCommand.cs index cbfcdeabc..4045bfa88 100644 --- a/FrEee.Core.Domain/Objects/Commands/JoinFleetCommand.cs +++ b/FrEee.Gameplay/Commands/Fleets/JoinFleetCommand.cs @@ -3,13 +3,14 @@ using FrEee.Extensions; using System.Collections.Generic; using FrEee.Objects.GameState; +using FrEee.Objects.LogMessages; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Fleets; /// /// A command for a space vehicle to join a fleet. /// -public class JoinFleetCommand : Command +public class JoinFleetCommand : Command, IJoinFleetCommand { public JoinFleetCommand(IMobileSpaceObject vehicle, Fleet fleet) : base(vehicle) @@ -17,20 +18,20 @@ public JoinFleetCommand(IMobileSpaceObject vehicle, Fleet fleet) Fleet = fleet; } - public JoinFleetCommand(IMobileSpaceObject vehicle, CreateFleetCommand cmd) + public JoinFleetCommand(IMobileSpaceObject vehicle, ICreateFleetCommand cmd) : base(vehicle) { CreateFleetCommand = cmd; } - public CreateFleetCommand CreateFleetCommand { get; set; } + public ICreateFleetCommand CreateFleetCommand { get; set; } [DoNotSerialize] public Fleet Fleet { get { - return fleet == null || fleet.ID <= 0 ? (Fleet)CreateFleetCommand.Fleet : (Fleet)fleet; + return fleet == null || fleet.ID <= 0 ? CreateFleetCommand.Fleet : (Fleet)fleet; } set { @@ -55,9 +56,9 @@ public override void Execute() // validation if (Fleet.Sector != null && Executor.Sector != Fleet.Sector) - Issuer.Log.Add(Executor.CreateLogMessage(Executor + " cannot join " + Fleet + " because they are not in the same sector.", LogMessages.LogMessageType.Warning)); + Issuer.Log.Add(Executor.CreateLogMessage(Executor + " cannot join " + Fleet + " because they are not in the same sector.", LogMessageType.Warning)); else if (Fleet.Owner != null && Fleet.Owner != Issuer && CreateFleetCommand == null) - Issuer.Log.Add(Executor.CreateLogMessage(Executor + " cannot join " + Fleet + " because this fleet does not belong to us.", LogMessages.LogMessageType.Warning)); + Issuer.Log.Add(Executor.CreateLogMessage(Executor + " cannot join " + Fleet + " because this fleet does not belong to us.", LogMessageType.Warning)); else { // remove from old fleet diff --git a/FrEee.Core.Domain/Objects/Commands/LeaveFleetCommand.cs b/FrEee.Gameplay/Commands/Fleets/LeaveFleetCommand.cs similarity index 77% rename from FrEee.Core.Domain/Objects/Commands/LeaveFleetCommand.cs rename to FrEee.Gameplay/Commands/Fleets/LeaveFleetCommand.cs index f203edc21..65a39d2cc 100644 --- a/FrEee.Core.Domain/Objects/Commands/LeaveFleetCommand.cs +++ b/FrEee.Gameplay/Commands/Fleets/LeaveFleetCommand.cs @@ -1,12 +1,13 @@ using FrEee.Extensions; +using FrEee.Objects.LogMessages; using FrEee.Objects.Space; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Fleets; /// /// A command for a space vehicle to leave a fleet. /// -public class LeaveFleetCommand : Command +public class LeaveFleetCommand : Command, ILeaveFleetCommand { public LeaveFleetCommand(IMobileSpaceObject vehicle) : base(vehicle) @@ -17,7 +18,7 @@ public override void Execute() { // validation if (Executor.Container == null) - Issuer.Log.Add(Executor.CreateLogMessage(Executor + " cannot leave its fleet because it is not currently in a fleet.", LogMessages.LogMessageType.Error)); + Issuer.Log.Add(Executor.CreateLogMessage(Executor + " cannot leave its fleet because it is not currently in a fleet.", LogMessageType.Error)); else { // remove from fleet diff --git a/FrEee.Core.Domain/Objects/Commands/DeleteMessageCommand.cs b/FrEee.Gameplay/Commands/Messages/DeleteMessageCommand.cs similarity index 85% rename from FrEee.Core.Domain/Objects/Commands/DeleteMessageCommand.cs rename to FrEee.Gameplay/Commands/Messages/DeleteMessageCommand.cs index 997d88ef5..d68c2da6c 100644 --- a/FrEee.Core.Domain/Objects/Commands/DeleteMessageCommand.cs +++ b/FrEee.Gameplay/Commands/Messages/DeleteMessageCommand.cs @@ -3,13 +3,14 @@ using FrEee.Objects.Civilization.Diplomacy.Messages; using FrEee.Objects.GameState; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Messages; /// /// A command to delete a message from an empire's inbox or sentbox. /// To delete from the outbox, simply delete the SendMessageCommand from the empire's command queue. /// -public class DeleteMessageCommand : Command +public class DeleteMessageCommand + : Command, IDeleteMessageCommand { public DeleteMessageCommand(IMessage msg) : base(Empire.Current) diff --git a/FrEee.Gameplay/Commands/Messages/MessageCommandFactory.cs b/FrEee.Gameplay/Commands/Messages/MessageCommandFactory.cs new file mode 100644 index 000000000..87c8b6e26 --- /dev/null +++ b/FrEee.Gameplay/Commands/Messages/MessageCommandFactory.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands.Designs; +using FrEee.Gameplay.Commands.Notes; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Diplomacy.Messages; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; +using FrEee.Objects.Space; +using FrEee.Objects.Vehicles; + +namespace FrEee.Gameplay.Commands.Messages; +public class MessageCommandFactory + : IMessageCommandFactory +{ + public ISendMessageCommand SendMessage(IMessage message) + { + return new SendMessageCommand(message); + } + + public IDeleteMessageCommand DeleteMessage(IMessage message) + { + return new DeleteMessageCommand(message); + } +} diff --git a/FrEee.Core.Domain/Objects/Commands/SendMessageCommand.cs b/FrEee.Gameplay/Commands/Messages/SendMessageCommand.cs similarity index 87% rename from FrEee.Core.Domain/Objects/Commands/SendMessageCommand.cs rename to FrEee.Gameplay/Commands/Messages/SendMessageCommand.cs index 2f2c9cd7d..f90eccd30 100644 --- a/FrEee.Core.Domain/Objects/Commands/SendMessageCommand.cs +++ b/FrEee.Gameplay/Commands/Messages/SendMessageCommand.cs @@ -3,13 +3,15 @@ using System.Collections.Generic; using FrEee.Objects.Civilization.Diplomacy.Messages; using FrEee.Objects.GameState; +using FrEee.Objects.LogMessages; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Messages; /// /// A command to send a diplomatic message. /// -public class SendMessageCommand : Command +public class SendMessageCommand + : Command, ISendMessageCommand { public SendMessageCommand(IMessage message) : base(Empire.Current) @@ -34,7 +36,7 @@ public override void Execute() Message.Owner.SentMessages.Add(Message); // TODO - comms interference intel projects Message.Recipient.IncomingMessages.Add(Message); - Message.Recipient.Log.Add(Message.CreateLogMessage("We have received a diplomatic message from the " + Message.Owner + ": " + Message.Text, LogMessages.LogMessageType.Diplomacy)); + Message.Recipient.Log.Add(Message.CreateLogMessage("We have received a diplomatic message from the " + Message.Owner + ": " + Message.Text, LogMessageType.Diplomacy)); if (Message is ActionMessage) { // execute unilateral action diff --git a/FrEee.Gameplay/Commands/Ministers/MinisterCommandFactory.cs b/FrEee.Gameplay/Commands/Ministers/MinisterCommandFactory.cs new file mode 100644 index 000000000..ac0de59df --- /dev/null +++ b/FrEee.Gameplay/Commands/Ministers/MinisterCommandFactory.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands.Designs; +using FrEee.Gameplay.Commands.Ministers; +using FrEee.Gameplay.Commands.Notes; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Diplomacy.Messages; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; +using FrEee.Objects.Space; +using FrEee.Objects.Vehicles; + +namespace FrEee.Gameplay.Commands.Ministers; +public class MinisterCommandFactory + : IMinisterCommandFactory +{ + public IToggleMinistersCommand ToggleMinisters() + { + return new ToggleMinistersCommand(); + } +} diff --git a/FrEee.Gameplay/Commands/Ministers/ToggleMinistersCommand.cs b/FrEee.Gameplay/Commands/Ministers/ToggleMinistersCommand.cs new file mode 100644 index 000000000..10d060d54 --- /dev/null +++ b/FrEee.Gameplay/Commands/Ministers/ToggleMinistersCommand.cs @@ -0,0 +1,31 @@ +using FrEee.Gameplay.Commands.Messages; +using FrEee.Objects.Civilization; +using FrEee.Objects.GameState; +using FrEee.Objects.LogMessages; +using FrEee.Serialization; +using FrEee.Utility; +using System.Collections.Generic; + +namespace FrEee.Gameplay.Commands.Ministers; + +/// +/// Toggles AI ministers. +/// +public class ToggleMinistersCommand + : Command, IToggleMinistersCommand +{ + public ToggleMinistersCommand() + : base(Empire.Current) + { + } + + public SafeDictionary> EnabledMinisters { get; set; } + + public override void Execute() + { + if (Executor.AI == null) + Executor.RecordLog(Executor, $"Could not toggle AI ministers for {Executor} because there is no AI for this empire.", LogMessageType.Error); + else + Executor.EnabledMinisters = EnabledMinisters; + } +} diff --git a/FrEee.Core.Domain/Objects/Commands/MinisterToggleCommand.cs b/FrEee.Gameplay/Commands/Notes/ClearPlayerNoteCommand.cs similarity index 93% rename from FrEee.Core.Domain/Objects/Commands/MinisterToggleCommand.cs rename to FrEee.Gameplay/Commands/Notes/ClearPlayerNoteCommand.cs index 87205e04e..2c48294c6 100644 --- a/FrEee.Core.Domain/Objects/Commands/MinisterToggleCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/ClearPlayerNoteCommand.cs @@ -3,7 +3,7 @@ using FrEee.Extensions; using FrEee.Objects.GameState; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Notes; /// /// Clears a player note. diff --git a/FrEee.Core.Domain/Objects/Commands/ClearPrivateNameCommand.cs b/FrEee.Gameplay/Commands/Notes/ClearPrivateNameCommand.cs similarity index 94% rename from FrEee.Core.Domain/Objects/Commands/ClearPrivateNameCommand.cs rename to FrEee.Gameplay/Commands/Notes/ClearPrivateNameCommand.cs index 212f5a99c..b17abea5b 100644 --- a/FrEee.Core.Domain/Objects/Commands/ClearPrivateNameCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/ClearPrivateNameCommand.cs @@ -3,7 +3,7 @@ using FrEee.Extensions; using FrEee.Objects.GameState; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Notes; /// /// Clears the private name for an object. diff --git a/FrEee.Gameplay/Commands/Notes/NoteCommandFactory.cs b/FrEee.Gameplay/Commands/Notes/NoteCommandFactory.cs new file mode 100644 index 000000000..1d0927749 --- /dev/null +++ b/FrEee.Gameplay/Commands/Notes/NoteCommandFactory.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; + +namespace FrEee.Gameplay.Commands.Notes; +public class NoteCommandFactory + : INoteCommandFactory +{ + public ICommand ClearPlayerNote(IReferrable target) + { + return new ClearPlayerNoteCommand(target); + } + + public ICommand ClearPrivateName(Empire empire, INameable target) + { + return new ClearPrivateNameCommand(empire, target); + } + + public ICommand SetPlayerInfo(Empire empire, PlayerInfo playerInfo) + { + return new SetPlayerInfoCommand(empire, playerInfo); + } + + public ICommand SetPlayerNote(IReferrable target, string note) + { + return new SetPlayerNoteCommand(target, note); + } + + public ICommand SetPrivateName(Empire empire, INameable target, string name) + { + return new SetPrivateNameCommand(empire, target, name); + } + + public ICommand SetPublicName(INameable target, string name) + { + return new SetPublicNameCommand(target, name); + } +} diff --git a/FrEee.Core.Domain/Objects/Commands/SetPlayerInfoCommand.cs b/FrEee.Gameplay/Commands/Notes/SetPlayerInfoCommand.cs similarity index 69% rename from FrEee.Core.Domain/Objects/Commands/SetPlayerInfoCommand.cs rename to FrEee.Gameplay/Commands/Notes/SetPlayerInfoCommand.cs index 52bcca271..d27e78ef8 100644 --- a/FrEee.Core.Domain/Objects/Commands/SetPlayerInfoCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/SetPlayerInfoCommand.cs @@ -3,18 +3,20 @@ using System; using System.Collections.Generic; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Notes; /// /// Sets the player info for an empire. /// /// [Serializable] -public class SetPlayerInfoCommand: Command +public class SetPlayerInfoCommand + : Command, ISetPlayerInfoCommand { - public SetPlayerInfoCommand(Empire target) + public SetPlayerInfoCommand(Empire target, PlayerInfo playerInfo) : base(target) { + PlayerInfo = playerInfo; } public override IEnumerable NewReferrables diff --git a/FrEee.Core.Domain/Objects/Commands/SetPlayerNoteCommand.cs b/FrEee.Gameplay/Commands/Notes/SetPlayerNoteCommand.cs similarity index 94% rename from FrEee.Core.Domain/Objects/Commands/SetPlayerNoteCommand.cs rename to FrEee.Gameplay/Commands/Notes/SetPlayerNoteCommand.cs index ccbe6149a..bb8d66eeb 100644 --- a/FrEee.Core.Domain/Objects/Commands/SetPlayerNoteCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/SetPlayerNoteCommand.cs @@ -3,7 +3,7 @@ using FrEee.Extensions; using FrEee.Objects.GameState; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Notes; /// /// Sets a player note. diff --git a/FrEee.Core.Domain/Objects/Commands/SetPrivateNameCommand.cs b/FrEee.Gameplay/Commands/Notes/SetPrivateNameCommand.cs similarity index 94% rename from FrEee.Core.Domain/Objects/Commands/SetPrivateNameCommand.cs rename to FrEee.Gameplay/Commands/Notes/SetPrivateNameCommand.cs index 88e1011eb..4d739dd28 100644 --- a/FrEee.Core.Domain/Objects/Commands/SetPrivateNameCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/SetPrivateNameCommand.cs @@ -3,7 +3,7 @@ using FrEee.Extensions; using FrEee.Objects.GameState; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Notes; /// /// Sets the private name for an object. diff --git a/FrEee.Core.Domain/Objects/Commands/SetPublicNameCommand.cs b/FrEee.Gameplay/Commands/Notes/SetPublicNameCommand.cs similarity index 90% rename from FrEee.Core.Domain/Objects/Commands/SetPublicNameCommand.cs rename to FrEee.Gameplay/Commands/Notes/SetPublicNameCommand.cs index 265a2ad1f..d66860796 100644 --- a/FrEee.Core.Domain/Objects/Commands/SetPublicNameCommand.cs +++ b/FrEee.Gameplay/Commands/Notes/SetPublicNameCommand.cs @@ -1,6 +1,6 @@ using FrEee.Objects.Civilization; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Notes; /// /// Sets the name of an object. diff --git a/FrEee.Core.Domain/Objects/Commands/AddOrderCommand.cs b/FrEee.Gameplay/Commands/Orders/AddOrderCommand.cs similarity index 94% rename from FrEee.Core.Domain/Objects/Commands/AddOrderCommand.cs rename to FrEee.Gameplay/Commands/Orders/AddOrderCommand.cs index db68cce7c..0f5f4b3e9 100644 --- a/FrEee.Core.Domain/Objects/Commands/AddOrderCommand.cs +++ b/FrEee.Gameplay/Commands/Orders/AddOrderCommand.cs @@ -6,14 +6,15 @@ using System; using System.Collections.Generic; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Orders; /// /// Adds an order to the end of the queue. /// /// [Serializable] -public class AddOrderCommand : OrderCommand +public class AddOrderCommand + : OrderCommand, IAddOrderCommand { public AddOrderCommand(IOrderable target, IOrder order) : base(target, order) diff --git a/FrEee.Core.Domain/Objects/Commands/OrderCommand.cs b/FrEee.Gameplay/Commands/Orders/OrderCommand.cs similarity index 96% rename from FrEee.Core.Domain/Objects/Commands/OrderCommand.cs rename to FrEee.Gameplay/Commands/Orders/OrderCommand.cs index 4078d38e0..00d63cd8c 100644 --- a/FrEee.Core.Domain/Objects/Commands/OrderCommand.cs +++ b/FrEee.Gameplay/Commands/Orders/OrderCommand.cs @@ -6,7 +6,7 @@ using FrEee.Objects.Civilization; using FrEee.Objects.GameState; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Orders; /// /// A command to manipulate an object's order queue. diff --git a/FrEee.Gameplay/Commands/Orders/OrderCommandFactory.cs b/FrEee.Gameplay/Commands/Orders/OrderCommandFactory.cs new file mode 100644 index 000000000..12906fade --- /dev/null +++ b/FrEee.Gameplay/Commands/Orders/OrderCommandFactory.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; + +namespace FrEee.Gameplay.Commands.Orders; +public class OrderCommandFactory + : IOrderCommandFactory +{ + public IAddOrderCommand AddOrder(IOrderable target, IOrder order) + { + return new AddOrderCommand(target, order); + } + + public IOrderCommand RearrangeOrders(T target, IOrder order, int deltaPosition) where T : IOrderable + { + return new RearrangeOrdersCommand(target, order, deltaPosition); + } + + public IRemoveOrderCommand RemoveOrder(IOrderable target, IOrder order) + { + return new RemoveOrderCommand(target, order); + } + + public IToggleOrdersOnHoldCommand ToggleOrdersOnHold(IOrderable target, bool areOrdersOnHold) + { + return new ToggleOrdersOnHoldCommand(target, areOrdersOnHold); + } + + public IToggleRepeatOrdersCommand ToggleRepeatOrders(IOrderable target, bool areRepeatOrdersEnabled) + { + return new ToggleRepeatOrdersCommand(target, areRepeatOrdersEnabled); + } +} diff --git a/FrEee.Core.Domain/Objects/Commands/RearrangeOrdersCommand.cs b/FrEee.Gameplay/Commands/Orders/RearrangeOrdersCommand.cs similarity index 95% rename from FrEee.Core.Domain/Objects/Commands/RearrangeOrdersCommand.cs rename to FrEee.Gameplay/Commands/Orders/RearrangeOrdersCommand.cs index 5f7764dd4..9a8268c7e 100644 --- a/FrEee.Core.Domain/Objects/Commands/RearrangeOrdersCommand.cs +++ b/FrEee.Gameplay/Commands/Orders/RearrangeOrdersCommand.cs @@ -4,7 +4,7 @@ using FrEee.Objects.LogMessages; using System; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Orders; /// /// Moves an order to another location in the queue. diff --git a/FrEee.Core.Domain/Objects/Commands/RemoveOrderCommand.cs b/FrEee.Gameplay/Commands/Orders/RemoveOrderCommand.cs similarity index 92% rename from FrEee.Core.Domain/Objects/Commands/RemoveOrderCommand.cs rename to FrEee.Gameplay/Commands/Orders/RemoveOrderCommand.cs index b8ab2c61e..53295435f 100644 --- a/FrEee.Core.Domain/Objects/Commands/RemoveOrderCommand.cs +++ b/FrEee.Gameplay/Commands/Orders/RemoveOrderCommand.cs @@ -5,14 +5,15 @@ using FrEee.Objects.Civilization; using FrEee.Objects.GameState; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Orders; /// /// Removes an order from the queue. /// /// [Serializable] -public class RemoveOrderCommand : OrderCommand +public class RemoveOrderCommand + : OrderCommand, IRemoveOrderCommand { public RemoveOrderCommand(IOrderable target, IOrder order) : base(target, order) diff --git a/FrEee.Gameplay/Commands/Orders/ToggleOrdersOnHoldCommand.cs b/FrEee.Gameplay/Commands/Orders/ToggleOrdersOnHoldCommand.cs new file mode 100644 index 000000000..56d97dd74 --- /dev/null +++ b/FrEee.Gameplay/Commands/Orders/ToggleOrdersOnHoldCommand.cs @@ -0,0 +1,23 @@ +using FrEee.Objects.Civilization; + +namespace FrEee.Gameplay.Commands.Orders; + +public class ToggleOrdersOnHoldCommand + : Command, IToggleOrdersOnHoldCommand +{ + public ToggleOrdersOnHoldCommand(IOrderable target, bool areOrdersOnHold) + : base(target) + { + IsToggleEnabled = areOrdersOnHold; + } + + /// + /// Are the orders on hold? + /// + public bool IsToggleEnabled { get; set; } + + public override void Execute() + { + Executor.AreOrdersOnHold = IsToggleEnabled; + } +} diff --git a/FrEee.Gameplay/Commands/Orders/ToggleRepeatOrdersCommand.cs b/FrEee.Gameplay/Commands/Orders/ToggleRepeatOrdersCommand.cs new file mode 100644 index 000000000..b9be7254b --- /dev/null +++ b/FrEee.Gameplay/Commands/Orders/ToggleRepeatOrdersCommand.cs @@ -0,0 +1,23 @@ +using FrEee.Objects.Civilization; + +namespace FrEee.Gameplay.Commands.Orders; + +public class ToggleRepeatOrdersCommand + : Command, IToggleRepeatOrdersCommand +{ + public ToggleRepeatOrdersCommand(IOrderable target, bool areRepeatOrdersEnabled) + : base(target) + { + IsToggleEnabled = areRepeatOrdersEnabled; + } + + /// + /// Are repeat orders enabled? + /// + public bool IsToggleEnabled { get; set; } + + public override void Execute() + { + Executor.AreRepeatOrdersEnabled = IsToggleEnabled; + } +} diff --git a/FrEee.Core.Domain/Objects/Commands/CreateWaypointCommand.cs b/FrEee.Gameplay/Commands/Waypoints/CreateWaypointCommand.cs similarity index 95% rename from FrEee.Core.Domain/Objects/Commands/CreateWaypointCommand.cs rename to FrEee.Gameplay/Commands/Waypoints/CreateWaypointCommand.cs index 967d01c15..e60c0d40b 100644 --- a/FrEee.Core.Domain/Objects/Commands/CreateWaypointCommand.cs +++ b/FrEee.Gameplay/Commands/Waypoints/CreateWaypointCommand.cs @@ -2,7 +2,7 @@ using FrEee.Objects.GameState; using System.Collections.Generic; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Waypoints; /// /// A command to create a new waypoint. diff --git a/FrEee.Core.Domain/Objects/Commands/DeleteWaypointCommand.cs b/FrEee.Gameplay/Commands/Waypoints/DeleteWaypointCommand.cs similarity index 75% rename from FrEee.Core.Domain/Objects/Commands/DeleteWaypointCommand.cs rename to FrEee.Gameplay/Commands/Waypoints/DeleteWaypointCommand.cs index 771a3891a..8ad168e01 100644 --- a/FrEee.Core.Domain/Objects/Commands/DeleteWaypointCommand.cs +++ b/FrEee.Gameplay/Commands/Waypoints/DeleteWaypointCommand.cs @@ -1,7 +1,8 @@ using FrEee.Objects.Civilization; using FrEee.Extensions; +using FrEee.Objects.LogMessages; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Waypoints; /// /// A command to delete a waypoint. @@ -19,12 +20,12 @@ public override void Execute() var emp = Executor.Owner; if (emp != Issuer) { - Issuer.Log.Add(Issuer.CreateLogMessage("We cannot issue a command to delete another empire's waypoints!", LogMessages.LogMessageType.Error)); + Issuer.Log.Add(Issuer.CreateLogMessage("We cannot issue a command to delete another empire's waypoints!", LogMessageType.Error)); return; } Executor.Dispose(); - Issuer.Log.Add(Issuer.CreateLogMessage(Executor.AlteredQueuesOnDelete + " vehicles' orders were truncated when " + Executor + " was deleted.", LogMessages.LogMessageType.Warning)); + Issuer.Log.Add(Issuer.CreateLogMessage(Executor.AlteredQueuesOnDelete + " vehicles' orders were truncated when " + Executor + " was deleted.", LogMessageType.Warning)); } } \ No newline at end of file diff --git a/FrEee.Core.Domain/Objects/Commands/HotkeyWaypointCommand.cs b/FrEee.Gameplay/Commands/Waypoints/HotkeyWaypointCommand.cs similarity index 92% rename from FrEee.Core.Domain/Objects/Commands/HotkeyWaypointCommand.cs rename to FrEee.Gameplay/Commands/Waypoints/HotkeyWaypointCommand.cs index 6757989a8..791c1b95b 100644 --- a/FrEee.Core.Domain/Objects/Commands/HotkeyWaypointCommand.cs +++ b/FrEee.Gameplay/Commands/Waypoints/HotkeyWaypointCommand.cs @@ -5,8 +5,9 @@ using System; using FrEee.Objects.Civilization.Orders; using FrEee.Objects.GameState; +using FrEee.Objects.LogMessages; -namespace FrEee.Objects.Commands; +namespace FrEee.Gameplay.Commands.Waypoints; /// /// A command to set a waypoint to a hotkey. @@ -38,7 +39,7 @@ public override void Execute() var emp = Executor.Owner; if (emp != Issuer) { - Issuer.Log.Add(Issuer.CreateLogMessage("We cannot issue a command to hotkey another empire's waypoints!", LogMessages.LogMessageType.Error)); + Issuer.Log.Add(Issuer.CreateLogMessage("We cannot issue a command to hotkey another empire's waypoints!", LogMessageType.Error)); return; } @@ -71,7 +72,7 @@ public override void Execute() } if (count > 0) - emp.Log.Add(Issuer.CreateLogMessage(count + " vehicles were redirected from " + oldWaypoint + " to " + Executor + ".", LogMessages.LogMessageType.Generic)); + emp.Log.Add(Issuer.CreateLogMessage(count + " vehicles were redirected from " + oldWaypoint + " to " + Executor + ".", LogMessageType.Generic)); } } } \ No newline at end of file diff --git a/FrEee.Gameplay/Commands/Waypoints/WaypointCommandFactory.cs b/FrEee.Gameplay/Commands/Waypoints/WaypointCommandFactory.cs new file mode 100644 index 000000000..f18ed1d54 --- /dev/null +++ b/FrEee.Gameplay/Commands/Waypoints/WaypointCommandFactory.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands.Designs; +using FrEee.Gameplay.Commands.Notes; +using FrEee.Objects.Civilization; +using FrEee.Objects.Civilization.Orders; +using FrEee.Objects.GameState; +using FrEee.Objects.Space; +using FrEee.Objects.Vehicles; + +namespace FrEee.Gameplay.Commands.Waypoints; +public class WaypointCommandFactory + : IWaypointCommandFactory +{ + public ICommand CreateWaypoint(Waypoint Waypoint) + { + return new CreateWaypointCommand(Waypoint); + } + + public ICommand DeleteWaypoint(Waypoint waypoint) + { + return new DeleteWaypointCommand(waypoint); + } + + public ICommand HotkeyWaypoint(Waypoint waypoint, int hotkey, bool redirect) + { + return new HotkeyWaypointCommand(waypoint, hotkey, redirect); + } +} diff --git a/FrEee.Gameplay/FrEee.Gameplay.csproj b/FrEee.Gameplay/FrEee.Gameplay.csproj new file mode 100644 index 000000000..868b49bde --- /dev/null +++ b/FrEee.Gameplay/FrEee.Gameplay.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + Library + FrEee.Gameplay + Stock implementations of basic game mechanics such as commands for FrEee. + + + + + + + + + + + false + FrEee.Gameplay + + + \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/Battle.cs b/FrEee.Processes/Combat/Grid/Battle.cs similarity index 99% rename from FrEee.Core.Domain/Processes/Combat/Grid/Battle.cs rename to FrEee.Processes/Combat/Grid/Battle.cs index 105f208f6..586d8a87a 100644 --- a/FrEee.Core.Domain/Processes/Combat/Grid/Battle.cs +++ b/FrEee.Processes/Combat/Grid/Battle.cs @@ -15,6 +15,7 @@ using FrEee.Objects.Civilization.CargoStorage; using FrEee.Objects.GameState; using FrEee.Modding.Abilities; +using FrEee.Processes.Combat.Events; namespace FrEee.Processes.Combat.Grid; @@ -500,7 +501,7 @@ int GetCombatSpeedThisRound(ICombatant c) var cd = new CargoDelta(); cd.UnitTypeTonnage.Add(VehicleTypes.Troop, null); cc.TransferCargo(cd, dropTarget, cc.Owner, true); - var groundBattle = new GroundBattle(dropTarget); + var groundBattle = DIRoot.Battles.BuildGroundBattle(dropTarget); groundBattle.Resolve(); } } diff --git a/FrEee.Processes/Combat/Grid/BattleFactory.cs b/FrEee.Processes/Combat/Grid/BattleFactory.cs new file mode 100644 index 000000000..86a539272 --- /dev/null +++ b/FrEee.Processes/Combat/Grid/BattleFactory.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Objects.Space; + +namespace FrEee.Processes.Combat.Grid; + +/// +/// Implementation of for the grid-based combat engine. +/// +public class BattleFactory + : IBattleFactory +{ + public IBattle BuildGroundBattle(Planet location) + { + return new GroundBattle(location); + } + + public IBattle BuildSpaceBattle(Sector location) + { + return new SpaceBattle(location); + } +} diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/Extensions.cs b/FrEee.Processes/Combat/Grid/Extensions.cs similarity index 100% rename from FrEee.Core.Domain/Processes/Combat/Grid/Extensions.cs rename to FrEee.Processes/Combat/Grid/Extensions.cs diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/GroundBattle.cs b/FrEee.Processes/Combat/Grid/GroundBattle.cs similarity index 100% rename from FrEee.Core.Domain/Processes/Combat/Grid/GroundBattle.cs rename to FrEee.Processes/Combat/Grid/GroundBattle.cs diff --git a/FrEee.Core.Domain/Processes/Combat/Grid/SpaceBattle.cs b/FrEee.Processes/Combat/Grid/SpaceBattle.cs similarity index 100% rename from FrEee.Core.Domain/Processes/Combat/Grid/SpaceBattle.cs rename to FrEee.Processes/Combat/Grid/SpaceBattle.cs diff --git a/FrEee.Processes/FrEee.Processes.csproj b/FrEee.Processes/FrEee.Processes.csproj new file mode 100644 index 000000000..1c645c511 --- /dev/null +++ b/FrEee.Processes/FrEee.Processes.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + Library + FrEee.Processes + Stock implementations of processes such as turn processing used by FrEee + + + + + + + + + + + false + FrEee.Processes + + + \ No newline at end of file diff --git a/FrEee.Core.Domain/Processes/TurnProcessor.cs b/FrEee.Processes/TurnProcessor.cs similarity index 95% rename from FrEee.Core.Domain/Processes/TurnProcessor.cs rename to FrEee.Processes/TurnProcessor.cs index 74ca892ee..f767688f5 100644 --- a/FrEee.Core.Domain/Processes/TurnProcessor.cs +++ b/FrEee.Processes/TurnProcessor.cs @@ -11,7 +11,6 @@ using FrEee.Modding; using FrEee.Extensions; using FrEee.Utility; -using FrEee.Objects.Commands; using FrEee.Objects.Civilization.Construction; using FrEee.Objects.Civilization.Orders; using FrEee.Objects.Civilization.CargoStorage; @@ -19,21 +18,16 @@ using FrEee.Processes.Combat; using FrEee.Modding.Abilities; using FrEee.Modding.Scripts; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands; namespace FrEee.Processes; /// -/// Processes turns. +/// Stock implementation of . /// -public class TurnProcessor +public class TurnProcessor : ITurnProcessor { - /// - /// Processes the turn. - /// - /// Stop processing if PLR files are missing? - /// Player empires which did not submit commands and are not defeated. - /// if the Galaxy empire is not null, or this galaxy is not the Galaxy galaxy. - // TODO - make non-static so we don't have to say Galaxy. everywhere public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = null, double desiredProgress = 1d) { //galaxy.SpaceObjectIDCheck("at start of turn"); @@ -119,8 +113,7 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = game.EnableAbilityCache(); // clear treaty clause cache (empires might have added treaties) - game.GivenTreatyClauseCache.Clear(); - game.ReceivedTreatyClauseCache.Clear(); + game.ResetTreatyClauseCaches(); // delete any floating space objects that are unused //galaxy.SpaceObjectCleanup(); @@ -129,8 +122,7 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = game.Battles.Clear(); PythonScriptEngine.ClearScope(); // no caching galaxy between turns! - game.GivenTreatyClauseCache = new SafeDictionary>(); - game.ReceivedTreatyClauseCache = new SafeDictionary>(); + game.ResetTreatyClauseCaches(); if (status != null) status.Progress += progressPerOperation; @@ -436,7 +428,7 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = foreach (var p in game.Galaxy.FindSpaceObjects(p => p.Cargo != null && p.Cargo.Units.Any(u => u.IsHostileTo(p.Owner) || p.IsHostileTo(u.Owner))) ) { - var battle = new GroundBattle(p); + var battle = DIRoot.Battles.BuildGroundBattle(p); battle.Resolve(); game.Battles.Add(battle); foreach (var emp in battle.Empires) @@ -709,10 +701,6 @@ public IEnumerable ProcessTurn(Game game, bool safeMode, Status status = return missingPlrs; } - /// - /// Only public for unit tests. You should probably call ProcessTurn instead. - /// - /// private static void ProcessColonyIncome(Game galaxy, Colony c) { var p = c.Container; @@ -749,10 +737,6 @@ private static void ProcessColonyIncome(Game galaxy, Colony c) } } - /// - /// Only public for unit tests. You should probably call ProcessTurn instead. - /// - /// private static void ProcessPopulationGrowth(Planet p) { var pop = p.Colony.Population; @@ -798,10 +782,6 @@ private static void ProcessPopulationGrowth(Planet p) } } - /// - /// Only public for unit tests. You should probably call ProcessTurn instead. - /// - /// private static void ProcessResourceValueChange(Game galaxy, Planet p) { foreach (var r in Resource.All.Where(r => r.HasValue)) diff --git a/FrEee.Root/Configuration.cs b/FrEee.Root/Configuration.cs new file mode 100644 index 000000000..7ec60d0f1 --- /dev/null +++ b/FrEee.Root/Configuration.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FrEee.Gameplay.Commands.Designs; +using FrEee.Gameplay.Commands.Fleets; +using FrEee.Gameplay.Commands.Messages; +using FrEee.Gameplay.Commands.Ministers; +using FrEee.Gameplay.Commands.Notes; +using FrEee.Gameplay.Commands.Orders; +using FrEee.Gameplay.Commands.Waypoints; +using FrEee.Processes; +using FrEee.Processes.Combat; +using FrEee.Processes.Combat.Grid; +using FrEee.Utility; + +namespace FrEee.Root; + +/// +/// Configures FrEee. +/// +public static class Configuration +{ + /// + /// Sets up any dependencies which need to be injected. + /// + public static void ConfigureDI() + { + // processes + DI.RegisterSingleton(); + DI.RegisterSingleton(); + + // gameplay + DI.RegisterSingleton(); + DI.RegisterSingleton(); + DI.RegisterSingleton(); + DI.RegisterSingleton(); + DI.RegisterSingleton(); + DI.RegisterSingleton(); + DI.RegisterSingleton(); + + // run this in the background, without awaiting it + DI.Run(); + } +} \ No newline at end of file diff --git a/FrEee.Root/FrEee.Root.csproj b/FrEee.Root/FrEee.Root.csproj new file mode 100644 index 000000000..eae00d5fb --- /dev/null +++ b/FrEee.Root/FrEee.Root.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + Library + FrEee.Root + Root of the FrEee game code. Configures dependency injection. + + + + + + + + + + all + + + all + + + + + false + FrEee.Processes + + + \ No newline at end of file diff --git a/FrEee.Tests/FrEee.Tests.csproj b/FrEee.Tests/FrEee.Tests.csproj index 02b0bf0ee..e2d7912f6 100644 --- a/FrEee.Tests/FrEee.Tests.csproj +++ b/FrEee.Tests/FrEee.Tests.csproj @@ -14,6 +14,7 @@ + diff --git a/FrEee.Tests/Objects/Technology/TechnologyTest.cs b/FrEee.Tests/Objects/Technology/TechnologyTest.cs index 29145f469..ce84330d1 100644 --- a/FrEee.Tests/Objects/Technology/TechnologyTest.cs +++ b/FrEee.Tests/Objects/Technology/TechnologyTest.cs @@ -1,10 +1,11 @@ using FrEee.Extensions; +using FrEee.Gameplay.Commands; using FrEee.Modding; using FrEee.Modding.Loaders; using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.GameState; using FrEee.Processes; +using FrEee.Utility; using NUnit.Framework; namespace FrEee.Objects.Technology; @@ -12,7 +13,7 @@ namespace FrEee.Objects.Technology; public class TechnologyTest { private Empire emp; - private TurnProcessor processor = new(); + private static ITurnProcessor processor; /// /// Loads the stock mod. Done once before running ALL the tests (not each individually; that would be pointless). @@ -21,6 +22,9 @@ public class TechnologyTest [OneTimeSetUp] public static void ClassInit() { + DI.RegisterSingleton(); + DI.Run(); + processor = DIRoot.TurnProcessor; new ModLoader().Load(null); } @@ -119,7 +123,10 @@ public void QueuedResearch() public void TestInit() { new Game(); - Game.Current.Setup.TechnologyCost = TechnologyCost.Low; + Game.Current.Setup = new() + { + TechnologyCost = TechnologyCost.Low + }; emp = new Empire(); Game.Current.Empires.Add(emp); } diff --git a/FrEee.UI.WinForms/Controls/BattleView.cs b/FrEee.UI.WinForms/Controls/BattleView.cs index 698700776..8ce888fed 100644 --- a/FrEee.UI.WinForms/Controls/BattleView.cs +++ b/FrEee.UI.WinForms/Controls/BattleView.cs @@ -9,7 +9,7 @@ using System.Linq; using System.Windows.Forms; using FrEee.Processes.Combat; -using FrEee.Processes.Combat.Grid; +using FrEee.Processes.Combat.Events; namespace FrEee.UI.WinForms.Controls; @@ -39,7 +39,7 @@ public bool AutoZoom } } - public Battle Battle + public IBattle Battle { get => battle; set @@ -134,7 +134,7 @@ public bool UseSquares private const int SectorBorderSize = 1; private bool autoZoom; - private Battle battle; + private IBattle battle; private List booms = new List(); private bool combatPhase = false; private Vector2 focusedLocation; diff --git a/FrEee.UI.WinForms/Controls/FleetReport.cs b/FrEee.UI.WinForms/Controls/FleetReport.cs index 654adcca4..1b048afeb 100644 --- a/FrEee.UI.WinForms/Controls/FleetReport.cs +++ b/FrEee.UI.WinForms/Controls/FleetReport.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using FrEee.Objects.Vehicles; using FrEee.Utility; @@ -12,6 +11,7 @@ using System.Windows.Forms; using FrEee.Objects.Civilization.Orders; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands.Orders; namespace FrEee.UI.WinForms.Controls; @@ -131,11 +131,11 @@ private void btnClearOrders_Click(object sender, System.EventArgs e) { foreach (var order in Fleet.Orders.ToArray()) { - var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); + var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); if (addCmd == null) { // not a newly added order, so create a remove command to take it off the server - var remCmd = new RemoveOrderCommand(Fleet, order); + var remCmd = DIRoot.OrderCommands.RemoveOrder(Fleet, order); Empire.Current.Commands.Add(remCmd); remCmd.Execute(); // show change locally } @@ -158,11 +158,11 @@ private void btnDeleteOrder_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null) { - var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); + var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); if (addCmd == null) { // not a newly added order, so create a remove command to take it off the server - var remCmd = new RemoveOrderCommand(Fleet, order); + var remCmd = DIRoot.OrderCommands.RemoveOrder(Fleet, order); Empire.Current.Commands.Add(remCmd); remCmd.Execute(); // show change locally } @@ -185,8 +185,7 @@ private void btnOrderGoesDown_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null && Fleet.Orders.IndexOf(order) < Fleet.Orders.Count - 1) { - var cmd = new RearrangeOrdersCommand( - Fleet, order, 1); + var cmd = DIRoot.OrderCommands.RearrangeOrders(Fleet, order, 1); Empire.Current.Commands.Add(cmd); cmd.Execute(); // show change locally Bind(); @@ -201,8 +200,7 @@ private void btnOrderGoesUp_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null && Fleet.Orders.IndexOf(order) > 0) { - var cmd = new RearrangeOrdersCommand( - Fleet, order, -1); + var cmd = DIRoot.OrderCommands.RearrangeOrders(Fleet, order, -1); Empire.Current.Commands.Add(cmd); cmd.Execute(); // show change locally Bind(); @@ -219,7 +217,7 @@ private void btnOrderToBottom_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null) { - var cmd = new RearrangeOrdersCommand( + var cmd = DIRoot.OrderCommands.RearrangeOrders( Fleet, order, Fleet.Orders.Count - Fleet.Orders.IndexOf(order) - 1); Empire.Current.Commands.Add(cmd); cmd.Execute(); // show change locally @@ -235,7 +233,7 @@ private void btnOrderToTop_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null) { - var cmd = new RearrangeOrdersCommand( + var cmd = DIRoot.OrderCommands.RearrangeOrders( Fleet, order, -fleet.Orders.IndexOf(order)); Empire.Current.Commands.Add(cmd); cmd.Execute(); // show change locally @@ -334,27 +332,27 @@ private void treeVehicles_NodeMouseClick(object sender, TreeNodeMouseClickEventA private void chkRepeat_CheckedChanged(object sender, EventArgs e) { - var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Fleet); + var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Fleet); if (cmd == null) { - cmd = new ToggleRepeatOrdersCommand(Fleet, chkRepeat.Checked); + cmd = DIRoot.OrderCommands.ToggleRepeatOrders(Fleet, chkRepeat.Checked); Empire.Current.Commands.Add(cmd); } else - cmd.AreRepeatOrdersEnabled = chkRepeat.Checked; + cmd.IsToggleEnabled = chkRepeat.Checked; cmd.Execute(); } private void chkOnHold_CheckedChanged(object sender, EventArgs e) { - var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Fleet); + var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Fleet); if (cmd == null) { - cmd = new ToggleOrdersOnHoldCommand(Fleet, chkOnHold.Checked); + cmd = DIRoot.OrderCommands.ToggleOrdersOnHold(Fleet, chkOnHold.Checked); Empire.Current.Commands.Add(cmd); } else - cmd.AreOrdersOnHold = chkOnHold.Checked; + cmd.IsToggleEnabled = chkOnHold.Checked; cmd.Execute(); } } \ No newline at end of file diff --git a/FrEee.UI.WinForms/Controls/PlanetReport.cs b/FrEee.UI.WinForms/Controls/PlanetReport.cs index 3511516d3..ea88a58e7 100644 --- a/FrEee.UI.WinForms/Controls/PlanetReport.cs +++ b/FrEee.UI.WinForms/Controls/PlanetReport.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using FrEee.Utility; using FrEee.Extensions; @@ -12,6 +11,7 @@ using FrEee.Objects.GameState; using FrEee.Modding.Templates; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands.Orders; namespace FrEee.UI.WinForms.Controls; @@ -242,14 +242,14 @@ private void picPortrait_Click(object sender, System.EventArgs e) private void chkRepeat_CheckedChanged(object sender, EventArgs e) { - var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Planet); + var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Planet); if (cmd == null) { - cmd = new ToggleRepeatOrdersCommand(Planet, chkRepeat.Checked); + cmd = DIRoot.OrderCommands.ToggleRepeatOrders(Planet, chkRepeat.Checked); Empire.Current.Commands.Add(cmd); } else - cmd.AreRepeatOrdersEnabled = chkRepeat.Checked; + cmd.IsToggleEnabled = chkRepeat.Checked; cmd.Execute(); } @@ -260,14 +260,14 @@ private void lstOrdersDetail_SelectedIndexChanged(object sender, EventArgs e) private void chkOnHold_CheckedChanged(object sender, EventArgs e) { - var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Planet); + var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Planet); if (cmd == null) { - cmd = new ToggleOrdersOnHoldCommand(Planet, chkOnHold.Checked); + cmd = DIRoot.OrderCommands.ToggleOrdersOnHold(Planet, chkOnHold.Checked); Empire.Current.Commands.Add(cmd); } else - cmd.AreOrdersOnHold = chkOnHold.Checked; + cmd.IsToggleEnabled = chkOnHold.Checked; cmd.Execute(); } } \ No newline at end of file diff --git a/FrEee.UI.WinForms/Controls/SearchBox.Designer.cs b/FrEee.UI.WinForms/Controls/SearchBox.Designer.cs index d12fa59c2..1f5288d27 100644 --- a/FrEee.UI.WinForms/Controls/SearchBox.Designer.cs +++ b/FrEee.UI.WinForms/Controls/SearchBox.Designer.cs @@ -28,37 +28,38 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.textBox = new System.Windows.Forms.TextBox(); - this.SuspendLayout(); + textBox = new System.Windows.Forms.TextBox(); + SuspendLayout(); // // textBox // - this.textBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBox.Location = new System.Drawing.Point(0, 0); - this.textBox.Name = "textBox"; - this.textBox.Size = new System.Drawing.Size(591, 20); - this.textBox.TabIndex = 0; - this.textBox.SizeChanged += new System.EventHandler(this.textBox_SizeChanged); - this.textBox.TextChanged += new System.EventHandler(this.textBox_TextChanged); - this.textBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox_KeyDown); - this.textBox.Leave += new System.EventHandler(this.textBox_Leave); + textBox.Dock = System.Windows.Forms.DockStyle.Fill; + textBox.Location = new System.Drawing.Point(0, 0); + textBox.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + textBox.Name = "textBox"; + textBox.Size = new System.Drawing.Size(690, 23); + textBox.TabIndex = 0; + textBox.SizeChanged += textBox_SizeChanged; + textBox.TextChanged += textBox_TextChanged; + textBox.KeyDown += textBox_KeyDown; + textBox.Leave += textBox_Leave; // // SearchBox // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.Color.Black; - this.Controls.Add(this.textBox); - this.ForeColor = System.Drawing.Color.White; - this.Name = "SearchBox"; - this.Size = new System.Drawing.Size(591, 22); - this.Load += new System.EventHandler(this.SearchBox_Load); - this.SizeChanged += new System.EventHandler(this.SearchBox_SizeChanged); - this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.SearchBox_KeyDown); - this.Leave += new System.EventHandler(this.SearchBox_Leave); - this.ResumeLayout(false); - this.PerformLayout(); - + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + BackColor = System.Drawing.Color.Black; + Controls.Add(textBox); + ForeColor = System.Drawing.Color.White; + Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + Name = "SearchBox"; + Size = new System.Drawing.Size(690, 25); + Load += SearchBox_Load; + SizeChanged += SearchBox_SizeChanged; + KeyDown += SearchBox_KeyDown; + Leave += SearchBox_Leave; + ResumeLayout(false); + PerformLayout(); } #endregion diff --git a/FrEee.UI.WinForms/Controls/SearchBox.resx b/FrEee.UI.WinForms/Controls/SearchBox.resx index 29dcb1b3a..4f24d55cd 100644 --- a/FrEee.UI.WinForms/Controls/SearchBox.resx +++ b/FrEee.UI.WinForms/Controls/SearchBox.resx @@ -1,17 +1,17 @@  - diff --git a/FrEee.UI.WinForms/Controls/SpaceVehicleReport.cs b/FrEee.UI.WinForms/Controls/SpaceVehicleReport.cs index 62cade2cf..5fd52780f 100644 --- a/FrEee.UI.WinForms/Controls/SpaceVehicleReport.cs +++ b/FrEee.UI.WinForms/Controls/SpaceVehicleReport.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Technology; using FrEee.Objects.Vehicles; using FrEee.Utility; @@ -14,6 +13,7 @@ using FrEee.Objects.Civilization.Orders; using FrEee.Objects.Civilization.CargoStorage; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands.Orders; namespace FrEee.UI.WinForms.Controls; @@ -183,11 +183,11 @@ private void btnClearOrders_Click(object sender, System.EventArgs e) { foreach (var order in vehicle.Orders.ToArray()) { - var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); + var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); if (addCmd == null) { // not a newly added order, so create a remove command to take it off the server - var remCmd = new RemoveOrderCommand(Vehicle, order); + var remCmd = DIRoot.OrderCommands.RemoveOrder(Vehicle, order); Empire.Current.Commands.Add(remCmd); remCmd.Execute(); // show change locally } @@ -210,11 +210,11 @@ private void btnDeleteOrder_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null) { - var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); + var addCmd = Empire.Current.Commands.OfType().SingleOrDefault(c => c.Order == order); if (addCmd == null) { // not a newly added order, so create a remove command to take it off the server - var remCmd = new RemoveOrderCommand(Vehicle, order); + var remCmd = DIRoot.OrderCommands.RemoveOrder(Vehicle, order); Empire.Current.Commands.Add(remCmd); remCmd.Execute(); // show change locally } @@ -237,7 +237,7 @@ private void btnOrderGoesDown_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null && vehicle.Orders.IndexOf(order) < vehicle.Orders.Count() - 1) { - var cmd = new RearrangeOrdersCommand( + var cmd = DIRoot.OrderCommands.RearrangeOrders( vehicle, order, 1); Empire.Current.Commands.Add(cmd); cmd.Execute(); // show change locally @@ -253,7 +253,7 @@ private void btnOrderGoesUp_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null && vehicle.Orders.IndexOf(order) > 0) { - var cmd = new RearrangeOrdersCommand( + var cmd = DIRoot.OrderCommands.RearrangeOrders( vehicle, order, -1); Empire.Current.Commands.Add(cmd); cmd.Execute(); // show change locally @@ -271,7 +271,7 @@ private void btnOrderToBottom_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null) { - var cmd = new RearrangeOrdersCommand( + var cmd = DIRoot.OrderCommands.RearrangeOrders( vehicle, order, Vehicle.Orders.Count() - vehicle.Orders.IndexOf(order) - 1); Empire.Current.Commands.Add(cmd); cmd.Execute(); // show change locally @@ -287,7 +287,7 @@ private void btnOrderToTop_Click(object sender, System.EventArgs e) var order = (IOrder)lstOrdersDetail.SelectedItem; if (order != null) { - var cmd = new RearrangeOrdersCommand( + var cmd = DIRoot.OrderCommands.RearrangeOrders( vehicle, order, -vehicle.Orders.IndexOf(order)); Empire.Current.Commands.Add(cmd); cmd.Execute(); // show change locally @@ -400,27 +400,31 @@ public override int GetHashCode() private void chkRepeat_CheckedChanged(object sender, EventArgs e) { - var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Vehicle); + var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Vehicle); if (cmd == null) { - cmd = new ToggleRepeatOrdersCommand(Vehicle, chkRepeat.Checked); + cmd = DIRoot.OrderCommands.ToggleRepeatOrders(Vehicle, chkRepeat.Checked); Empire.Current.Commands.Add(cmd); } else - cmd.AreRepeatOrdersEnabled = chkRepeat.Checked; + { + cmd.IsToggleEnabled = chkRepeat.Checked; + } cmd.Execute(); } private void chkOnHold_CheckedChanged(object sender, EventArgs e) { - var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Vehicle); + var cmd = Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == Vehicle); if (cmd == null) { - cmd = new ToggleOrdersOnHoldCommand(Vehicle, chkOnHold.Checked); + cmd = DIRoot.OrderCommands.ToggleOrdersOnHold(Vehicle, chkOnHold.Checked); Empire.Current.Commands.Add(cmd); } else - cmd.AreOrdersOnHold = chkOnHold.Checked; + { + cmd.IsToggleEnabled = chkOnHold.Checked; + } cmd.Execute(); } } \ No newline at end of file diff --git a/FrEee.UI.WinForms/Forms/ActivateAbilityForm.cs b/FrEee.UI.WinForms/Forms/ActivateAbilityForm.cs index 14d1d8a3c..272f0bc6a 100644 --- a/FrEee.UI.WinForms/Forms/ActivateAbilityForm.cs +++ b/FrEee.UI.WinForms/Forms/ActivateAbilityForm.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using FrEee.Extensions; using FrEee.UI.WinForms.Utility.Extensions; @@ -12,6 +11,8 @@ using FrEee.Objects.GameState; using FrEee.Objects.Civilization.Orders; using FrEee.Modding.Abilities; +using FrEee.Utility; +using FrEee.Gameplay.Commands.Orders; namespace FrEee.UI.WinForms.Forms; @@ -272,7 +273,7 @@ private void btnOK_Click(object sender, EventArgs e) // issue command var order = new ActivateAbilityOrder(sel.Source, sel.Ability, target); - var cmd = new AddOrderCommand(sobj, order); + var cmd = DIRoot.OrderCommands.AddOrder(sobj, order); cmd.Execute(); Empire.Current.Commands.Add(cmd); Close(); diff --git a/FrEee.UI.WinForms/Forms/BattleReplayForm.cs b/FrEee.UI.WinForms/Forms/BattleReplayForm.cs index 71aa61f43..985f16de7 100644 --- a/FrEee.UI.WinForms/Forms/BattleReplayForm.cs +++ b/FrEee.UI.WinForms/Forms/BattleReplayForm.cs @@ -10,20 +10,20 @@ using System.Linq; using System.Windows.Forms; using FrEee.Processes.Combat; -using FrEee.Processes.Combat.Grid; +using FrEee.Processes.Combat.Events; namespace FrEee.UI.WinForms.Forms; -public partial class BattleReplayForm : GameForm, IBindable +public partial class BattleReplayForm : GameForm, IBindable { - public BattleReplayForm(Battle b) + public BattleReplayForm(IBattle b) { InitializeComponent(); Bind(b); reportPanel.Controls.Add(CreateLogListBox()); } - public Battle Battle { get; private set; } + public IBattle Battle { get; private set; } public ICombatant SelectedCombatant { @@ -47,7 +47,7 @@ public ICombatant SelectedCombatant private ICombatant selectedCombatant; - public void Bind(Battle data) + public void Bind(IBattle data) { Battle = data; Bind(); diff --git a/FrEee.UI.WinForms/Forms/BattleResultsForm.cs b/FrEee.UI.WinForms/Forms/BattleResultsForm.cs index e9cd28afb..ef4a0b541 100644 --- a/FrEee.UI.WinForms/Forms/BattleResultsForm.cs +++ b/FrEee.UI.WinForms/Forms/BattleResultsForm.cs @@ -12,7 +12,6 @@ using System.Windows.Forms; using FrEee.Objects.Vehicles; using FrEee.Processes.Combat; -using FrEee.Processes.Combat.Grid; namespace FrEee.UI.WinForms.Forms; @@ -144,13 +143,7 @@ private void btnClose_Click(object sender, EventArgs e) private void btnReplay_Click(object sender, EventArgs e) { - Form form; - //if (Battle is FrEee.Processes.Combat.Simple.Battle b) - // form = new LogForm(MainGameForm.Instance, b.Log); - if (Battle is Battle b2) - form = new BattleReplayForm(b2); - else - throw new Exception($"Unknown battle type {Battle.GetType()}!"); + BattleReplayForm form = new(Battle); this.ShowChildForm(form); } diff --git a/FrEee.UI.WinForms/Forms/CombatSimulatorForm.cs b/FrEee.UI.WinForms/Forms/CombatSimulatorForm.cs index b1573bdd0..5a1cfda35 100644 --- a/FrEee.UI.WinForms/Forms/CombatSimulatorForm.cs +++ b/FrEee.UI.WinForms/Forms/CombatSimulatorForm.cs @@ -1,6 +1,5 @@ using FrEee.Objects; using FrEee.Objects.Civilization; -using FrEee.Processes.Combat.Grid; using FrEee.Objects.Space; using FrEee.Objects.Vehicles; using FrEee.Modding; @@ -14,6 +13,7 @@ using System.Windows.Forms; using FrEee.Objects.GameState; using FrEee.Processes.Combat; +using FrEee.Utility; namespace FrEee.UI.WinForms.Forms; @@ -255,7 +255,7 @@ private void btnOK_Click(object sender, EventArgs e) simPlanet.Sector = new Sector(new StarSystem(0) { Name = "Simulation" }, new Point()); foreach (Troop t in Empires.SelectMany(se => se.Troops.Select(ss => ss.Unit))) planet.Cargo.Units.Add(t); - battle = new GroundBattle(planet); + battle = DIRoot.Battles.BuildGroundBattle(planet); // simulate the battle battle.Resolve(); @@ -267,7 +267,7 @@ private void btnOK_Click(object sender, EventArgs e) ispobj.Sector = location; // create battle with all our combatants //var battle = new Battle_Space(Empires.SelectMany(se => se.SpaceObjects.Select(ss => ss.SpaceObject))); - battle = new SpaceBattle(location); + battle = DIRoot.Battles.BuildSpaceBattle(location); // simulate the battle battle.Resolve(); diff --git a/FrEee.UI.WinForms/Forms/ConstructionQueueForm.cs b/FrEee.UI.WinForms/Forms/ConstructionQueueForm.cs index 08018dab3..a7b65c9fd 100644 --- a/FrEee.UI.WinForms/Forms/ConstructionQueueForm.cs +++ b/FrEee.UI.WinForms/Forms/ConstructionQueueForm.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using FrEee.Objects.Technology; using FrEee.Modding; @@ -19,6 +18,9 @@ using FrEee.Objects.GameState; using FrEee.Objects.Civilization.CargoStorage; using FrEee.Modding.Templates; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Orders; +using FrEee.Gameplay.Commands.Designs; namespace FrEee.UI.WinForms.Forms; @@ -348,7 +350,7 @@ private void btnBottom_Click(object sender, EventArgs e) var sel = SelectedOrders.ToArray(); foreach (var item in sel.Select(o => new { Order = o, OldIndex = ConstructionQueue.Orders.IndexOf(o), NewIndex = ConstructionQueue.Orders.Count() })) { - var cmd = new RearrangeOrdersCommand(ConstructionQueue, item.Order, item.NewIndex - item.OldIndex); + var cmd = DIRoot.OrderCommands.RearrangeOrders(ConstructionQueue, item.Order, item.NewIndex - item.OldIndex); newCommands.Add(cmd); cmd.Execute(); } @@ -386,7 +388,7 @@ private void btnDown_Click(object sender, EventArgs e) delta = FindSameItemsCountBelow(sel.Last()) + sel.Count() - 1; foreach (var order in sel) { - var cmd = new RearrangeOrdersCommand(ConstructionQueue, order, delta); + var cmd = DIRoot.OrderCommands.RearrangeOrders(ConstructionQueue, order, delta); newCommands.Add(cmd); cmd.Execute(); } @@ -407,7 +409,7 @@ private void btnTop_Click(object sender, EventArgs e) var sel = SelectedOrders.ToArray(); foreach (var item in sel.Select(o => new { Order = o, OldIndex = ConstructionQueue.Orders.IndexOf(o), NewIndex = sel.IndexOf(o) })) { - var cmd = new RearrangeOrdersCommand(ConstructionQueue, item.Order, item.NewIndex - item.OldIndex); + var cmd = DIRoot.OrderCommands.RearrangeOrders(ConstructionQueue, item.Order, item.NewIndex - item.OldIndex); newCommands.Add(cmd); cmd.Execute(); } @@ -424,7 +426,7 @@ private void btnUp_Click(object sender, EventArgs e) delta = -FindSameItemsCountAbove(sel.First()); foreach (var order in sel) { - var cmd = new RearrangeOrdersCommand(ConstructionQueue, order, delta); + var cmd = DIRoot.OrderCommands.RearrangeOrders(ConstructionQueue, order, delta); newCommands.Add(cmd); cmd.Execute(); } @@ -446,8 +448,8 @@ private void CancelChanges() ConstructionQueue.Orders.Clear(); foreach (var order in oldQueue) ConstructionQueue.Orders.Add(order); - Empire.Current.Commands.Remove(Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == ConstructionQueue)); - Empire.Current.Commands.Remove(Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == ConstructionQueue)); + Empire.Current.Commands.Remove(Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == ConstructionQueue)); + Empire.Current.Commands.Remove(Empire.Current.Commands.OfType().SingleOrDefault(x => x.Executor == ConstructionQueue)); ConstructionQueue.AreOrdersOnHold = wasOnHold; ConstructionQueue.AreRepeatOrdersEnabled = wasRepeat; } @@ -616,7 +618,7 @@ private void lstFacilities_MouseDown(object sender, MouseEventArgs e) { var order = new ConstructionOrder { Template = template }; ConstructionQueue.Orders.Add(order); - var cmd = new AddOrderCommand + var cmd = DIRoot.OrderCommands.AddOrder ( ConstructionQueue, order @@ -755,7 +757,7 @@ private void lstShips_MouseDown(object sender, MouseEventArgs e) // add to queue var order = design.CreateConstructionOrder(ConstructionQueue); ConstructionQueue.Orders.Add(order); - var cmd = new AddOrderCommand + var cmd = DIRoot.OrderCommands.AddOrder ( ConstructionQueue, order @@ -837,7 +839,7 @@ private void lstUpgrades_MouseDown(object sender, MouseEventArgs e) { var order = new UpgradeFacilityOrder(upgrade); ConstructionQueue.Orders.Add(order); - var cmd = new AddOrderCommand + var cmd = DIRoot.OrderCommands.AddOrder ( ConstructionQueue, order @@ -895,7 +897,7 @@ private string MakeUpgradePresentQueuedString(int present, int queued) private void RemoveOrder(IConstructionOrder order, bool rebindGui = true) { - var cmds = Empire.Current.Commands.OfType().Where(o => o.Order == order).ToArray(); + var cmds = Empire.Current.Commands.OfType().Where(o => o.Order == order).ToArray(); if (cmds.Any()) { // remove add-order command since the order is new this turn @@ -904,7 +906,7 @@ private void RemoveOrder(IConstructionOrder order, bool rebindGui = true) } else { - cmds = newCommands.OfType().Where(o => o.Order == order).ToArray(); + cmds = newCommands.OfType().Where(o => o.Order == order).ToArray(); if (cmds.Any()) { // Not only new this turn, but new this instance of this form! @@ -914,7 +916,7 @@ private void RemoveOrder(IConstructionOrder order, bool rebindGui = true) else { // add remove-order command - var cmd = new RemoveOrderCommand(ConstructionQueue, order); + var cmd = DIRoot.OrderCommands.RemoveOrder(ConstructionQueue, order); newCommands.Add(cmd); } } @@ -996,27 +998,27 @@ private void btnHelp_Click(object sender, EventArgs e) private void chkRepeat_CheckedChanged(object sender, EventArgs e) { - var cmd = (Empire.Current.Commands.Union(newCommands ?? Enumerable.Empty())).OfType().SingleOrDefault(x => x.Executor == ConstructionQueue); + var cmd = (Empire.Current.Commands.Union(newCommands ?? Enumerable.Empty())).OfType().SingleOrDefault(x => x.Executor == ConstructionQueue); if (cmd == null) { - cmd = new ToggleRepeatOrdersCommand(ConstructionQueue, chkRepeat.Checked); + cmd = DIRoot.OrderCommands.ToggleRepeatOrders(ConstructionQueue, chkRepeat.Checked); newCommands.Add(cmd); } else - cmd.AreRepeatOrdersEnabled = chkRepeat.Checked; + cmd.IsToggleEnabled = chkRepeat.Checked; cmd.Execute(); } private void chkOnHold_CheckedChanged(object sender, EventArgs e) { - var cmd = (Empire.Current.Commands.Union(newCommands ?? Enumerable.Empty())).OfType().SingleOrDefault(x => x.Executor == ConstructionQueue); + var cmd = (Empire.Current.Commands.Union(newCommands ?? Enumerable.Empty())).OfType().SingleOrDefault(x => x.Executor == ConstructionQueue); if (cmd == null) { - cmd = new ToggleOrdersOnHoldCommand(ConstructionQueue, chkOnHold.Checked); + cmd = DIRoot.OrderCommands.ToggleOrdersOnHold(ConstructionQueue, chkOnHold.Checked); newCommands.Add(cmd); } else - cmd.AreOrdersOnHold = chkOnHold.Checked; + cmd.IsToggleEnabled = chkOnHold.Checked; cmd.Execute(); } } \ No newline at end of file diff --git a/FrEee.UI.WinForms/Forms/DesignListForm.cs b/FrEee.UI.WinForms/Forms/DesignListForm.cs index 309425048..eb68f153c 100644 --- a/FrEee.UI.WinForms/Forms/DesignListForm.cs +++ b/FrEee.UI.WinForms/Forms/DesignListForm.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Technology; using FrEee.Utility; using FrEee.Extensions; @@ -14,6 +13,8 @@ using FrEee.Objects.Vehicles; using FrEee.Objects.GameState; using FrEee.Objects.Space; +using FrEee.Gameplay.Commands.Orders; +using FrEee.Gameplay.Commands.Designs; namespace FrEee.UI.WinForms.Forms; @@ -161,10 +162,12 @@ private void btnObsolete_Click(object sender, EventArgs e) foreach (IDesign d in lstDesigns.SelectedItems.Cast().Select(item => item.Tag)) { d.IsObsolete = !d.IsObsolete; - foreach (var cmd in Empire.Current.Commands.OfType().Where(cmd => (cmd.Design ?? cmd.NewDesign) == d && cmd.IsObsolete != d.IsObsolete).ToArray()) + foreach (var cmd in Empire.Current.Commands.OfType().Where(cmd => (cmd.Design ?? cmd.NewDesign) == d && cmd.IsObsolete != d.IsObsolete).ToArray()) Empire.Current.Commands.Remove(cmd); - if (!Empire.Current.Commands.OfType().Where(cmd => cmd.Design == d && cmd.IsObsolete == d.IsObsolete).Any()) - Empire.Current.Commands.Add(new SetObsoleteFlagCommand(d, d.IsObsolete)); + if (!Empire.Current.Commands.OfType().Where(cmd => cmd.Design == d && cmd.IsObsolete == d.IsObsolete).Any()) + { + Empire.Current.Commands.Add(DIRoot.DesignCommands.SetObsoleteFlag(d, d.IsObsolete)); + } } BindDesignList(); } diff --git a/FrEee.UI.WinForms/Forms/DiplomacyForm.cs b/FrEee.UI.WinForms/Forms/DiplomacyForm.cs index 2dd723de2..bf06ad887 100644 --- a/FrEee.UI.WinForms/Forms/DiplomacyForm.cs +++ b/FrEee.UI.WinForms/Forms/DiplomacyForm.cs @@ -1,7 +1,6 @@ using FrEee.Objects.Civilization; using FrEee.Objects.Civilization.Diplomacy; using FrEee.Objects.Civilization.Diplomacy.Clauses; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using FrEee.Objects.Technology; using FrEee.Objects.Vehicles; @@ -18,6 +17,7 @@ using FrEee.Objects.Civilization.Diplomacy.Messages; using FrEee.Objects.Civilization.Diplomacy.Actions; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands; namespace FrEee.UI.WinForms.Forms; @@ -194,7 +194,7 @@ private void btnSend_Click(object sender, EventArgs e) msg.InReplyTo = InReplyTo; // create a command to send it - var cmd = new SendMessageCommand(msg); + var cmd = DIRoot.MessageCommands.SendMessage(msg); Empire.Current.Commands.Add(cmd); // all done! diff --git a/FrEee.UI.WinForms/Forms/EmpireListForm.cs b/FrEee.UI.WinForms/Forms/EmpireListForm.cs index 062823240..09646354e 100644 --- a/FrEee.UI.WinForms/Forms/EmpireListForm.cs +++ b/FrEee.UI.WinForms/Forms/EmpireListForm.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Utility; using FrEee.Extensions; using FrEee.UI.WinForms.Utility.Extensions; @@ -11,6 +10,8 @@ using System.Windows.Forms; using FrEee.Objects.Civilization.Diplomacy.Messages; using FrEee.Objects.GameState; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Messages; namespace FrEee.UI.WinForms.Forms; @@ -134,7 +135,11 @@ private void BindEmpire(Empire emp, TabPage tab = null) lblBudgetWarning.Visible = emp != Empire.Current; // message log - var msgs = Empire.Current.IncomingMessages.Where(m => m.Owner == emp).Union(Empire.Current.SentMessages.Where(m => m.Recipient == emp)).Union(Empire.Current.Commands.OfType().Select(cmd => cmd.Message)); + var msgs = Empire.Current.IncomingMessages + .Where(m => m.Owner == emp) + .Union(Empire.Current.SentMessages.Where(m => m.Recipient == emp)) + .Union(Empire.Current.Commands.OfType() + .Select(cmd => cmd.Message)); lstMessages.Initialize(64, 64); foreach (var msg in msgs.OrderByDescending(m => m.TurnNumber)) lstMessages.AddItemWithImage(msg.TurnNumber.ToStardate(), "", msg, msg.Owner.Portrait, null, msg.Owner == Empire.Current ? "Us" : msg.Owner.Name, msg.Recipient == Empire.Current ? "Us" : msg.Recipient.Name, msg.Text); @@ -194,11 +199,13 @@ private void btnDelete_Click(object sender, EventArgs e) { if (Empire.Current.IncomingMessages.Contains(msg) || Empire.Current.SentMessages.Contains(msg)) { - var cmd = new DeleteMessageCommand(msg); + var cmd = DIRoot.MessageCommands.DeleteMessage(msg); Empire.Current.Commands.Add(cmd); cmd.Execute(); } - var sendCommand = Empire.Current.Commands.OfType().SingleOrDefault(cmd => cmd.Message == msg); + var sendCommand = Empire.Current.Commands + .OfType() + .SingleOrDefault(cmd => cmd.Message == msg); if (sendCommand != null) Empire.Current.Commands.Remove(sendCommand); } diff --git a/FrEee.UI.WinForms/Forms/FleetTransferForm.cs b/FrEee.UI.WinForms/Forms/FleetTransferForm.cs index 7e424ec49..1adfddcc2 100644 --- a/FrEee.UI.WinForms/Forms/FleetTransferForm.cs +++ b/FrEee.UI.WinForms/Forms/FleetTransferForm.cs @@ -1,6 +1,5 @@  using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using FrEee.Objects.Vehicles; using FrEee.Utility; @@ -13,6 +12,8 @@ using System.Drawing; using System.Linq; using System.Windows.Forms; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Fleets; namespace FrEee.UI.WinForms.Forms; @@ -111,23 +112,23 @@ private void BindFleets(Fleet selected = null) CreateNode(treeFleets, f); // create any new fleets - foreach (var cmd in newCommands.OfType()) + foreach (var cmd in newCommands.OfType()) CreateNode(treeFleets, cmd.Fleet); // remove vehicles that are being removed from fleets - foreach (var cmd in newCommands.OfType()) + foreach (var cmd in newCommands.OfType()) { var node = FindNode(treeFleets, cmd.Executor); node.Remove(); } - foreach (var cmd in newCommands.OfType()) + foreach (var cmd in newCommands.OfType()) { var node = FindNode(treeFleets, cmd.Executor); node.Remove(); } // add vehicles that are being added to fleets - foreach (var cmd in newCommands.OfType()) + foreach (var cmd in newCommands.OfType()) { var node = FindNode(treeFleets, cmd.Fleet); CreateNode(node, cmd.Executor); @@ -149,13 +150,13 @@ private void BindVehicles(IMobileSpaceObject selected = null) vehicles.Add(v); // add vehicles that are being removed from fleets (but not fleets themselves, those go in the fleets tree) - foreach (var v in newCommands.OfType().Select(c => c.Executor).OfType()) + foreach (var v in newCommands.OfType().Select(c => c.Executor).OfType()) vehicles.Add(v); - foreach (var v in newCommands.OfType().SelectMany(c => c.Executor.Vehicles.OfType())) + foreach (var v in newCommands.OfType().SelectMany(c => c.Executor.Vehicles.OfType())) vehicles.Add(v); // remove vehicles that are being added to fleets - foreach (var v in newCommands.OfType().Select(c => c.Executor).OfType()) + foreach (var v in newCommands.OfType().Select(c => c.Executor).OfType()) vehicles.Remove(v); // make a tree of vehicles @@ -205,7 +206,7 @@ private void btnCreate_Click(object sender, EventArgs e) var fleet = new Fleet(); fleet.Name = txtFleetName.Text; - var cmd = new CreateFleetCommand(fleet, sector); + var cmd = DIRoot.FleetCommands.CreateFleet(fleet, sector); newCommands.Add(cmd); newFleets.Add(fleet); @@ -290,17 +291,17 @@ private void DisbandFleet(Fleet fleet) if (!newFleets.Contains(fleet)) { // create a disband command - var cmd = new DisbandFleetCommand(fleet); + var cmd = DIRoot.FleetCommands.DisbandFleet(fleet); newCommands.Add(cmd); } else { // delete any create/join/leave commands - var cmd = newCommands.OfType().Single(c => c.Fleet == fleet); + var cmd = newCommands.OfType().Single(c => c.Fleet == fleet); newCommands.Remove(cmd); - foreach (var c in newCommands.OfType().Where(c => c.Fleet == fleet)) + foreach (var c in newCommands.OfType().Where(c => c.Fleet == fleet)) newCommands.Remove(c); - foreach (var c in newCommands.OfType().Where(c => c.Executor.Container == fleet)) + foreach (var c in newCommands.OfType().Where(c => c.Executor.Container == fleet)) newCommands.Remove(c); } @@ -323,16 +324,16 @@ private void DoAddToFleet(IMobileSpaceObject vehicle, Fleet fleet) if (fleet == null) return; - JoinFleetCommand cmd; + IJoinFleetCommand cmd; if (!newFleets.Contains(fleet)) { // fleet already exists, we can add to it - cmd = new JoinFleetCommand(vehicle, fleet); + cmd = DIRoot.FleetCommands.JoinFleet(vehicle, fleet); } else { // fleet is new, we need to reference it by its command - cmd = new JoinFleetCommand(vehicle, newCommands.OfType().Single(c => c.Fleet == fleet)); + cmd = DIRoot.FleetCommands.JoinFleet(vehicle, newCommands.OfType().Single(c => c.Fleet == fleet)); } newCommands.Add(cmd); } @@ -405,7 +406,7 @@ private void RemoveFromFleet(IMobileSpaceObject vehicle) if (vehicle.Container == null) return; - var cmd = new LeaveFleetCommand(vehicle); + var cmd = DIRoot.FleetCommands.LeaveFleet(vehicle); newCommands.Add(cmd); BindVehicles(vehicle); var node = treeFleets.GetAllNodes().Single(x => x.Tag == vehicle); diff --git a/FrEee.UI.WinForms/Forms/HostConsoleForm.cs b/FrEee.UI.WinForms/Forms/HostConsoleForm.cs index bb2f5381c..1d4b3890a 100644 --- a/FrEee.UI.WinForms/Forms/HostConsoleForm.cs +++ b/FrEee.UI.WinForms/Forms/HostConsoleForm.cs @@ -121,7 +121,7 @@ void ProcessTurn() var t = new Thread(new ThreadStart(() => { status.Message = "Processing turn"; - var processor = new TurnProcessor(); + var processor = DIRoot.TurnProcessor; processor.ProcessTurn(Game.Current, false, status, 0.5); Game.SaveAll(status, 1.0); })); diff --git a/FrEee.UI.WinForms/Forms/MainGameForm.cs b/FrEee.UI.WinForms/Forms/MainGameForm.cs index c62940cdd..5dc05dd33 100644 --- a/FrEee.UI.WinForms/Forms/MainGameForm.cs +++ b/FrEee.UI.WinForms/Forms/MainGameForm.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using FrEee.Objects.Technology; using FrEee.Objects.Vehicles; @@ -27,6 +26,9 @@ using FrEee.UI.Blazor.Views.GalaxyMapModes; using FrEee.Processes.Combat; using FrEee.Modding.Abilities; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Orders; +using FrEee.Gameplay.Commands.Messages; namespace FrEee.UI.WinForms.Forms; @@ -764,8 +766,8 @@ private IEnumerable FindTodos() var messages = Empire.Current.IncomingMessages.OfType().Count(m => m.TurnNumber >= Game.Current.TurnNumber - 1 && - !Empire.Current.Commands.OfType().Where(c => c.Message.InReplyTo == m).Any() && - !Empire.Current.Commands.OfType().Where(c => c.Message == m).Any()); + !Empire.Current.Commands.OfType().Where(c => c.Message.InReplyTo == m).Any() && + !Empire.Current.Commands.OfType().Where(c => c.Message == m).Any()); if (messages == 1) todos.Add("1 unresolved diplomatic proposal"); else if (messages > 1) @@ -1200,7 +1202,7 @@ private void SaveCommands(bool endTurn) Game.Load(Game.Current.Name, Game.Current.TurnNumber); status.Progress = 0.25; status.Message = "Processing turn"; - var processor = new TurnProcessor(); + var processor = DIRoot.TurnProcessor; processor.ProcessTurn(Game.Current, false, status, 0.5); status.Message = "Saving game"; Game.SaveAll(status, 0.75); @@ -1339,10 +1341,10 @@ private void SetWaypoint(int waypointNumber, bool redirect) // set the waypoint ICommand cmd; - cmd = new CreateWaypointCommand(waypoint); + cmd = DIRoot.WaypointCommands.CreateWaypoint(waypoint); Empire.Current.Commands.Add(cmd); cmd.Execute(); - cmd = new HotkeyWaypointCommand(waypoint, waypointNumber, redirect); + cmd = DIRoot.WaypointCommands.HotkeyWaypoint(waypoint, waypointNumber, redirect); Empire.Current.Commands.Add(cmd); cmd.Execute(); @@ -1419,7 +1421,7 @@ private void starSystemView_SectorClicked(StarSystemView sender, Sector sector) var order = new MoveOrder(sector, !aggressiveMode); v.AddOrder(order); BindReport(); - var cmd = new AddOrderCommand(v, order); + var cmd = DIRoot.OrderCommands.AddOrder(v, order); Empire.Current.Commands.Add(cmd); starSystemView.Invalidate(); // show move lines ChangeCommandMode(CommandMode.None, null); diff --git a/FrEee.UI.WinForms/Forms/MinistersForm.cs b/FrEee.UI.WinForms/Forms/MinistersForm.cs index e421ac9bf..3c6b26b53 100644 --- a/FrEee.UI.WinForms/Forms/MinistersForm.cs +++ b/FrEee.UI.WinForms/Forms/MinistersForm.cs @@ -1,5 +1,6 @@ -using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; +using FrEee.Gameplay.Commands.Messages; +using FrEee.Gameplay.Commands.Ministers; +using FrEee.Objects.Civilization; using FrEee.Utility; using System; using System.Collections.Generic; @@ -34,10 +35,10 @@ private void MinistersForm_Load(object sender, EventArgs e) private void btnClose_Click(object sender, EventArgs e) { - var cmd = Empire.Current.Commands.OfType().SingleOrDefault(); + var cmd = Empire.Current.Commands.OfType().SingleOrDefault(); if (cmd == null) { - cmd = new MinisterToggleCommand(); + cmd = DIRoot.MinisterCommands.ToggleMinisters(); Empire.Current.Commands.Add(cmd); } var dict = new SafeDictionary>(); diff --git a/FrEee.UI.WinForms/Forms/RecycleForm.cs b/FrEee.UI.WinForms/Forms/RecycleForm.cs index 35d557587..9e2ab0fc5 100644 --- a/FrEee.UI.WinForms/Forms/RecycleForm.cs +++ b/FrEee.UI.WinForms/Forms/RecycleForm.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Space; using FrEee.Objects.Technology; using FrEee.Objects.Vehicles; @@ -14,6 +13,9 @@ using FrEee.Objects.Civilization.Orders; using FrEee.Objects.Civilization.CargoStorage; using FrEee.Objects.Civilization.Orders.RecycleBehaviors; +using FrEee.Gameplay.Commands; +using FrEee.Gameplay.Commands.Orders; +using FrEee.Utility; namespace FrEee.UI.WinForms.Forms; @@ -109,7 +111,7 @@ private void Bind() { // facilities var fnode = ftnode.AddItemWithImage(f.Name, f, f.Icon); - var orders = Empire.Current.Commands.OfType() + var orders = Empire.Current.Commands.OfType() .Where(x => x.Order is RecycleFacilityOrCargoOrder o && x.Executor == p && o.Target == f) .Select(x => ((RecycleFacilityOrCargoOrder)x.Order).Behavior.Verb); if (orders.Any()) @@ -135,7 +137,7 @@ private void Bind() var vnode = treeVehicles.AddItemWithImage(v.Name, v, v.Icon); if (v is ICargoContainer cc) BindUnitsIn(cc, vnode); - var orders = Empire.Current.Commands.OfType() + var orders = Empire.Current.Commands.OfType() .Where(x => x.Order is RecycleVehicleInSpaceOrder && x.Executor == v) .Select(x => ((RecycleVehicleInSpaceOrder)x.Order).Behavior.Verb); if (orders.Any()) @@ -171,7 +173,7 @@ private void BindUnitsIn(ICargoContainer cc, TreeNode ccnode) { // units var unode = udnode.AddItemWithImage(u.Name, u, u.Icon); - var orders = Empire.Current.Commands.OfType() + var orders = Empire.Current.Commands.OfType() .Where(x => x.Order is RecycleFacilityOrCargoOrder o && x.Executor == cc && o.Target == u) .Select(x => ((RecycleFacilityOrCargoOrder)x.Order).Behavior.Verb); if (orders.Any()) @@ -245,11 +247,11 @@ private void btnRevert_Click(object sender, EventArgs e) private void btnScrap_Click(object sender, EventArgs e) { foreach (var f in SelectedFacilities) - AddCommand(new AddOrderCommand(f.Container, new RecycleFacilityOrCargoOrder(new ScrapBehavior(), f))); + AddCommand(DIRoot.OrderCommands.AddOrder(f.Container, new RecycleFacilityOrCargoOrder(new ScrapBehavior(), f))); foreach (var v in SelectedVehiclesInSpace) - AddCommand(new AddOrderCommand(v, new RecycleVehicleInSpaceOrder(new ScrapBehavior()))); + AddCommand(DIRoot.OrderCommands.AddOrder(v, new RecycleVehicleInSpaceOrder(new ScrapBehavior()))); foreach (var u in SelectedUnitsInCargo) - AddCommand(new AddOrderCommand((IMobileSpaceObject)u.Container, new RecycleFacilityOrCargoOrder(new ScrapBehavior(), u))); + AddCommand(DIRoot.OrderCommands.AddOrder((IMobileSpaceObject)u.Container, new RecycleFacilityOrCargoOrder(new ScrapBehavior(), u))); Bind(); } diff --git a/FrEee.UI.WinForms/Forms/ResearchForm.cs b/FrEee.UI.WinForms/Forms/ResearchForm.cs index fc9289f2c..10e6ec38a 100644 --- a/FrEee.UI.WinForms/Forms/ResearchForm.cs +++ b/FrEee.UI.WinForms/Forms/ResearchForm.cs @@ -1,5 +1,4 @@ using FrEee.Objects.Civilization; -using FrEee.Objects.Commands; using FrEee.Objects.Technology; using FrEee.Modding; using FrEee.Utility; @@ -13,6 +12,7 @@ using System.Linq; using System.Windows.Forms; using FrEee.Objects.GameState; +using FrEee.Gameplay.Commands; namespace FrEee.UI.WinForms.Forms; diff --git a/FrEee.UI.WinForms/FrEee.UI.WinForms.csproj b/FrEee.UI.WinForms/FrEee.UI.WinForms.csproj index aea39861c..2ba1e4b31 100644 --- a/FrEee.UI.WinForms/FrEee.UI.WinForms.csproj +++ b/FrEee.UI.WinForms/FrEee.UI.WinForms.csproj @@ -10,14 +10,15 @@ - - + + + diff --git a/FrEee.UI.WinForms/Program.cs b/FrEee.UI.WinForms/Program.cs index cd642a8bf..67a61e4f5 100644 --- a/FrEee.UI.WinForms/Program.cs +++ b/FrEee.UI.WinForms/Program.cs @@ -15,6 +15,7 @@ using System.Text.RegularExpressions; using System.Windows.Forms; using FrEee.Objects.GameState; +using FrEee.Root; namespace FrEee.UI.WinForms; @@ -92,6 +93,9 @@ void Log(Exception ex) } }; + // set up dependency injection + Configuration.ConfigureDI(); + // HACK - so many things are based on the working directory... Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); @@ -281,7 +285,7 @@ private static int ProcessTurn(bool safe) status.Changed += new Status.ChangedDelegate(status_Changed); Console.WriteLine("Processing turn..."); - var processor = new TurnProcessor(); + var processor = DIRoot.TurnProcessor; var emps = processor.ProcessTurn(Game.Current, false, status); foreach (var emp in emps) Console.WriteLine(emp + " did not submit a PLR file."); diff --git a/FrEee.UI.WinForms/Utility/Extensions/GuiExtensions.cs b/FrEee.UI.WinForms/Utility/Extensions/GuiExtensions.cs index 62b4b4c1d..6027e4ec4 100644 --- a/FrEee.UI.WinForms/Utility/Extensions/GuiExtensions.cs +++ b/FrEee.UI.WinForms/Utility/Extensions/GuiExtensions.cs @@ -8,6 +8,9 @@ using Microsoft.AspNetCore.Components.WebView.WindowsForms; using Microsoft.Extensions.DependencyInjection; +using FrEee.Gameplay; +using FrEee.Gameplay.Commands.Fleets; + namespace FrEee.UI.WinForms.Utility.Extensions; /// diff --git a/FrEee.sln b/FrEee.sln index a3ed87e80..8a2f36e79 100644 --- a/FrEee.sln +++ b/FrEee.sln @@ -22,6 +22,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrEee.Core.Utility", "FrEee EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrEee.Core.Domain", "FrEee.Core.Domain\FrEee.Core.Domain.csproj", "{ECA7A08B-992A-43EC-8D98-2AE887897343}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrEee.Processes", "FrEee.Processes\FrEee.Processes.csproj", "{D616CD99-209A-47F9-85CF-605A18C29E47}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrEee.Root", "FrEee.Root\FrEee.Root.csproj", "{4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrEee.Gameplay", "FrEee.Gameplay\FrEee.Gameplay.csproj", "{B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -104,6 +110,42 @@ Global {ECA7A08B-992A-43EC-8D98-2AE887897343}.Release|x64.Build.0 = Release|Any CPU {ECA7A08B-992A-43EC-8D98-2AE887897343}.Release|x86.ActiveCfg = Release|Any CPU {ECA7A08B-992A-43EC-8D98-2AE887897343}.Release|x86.Build.0 = Release|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Debug|x64.ActiveCfg = Debug|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Debug|x64.Build.0 = Debug|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Debug|x86.ActiveCfg = Debug|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Debug|x86.Build.0 = Debug|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Release|Any CPU.Build.0 = Release|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Release|x64.ActiveCfg = Release|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Release|x64.Build.0 = Release|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Release|x86.ActiveCfg = Release|Any CPU + {D616CD99-209A-47F9-85CF-605A18C29E47}.Release|x86.Build.0 = Release|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Debug|x64.ActiveCfg = Debug|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Debug|x64.Build.0 = Debug|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Debug|x86.ActiveCfg = Debug|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Debug|x86.Build.0 = Debug|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Release|Any CPU.Build.0 = Release|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Release|x64.ActiveCfg = Release|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Release|x64.Build.0 = Release|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Release|x86.ActiveCfg = Release|Any CPU + {4EF4E395-F1D7-4419-90DC-EFEBEF5FDCD5}.Release|x86.Build.0 = Release|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Debug|x64.ActiveCfg = Debug|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Debug|x64.Build.0 = Debug|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Debug|x86.ActiveCfg = Debug|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Debug|x86.Build.0 = Debug|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|Any CPU.Build.0 = Release|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|x64.ActiveCfg = Release|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|x64.Build.0 = Release|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|x86.ActiveCfg = Release|Any CPU + {B79ED9FD-82A2-4806-80EC-CD505CD4A2DC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE