From 0d819878f02acf33108c7361e852fe175b9c97da Mon Sep 17 00:00:00 2001 From: Adams Date: Sat, 28 Sep 2024 10:57:34 -0400 Subject: [PATCH] Interim commit. --- Assets/Resources/Data/Officers.xml | 42 ++ Assets/Resources/Data/PlanetSystems.xml | 560 +++++++++++------- .../Conditionals/ConditionalFactory.cs | 116 ++++ .../Conditionals/GenericConditional.cs | 32 + .../IConditional.cs} | 2 +- Assets/Scripts/Core/GameEntity.cs | 64 +- Assets/Scripts/Core/LeafNode.cs | 4 +- Assets/Scripts/Core/ReferenceNode.cs | 6 +- Assets/Scripts/Core/SceneNode.cs | 22 +- Assets/Scripts/Events/GameEvent.cs | 7 +- Assets/Scripts/Events/MissionEvent.cs | 7 +- Assets/Scripts/Events/NarrativeEvent.cs | 28 + Assets/Scripts/Game/CapitalShip.cs | 7 +- Assets/Scripts/Game/Fleet.cs | 9 +- Assets/Scripts/Game/GalaxyMap.cs | 4 +- Assets/Scripts/Game/Officer.cs | 3 - Assets/Scripts/Game/Planet.cs | 9 +- Assets/Scripts/Game/PlanetSystem.cs | 4 +- Assets/Scripts/Game/Regiment.cs | 4 - Assets/Scripts/Game/SpecialForces.cs | 5 - Assets/Scripts/Game/Starfighter.cs | 5 - Assets/Scripts/Generation/OfficerGenerator.cs | 2 +- Assets/Scripts/Managers/GameEventManager.cs | 4 +- Assets/Scripts/Managers/GameManager.cs | 4 +- Assets/Scripts/Managers/MissionManager.cs | 17 +- .../Scripts/Managers/NarrativeEventManager.cs | 44 ++ Assets/Scripts/Missions/Mission.cs | 5 +- Assets/Tests/EditMode/Core/GameEntityTests.cs | 71 ++- Assets/Tests/EditMode/Core/SceneNodeTests.cs | 154 +++++ Assets/Tests/EditMode/Game/PlanetTests.cs | 113 ++-- .../EditMode/Managers/GameManagerTests.cs | 5 +- .../EditMode/Managers/SaveGameManagerTests.cs | 1 - .../Tests/EditMode/Missions/MissionTests.cs | 2 +- 33 files changed, 1023 insertions(+), 339 deletions(-) create mode 100644 Assets/Scripts/Conditionals/ConditionalFactory.cs create mode 100644 Assets/Scripts/Conditionals/GenericConditional.cs rename Assets/Scripts/{Events/ICondition.cs => Conditionals/IConditional.cs} (93%) create mode 100644 Assets/Scripts/Events/NarrativeEvent.cs create mode 100644 Assets/Scripts/Managers/NarrativeEventManager.cs create mode 100644 Assets/Tests/EditMode/Core/SceneNodeTests.cs diff --git a/Assets/Resources/Data/Officers.xml b/Assets/Resources/Data/Officers.xml index 28a9624..328990e 100644 --- a/Assets/Resources/Data/Officers.xml +++ b/Assets/Resources/Data/Officers.xml @@ -5,6 +5,7 @@ OFEM001 + EMPEROR_PALPATINE Emperor Palpatine FNEMP1 true @@ -36,6 +37,7 @@ OFEM002 + DARTH_VADER Darth Vader FNEMP1 true @@ -66,6 +68,7 @@ OFEM003 + JERJERROD Jerjerrod FNEMP1 @@ -98,6 +101,7 @@ OFEM004 + PIETT Piett FNEMP1 @@ -130,6 +134,7 @@ OFEM005 + VEERS Veers FNEMP1 @@ -162,6 +167,7 @@ OFEM006 + BRANDEI Brandei FNEMP1 @@ -194,6 +200,7 @@ OFEM007 + DORJA Dorja FNEMP1 @@ -226,6 +233,7 @@ OFEM008 + BIN_ESSADA Bin Essada FNEMP1 @@ -258,6 +266,7 @@ OFEM009 + NILES_FERRIER Niles Ferrier FNEMP1 @@ -290,6 +299,7 @@ OFEM010 + GRAMMEL Grammel FNEMP1 @@ -322,6 +332,7 @@ OFEM011 + GRIFF Griff FNEMP1 @@ -354,6 +365,7 @@ OFEM012 + KLEV Klev FNEMP1 @@ -386,6 +398,7 @@ OFEM013 + NEEDA Needa FNEMP1 @@ -418,6 +431,7 @@ OFEM014 + BANE_NOTHOS Bane Nothos FNEMP1 @@ -450,6 +464,7 @@ OFEM015 + ORLOK Orlok FNEMP1 @@ -482,6 +497,7 @@ OFEM016 + PALLAEON Pallaeon FNEMP1 @@ -514,6 +530,7 @@ OFEM017 + SCREED Screed FNEMP1 @@ -546,6 +563,7 @@ OFEM018 + THRAWN Thrawn FNEMP1 @@ -578,6 +596,7 @@ OFEM019 + ZUGGS Zuggs FNEMP1 @@ -610,6 +629,7 @@ OFEM020 + DAALA Daala FNEMP1 @@ -642,6 +662,7 @@ OFEM021 + THANAS Pter Thanas FNEMP1 @@ -677,6 +698,7 @@ OFAL001 + MON_MOTHMA Mon Mothma FNALL1 true @@ -706,6 +728,7 @@ OFAL002 + LEIA_ORGANA Leia Organa FNALL1 true @@ -735,6 +758,7 @@ OFAL003 + LUKE_SKYWALKER Luke Skywalker FNALL1 true @@ -765,6 +789,7 @@ OFAL004 + HAN_SOLO Han Solo FNALL1 true @@ -795,6 +820,7 @@ OFAL005 + ACKBAR Ackbar FNALL1 @@ -827,6 +853,7 @@ OFAL006 + WEDGE_ANTILLES Wedge Antilles FNALL1 @@ -859,6 +886,7 @@ OFAL007 + LANDO_CALRISSIAN Lando Calrissian FNALL1 @@ -891,6 +919,7 @@ OFAL008 + CHEWBACCA Chewbacca FNALL1 @@ -923,6 +952,7 @@ OFAL009 + JAN_DODONNA Jan Dodonna FNALL1 @@ -955,6 +985,7 @@ OFAL010 + CRIX_MADINE Crix Madine FNALL1 @@ -987,6 +1018,7 @@ OFAL011 + CARLIST_RIEEKAN Carlist Rieekan FNALL1 @@ -1019,6 +1051,7 @@ OFAL012 + AFYON Afyon FNALL1 @@ -1051,6 +1084,7 @@ OFAL0113 + DRAYSON Drayson FNALL1 @@ -1083,6 +1117,7 @@ OFAL014 + BORSK_FEYLA Borsk Fey'la FNALL1 @@ -1115,6 +1150,7 @@ OFAL015 + TURA_RAFTICAN Tura Raftican FNALL1 @@ -1147,6 +1183,7 @@ OFAL016 + BREN_DERLIN Bren Derlin FNALL1 @@ -1179,6 +1216,7 @@ OFAL017 + GARM_BEL_IBLIS Garm Bel Iblis FNALL1 @@ -1211,6 +1249,7 @@ OFAL018 + TALON_KARRDE Talon Karrde FNALL1 @@ -1243,6 +1282,7 @@ OFAL019 + NARRA Narra FNALL1 @@ -1275,6 +1315,7 @@ OFAL020 + HUOBA_NEVA Huoba Neva FNALL1 @@ -1307,6 +1348,7 @@ OFAL021 + PAGE Page FNALL1 diff --git a/Assets/Resources/Data/PlanetSystems.xml b/Assets/Resources/Data/PlanetSystems.xml index e295070..03b0d6b 100644 --- a/Assets/Resources/Data/PlanetSystems.xml +++ b/Assets/Resources/Data/PlanetSystems.xml @@ -12,42 +12,52 @@ PLSEW01 + YAGA_MINOR Yaga Minor PLSEW02 + CHANDRILA Chandrila PLSEW03 + GHORMAN Ghorman PLSEW04 + AVARAM Averam PLSEW05 + CORUSCANT Coruscant PLSEW06 + BALMORRA Balmorra PLSEW07 + CORSIN Corsin PLSEW08 + UVENA Uvena PLSEW09 + SVIVREN Svivren PLSEW10 + YAGA_MAJOR Bortras @@ -61,42 +71,52 @@ PLCOR01 + XYQUINE Xyquine PLCOR02 + DRALL Drall PLCOR03 + TALUS Talus PLCOR04 + CORFAI Corfai PLCOR05 + COMMENOR Commenor PLCOR06 + SELONIA Selonia PLCOR07 + VAGRAN Vagran PLCOR08 + CORELLIA Corellia PLCOR09 + DUROS Duros PLCOR10 + TRALUS Tralus @@ -109,44 +129,54 @@ PSFAK - Delaya PLFAK01 + DELAYA + Delaya - Mrisst PLFAK02 + MRISST + Mrisst - Bimmisaari PLFAK03 + BIMMISAARI + Bimmisaari - Obroa-skai PLFAK04 + OBROA_SKAI + Obroa-skai - Carida PLFAK05 + CARIDA + Carida - Palanhi PLFAK06 + PALANHI + Palanhi - Ando PLFAK07 + ANDO + Ando - Berchest PLFAK08 + BERCHEST + Berchest - Halowan PLFAK09 + HALOWAN + Halowan - Ralltiir PLFAK10 + RALLTIIR + Ralltiir @@ -158,44 +188,54 @@ PLDOL - Sullust PLDOL01 + SULLUST + Sullust - Orto PLDOL02 + ORTO + Orto - Bpfassh PLDOL03 + BPFASSH + Bpfassh - Bothawui PLDOL04 + BOTHAWUI + Bothawui - Kothlis PLDOL05 + KOTHLIS + Kothlis - Mon Calamari PLDOL06 + MON_CALAMARI + Mon Calamari - Praesitlyn PLDOL07 + PRAESITLYN + Praesitlyn - Sluis Van PLDOL08 + SLUIS_VAN + Sluis Van + PLDOL09 + UMGUL Umgul - PLDOL08 - Denab PLDOL10 + DENAB + Denab @@ -207,44 +247,54 @@ PLFAR - Wistril PLFAR01 + WISTRIL + Wistril - Bilbringi PLFAR02 + BILBRINGI + Bilbringi - Byss PLFAR03 + BYSS + Byss - Khomm PLFAR04 + KHOMM + Khomm - Phraetiss PLFAR05 + PHRAETISS + Phraetiss - Kinyen PLFAR06 + KINYEN + Kinyen - Rishi PLFAR07 + RISHI + Rishi - Firro PLFAR08 + FIRRO + Firro - Taanab PLFAR09 + TAANAB + Taanab - Charmath PLFAR10 + CHARMATH + Charmath @@ -257,42 +307,52 @@ PLSLU01 + PHORLISS Phorliss PLSLU02 + KAMPARAS Kamparas PLSLU03 + KETARIS Ketaris PLSLU04 + BALFRON Balfron PLSLU05 + PANTOLOMIN Pantolomin PLSLU06 + TANGRENE Tangrene PLSLU07 + OMWAT Omwat PLSLU08 + WOR_TANDELL Wor Tandell PLSLU09 + SARKA Sarka PLSLU10 + CAPRIONRIL Caprionril @@ -308,44 +368,54 @@ PLATR - Zeffliffl PLATR01 + ZEFFLIFFL + Zeffliffl - Moltok PLATR02 + MOLTOK + Moltok - Togoria PLATR03 + TOGORIA + Togoria - Nam'ta PLATR04 + NAMTA + Nam'ta - Tibrin PLATR05 + TIBRIN + Tibrin - Despayre PLATR06 + DESPAYRE + Despayre - Spefik PLATR07 + SPEFIK + Spefik - Trammis PLATR08 + TRAMMIS + Trammis - Fedje PLATR09 + FEDJE + Fedje - Generis PLATR10 + GENERIS + Generis @@ -357,44 +427,54 @@ PLMOD - Adega PLMOD01 + ADEGA + Adega - Basilisk PLMOD02 + BASILISK + Basilisk - Annaj PLMOD03 + ANNAJ + Annaj - Khuiumin PLMOD04 + KHUIUMIN + Khuiumin - Pzob PLMOD05 + PZOB + Pzob - Gandolo IV PLMOD06 + GANDOLO_IV + Gandolo IV - Agrilat PLMOD07 + AGRILAT + Agrilat - Vjun PLMOD08 + VJUN + Vjun - Endor PLMOD09 + ENDOR + Endor - Hozrel XI PLMOD10 + HOZREL_XI + Hozrel XI @@ -406,44 +486,54 @@ PLQUE - Rafa PLQUE01 + RAFA + Rafa - Pil Diller PLQUE02 + PIL_DILLER + Pil Diller - Kirrek PLQUE03 + KIRREK + Kirrek - Varn PLQUE04 + VARN + Varn - Dathomir PLQUE05 + DATHOMIR + Dathomir - Thrakia PLQUE06 + THRAKIA + Thrakia - Vinsoth PLQUE07 + VINSOTH + Vinsoth - Amorris PLQUE08 + AMORRIS + Amorris - Corstris PLQUE09 + CORSTRIS + Corstris - Selaggis PLQUE10 + SELAGGIS + Selaggis @@ -455,45 +545,55 @@ PLCHU - Lelmra PLCHU01 + LELMRA + Lelmra - Gentes PLCHU02 + GENTES + Gentes - Allyuen PLCHU03 + ALLYUEN + Allyuen - Storthus PLCHU04 + STORTHUS + Storthus - Tokmia PLCHU05 + TOKMIA + Tokmia - Deyer PLCHU06 + DEYER + Deyer - Hoth PLCHU07 + HOTH + Hoth - Anoat PLCHU08 + ANOAT + Anoat - Bespin PLCHU09 + BESPIN + Bespin true - New Cov PLCHU10 + NEW_COV + New Cov @@ -505,44 +605,54 @@ PLKAN - Xa Fel PLKAN01 + XA_FEL + Xa Fel - Vodran PLKAN02 + VODRAN + Vodran - Munto Codru PLKAN03 + MUNTO_CODRU + Munto Codru - Davnar PLKAN04 + DAVNAR + Davnar - Derra IV PLKAN05 + DERRA_IV + Derra IV - Mindar PLKAN06 + MINDAR + Mindar - Culroon III PLKAN07 + CULROON_III + Culroon III - Spuma PLKAN08 + SPUMA + Spuma - Smarteel PLKAN09 + SMARTEEL + Smarteel - Nal Hutta PLKAN10 + NAL_HUTTA + Nal Hutta @@ -554,44 +664,54 @@ PLDUF - Zebitrope IV PLDUF01 + ZEBITROPE_IV + Zebitrope IV - Womrik PLDUF02 + WOMRIK + Womrik - Klatooine PLDUF03 + KLATOOINE + Klatooine - Ord Trasi PLDUF04 + ORD_TRASI + Ord Trasi - Algarian PLDUF05 + ALGARIAN + Algarian - Filve PLDUF06 + FILVE + Filve - Toprawa PLDUF07 + TOPRAWA + Toprawa - Ord Mantell PLDUF08 + ORD_MANTELL + Ord Mantell - Gamorr PLDUF09 + GAMORR + Gamorr - Ord Pardon PLDUF10 + ORD_PARDON + Ord Pardon @@ -603,44 +723,54 @@ PLABR - Hishyim PLABR01 + HISHYIM + Hishyim - Ukio PLABR02 + UKIO + Ukio - Hefi PLABR03 + HEFI + Hefi - Abregado PLABR04 + ABREGADO + Abregado - Da Soocha PLABR05 + DA_SOOCHA + Da Soocha - Tieos PLABR06 + TIEOS + Tieos - Cathar PLABR07 + CATHAR + Cathar - Galpos II PLABR08 + GALPOS_II + Galpos II - Garban PLABR09 + GARBAN + Garban - Intuci PLABR10 + INTUCI + Intuci @@ -652,44 +782,54 @@ PLXAP - Thanta Zilbra PLXAP01 + THANTA_ZILBRA + Thanta Zilbra - Norulac PLXAP02 + NORULAC + Norulac - Norulac PLXAP03 + NORULAC + Norulac - Ambria PLXAP04 + AMBRIA + Ambria - Stic PLXAP05 + STIC + Stic - Kirdo III PLXAP06 + KIRDO_III + Kirdo III - G'rho PLXAP07 + GRHO + G'rho - Ruuria PLXAP08 + RUURIA + Ruuria - Tund PLXAP09 + TUND + Tund - Neelgaimon PLXAP10 + NEELGAIMON + Neelgaimon @@ -701,44 +841,54 @@ PLORU - Lafra PLORU01 + LAFRA + Lafra - Tatooine PLORU02 + TATOOINE + Tatooine - Kimanan PLORU03 + KIMANAN + Kimanan - Chazwa PLORU04 + CHAZWA + Chazwa - Mantessa PLORU05 + MANTESSA + Mantessa - Bakura PLORU06 + BAKURA + Bakura - Joiol PLORU07 + JOIOL + Joiol - Daltar PLORU08 + DALTAR + Daltar - Ryloth PLORU09 + RYLOTH + Ryloth - Poderis PLORU10 + PODERIS + Poderis @@ -750,44 +900,54 @@ PLJOS - Chrondre PLJOS01 + CHRONDRE + Chrondre - Waskiro PLJOS02 + WASKIRO + Waskiro - Engira PLJOS03 + ENGIRA + Engira - Cardooine PLJOS04 + CARDOOINE + Cardooine - Dar'Or PLJOS05 + DAROR + Dar'Or - Jomark PLJOS06 + JOMARK + Jomark - Douglas III PLJOS07 + DOUGLAS_III + Douglas III - Kiffex PLJOS08 + KIFFEX + Kiffex - Trogan PLJOS09 + TROGAN + Trogan - Azbian PLJOS10 + AZBIAN + Azbian @@ -799,44 +959,54 @@ PLSUM - Tierfon PLSUM01 + TIERFON + Tierfon - Flax PLSUM02 + FLAX + Flax - Alk'lellish III PLSUM03 + ALKLELLISH_III + Alk'lellish III - Kashyyyk PLSUM04 + KASHYYYK + Kashyyyk - Geedon V PLSUM05 + GEEDON_V + Geedon V - Yavin PLSUM06 + YAVIN + Yavin + PLSUM07 + BOORDII Boordii - 07 - Linuri PLSUM08 + LINURI + Linuri + PLSUM09 + QAT_CHRYSTAC Qat Chrystac - 09 - Woostri PLSUM10 + WOOSTRI + Woostri @@ -848,44 +1018,54 @@ PLGLY - Nentan PLGLY01 + NENTAN + Nentan - Elrood PLGLY02 + ELROOD + Elrood - Yag'Dhul PLGLY03 + YAGDHUL + Yag'Dhul - Sedri PLGLY04 + SEDRI + Sedri - Vortex PLGLY05 + VORTEX + Vortex - Valrar PLGLY06 + VALRAR + Valrar - Fornax PLGLY07 + FORNAX + Fornax - Altarrn PLGLY08 + ALTARRN + Altarrn - Arkania PLGLY09 + ARKANIA + Arkania - Fef PLGLY10 + FEF + Fef @@ -897,93 +1077,55 @@ PLMAY - Kabal PLMAY01 + KABAL + Kabal - Triton PLMAY02 + TRITON + Triton - Clak'dor VII PLMAY03 + CLAKDOR_VII + Clak'dor VII - H'nemthe PLMAY04 + HNEMTHE + H'nemthe - Cona PLMAY05 + CONA + Cona - Urdur PLMAY06 + URDUR + Urdur - Oetrago PLMAY07 + OETRAGO + Oetrago - Chalcedon PLMAY08 + CHALCEDON + Chalcedon - Dantooine PLMAY09 + DANTOOINE + Dantooine - Anchoron PLMAY10 + ANCHORON + Anchoron - - Calaron - OuterRim - Small - Medium - - - Akrit'tar - PLCAL01 - - - Kessel - PLCAL02 - - - Norval II - PLCAL03 - - - Morvogodine - PLCAL04 - - - Ithor - PLCAL05 - - - Skor II - PLCAL06 - - - Fwillsving - PLCAL07 - - - Kubindi - PLCAL08 - - - Jerijador - PLCAL09 - - - F'tral - PLCAL10 - - - - \ No newline at end of file + diff --git a/Assets/Scripts/Conditionals/ConditionalFactory.cs b/Assets/Scripts/Conditionals/ConditionalFactory.cs new file mode 100644 index 0000000..65ae228 --- /dev/null +++ b/Assets/Scripts/Conditionals/ConditionalFactory.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using System.Linq; +using System; + +/// +/// +/// +/// @TODO: Add mechanism for to check parameters for validity before attempting to use them. +public static class ConditionalFactory +{ + /// + /// + /// + /// + /// + private delegate IConditional ConditionalCreator(Dictionary parameters); + + /// + /// + /// + private static readonly Dictionary conditionCreators = new Dictionary + { + { "IsOnSamePlanet", CreateAreOnSamePlanet }, + { "AreOnOpposingFactions", CreateAreOnOpposingFactions }, + }; + + /// + /// + /// + /// + /// + /// + /// + public static IConditional CreateConditional(string conditionType, Dictionary parameters) + { + if (conditionCreators.TryGetValue(conditionType, out var creator)) + { + return creator(parameters); + } + else + { + throw new ArgumentException($"Invalid condition type: {conditionType}"); + } + } + + /// + /// + /// + /// + /// + private static IConditional CreateAreOnSamePlanet(Dictionary parameters) + { + return new GenericConditional(AreOnSamePlanet, parameters); + } + + /// + /// + /// + /// + /// + private static IConditional CreateAreOnOpposingFactions(Dictionary parameters) + { + return new GenericConditional(AreOnOpposingFactions, parameters); + } + + /// + /// + /// + /// + /// + /// + private static bool AreOnSamePlanet(Game game, Dictionary parameters) + { + List instanceIDs = (List)parameters["InstanceIDs"]; + List sceneNodes = instanceIDs.Select(instanceId => game.GetSceneNodeByInstanceID(instanceId)).ToList(); + Planet comparator = null; + + foreach (SceneNode node in sceneNodes) + { + // If any of the nodes are null, return false. + if (node == null) + { + return false; + } + + // If the comparator is null, set it to the planet of the current node. + Planet planet = node.GetClosestParentOfType(); + comparator ??= planet; + + // If the planet of the current node is not the same as the comparator, return false. + if (comparator != planet) + { + return false; + } + } + + return true; + } + + /// + /// + /// + /// + /// + /// + private static bool AreOnOpposingFactions(Game game, Dictionary parameters) + { + var instanceIDs = (List)parameters["InstanceIDs"]; + var sceneNodes = instanceIDs + .Select(game.GetSceneNodeByInstanceID) + .Where(node => node != null) + .ToList(); + + return sceneNodes.Count == 2 && sceneNodes[0].OwnerGameID != sceneNodes[1].OwnerGameID; + } +} diff --git a/Assets/Scripts/Conditionals/GenericConditional.cs b/Assets/Scripts/Conditionals/GenericConditional.cs new file mode 100644 index 0000000..501b922 --- /dev/null +++ b/Assets/Scripts/Conditionals/GenericConditional.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +/// +/// +/// +public class GenericConditional : IConditional +{ + private readonly Func, bool> callback; + private Dictionary parameters; + + /// + /// + /// + /// + /// + public GenericConditional(Func, bool> callback, Dictionary parameters) + { + this.callback = callback; + this.parameters = parameters; + } + + /// + /// + /// + /// + /// + public bool IsMet(Game game) + { + return callback(game, parameters); + } +} diff --git a/Assets/Scripts/Events/ICondition.cs b/Assets/Scripts/Conditionals/IConditional.cs similarity index 93% rename from Assets/Scripts/Events/ICondition.cs rename to Assets/Scripts/Conditionals/IConditional.cs index a9b0293..cecf773 100644 --- a/Assets/Scripts/Events/ICondition.cs +++ b/Assets/Scripts/Conditionals/IConditional.cs @@ -1,7 +1,7 @@ /// /// Represents a condition that must be met for an event or action to proceed. /// -public interface ICondition +public interface IConditional { /// /// Evaluates the condition in the context of the provided game instance. diff --git a/Assets/Scripts/Core/GameEntity.cs b/Assets/Scripts/Core/GameEntity.cs index 72d03f2..599366c 100644 --- a/Assets/Scripts/Core/GameEntity.cs +++ b/Assets/Scripts/Core/GameEntity.cs @@ -1,39 +1,55 @@ -using System.Xml.Serialization; using System; +using System.Collections.Generic; +using System.Xml.Serialization; [Serializable] public class GameEntity { private string _instanceId; + private string _ownerGameID; - // Set the InstaceID property. - // This is a unique ID set for each node. + /// + /// InstanceID is a unique identifier for the object. If not set, it will be generated automatically. + /// Its primar + /// [CloneIgnore] public string InstanceID { - get - { - // Generate a new instance ID if it is not set. - if (_instanceId == null) - { - _instanceId = Guid.NewGuid().ToString().Replace("-", ""); - } - return _instanceId; - } - set - { - // Set the instance ID if it is not set. - if (_instanceId == null) - { - _instanceId = value; - } - } + get => _instanceId ??= Guid.NewGuid().ToString().Replace("-", ""); + set => _instanceId ??= value; } - // Set the GameID property. - // This is a non-unique ID set for each specific types of objects, such as planets, ships, etc. + + /// + /// GameID is a non-unique identifier for specific types of objects, such as starfighters, ships, regiments, etc. + /// + /// public string GameID { get; set; } - // Game Info + // Owner Info public string DisplayName { get; set; } public string Description { get; set; } -} \ No newline at end of file + [CloneIgnore] + public string OwnerGameID + { + get => _ownerGameID; + set => SetOwnerGameID(value); + } + public List AllowedOwnerGameIDs { get; set; } + + /// + /// Sets the owner game ID. If the ID is not in the allowed list, throws an exception. + /// + /// The owner game ID to set. + /// Thrown when the owner game ID is invalid. + private void SetOwnerGameID(string value) + { + if (AllowedOwnerGameIDs == null || AllowedOwnerGameIDs.Count == 0 || AllowedOwnerGameIDs.Contains(value)) + { + _ownerGameID = value; + } + else + { + throw new ArgumentException($"Invalid owner game ID: {value}"); + } + } +} diff --git a/Assets/Scripts/Core/LeafNode.cs b/Assets/Scripts/Core/LeafNode.cs index 5515cec..7dd795b 100644 --- a/Assets/Scripts/Core/LeafNode.cs +++ b/Assets/Scripts/Core/LeafNode.cs @@ -16,7 +16,7 @@ protected LeafNode() { } /// Adds a child to the node. For leaf nodes, this operation does nothing. /// /// The child node to add. - protected internal override void AddChild(SceneNode child) + public override void AddChild(SceneNode child) { // Do nothing (leaf nodes do not have children). } @@ -26,7 +26,7 @@ protected internal override void AddChild(SceneNode child) /// /// The child node to remove. - protected internal override void RemoveChild(SceneNode child) + public override void RemoveChild(SceneNode child) { // Do nothing (leaf nodes do not have children). } diff --git a/Assets/Scripts/Core/ReferenceNode.cs b/Assets/Scripts/Core/ReferenceNode.cs index 2710420..e2e6a0f 100644 --- a/Assets/Scripts/Core/ReferenceNode.cs +++ b/Assets/Scripts/Core/ReferenceNode.cs @@ -17,14 +17,14 @@ public class ReferenceNode public SceneNode Node { get; set; } /// - /// + /// Default constructor. /// public ReferenceNode() { } /// - /// + /// Initializes the reference node with a scene node, which is the object to be referenced. /// - /// + /// The scene node to reference. public ReferenceNode(SceneNode node) { Node = node; diff --git a/Assets/Scripts/Core/SceneNode.cs b/Assets/Scripts/Core/SceneNode.cs index ce0e88d..37de479 100644 --- a/Assets/Scripts/Core/SceneNode.cs +++ b/Assets/Scripts/Core/SceneNode.cs @@ -35,17 +35,35 @@ public SceneNode GetParent() return ParentNode; } + /// Gets the closest parent scene node of the specified type. + /// + /// The type of the parent scene node. + /// The closest parent scene node of the specified type. + public T GetClosestParentOfType() where T : SceneNode + { + SceneNode parent = ParentNode; + while (parent != null) + { + if (parent is T) + { + return (T)parent; + } + parent = parent.GetParent(); + } + return null; + } + /// /// /// /// - protected internal abstract void AddChild(SceneNode child); + public abstract void AddChild(SceneNode child); /// /// /// /// - protected internal abstract void RemoveChild(SceneNode child); + public abstract void RemoveChild(SceneNode child); /// /// Gets an enumerable collection of child scene nodes. diff --git a/Assets/Scripts/Events/GameEvent.cs b/Assets/Scripts/Events/GameEvent.cs index 8ada1b1..67ec273 100644 --- a/Assets/Scripts/Events/GameEvent.cs +++ b/Assets/Scripts/Events/GameEvent.cs @@ -20,7 +20,12 @@ public abstract class GameEvent : GameEntity public event Action OnEventTriggered; /// - /// Initializes a new instance of the class with the specified parameters. + /// Default constructor used for serialization. + /// + public GameEvent() { } + + /// + /// /// /// The tick at which the event is scheduled to occur. protected GameEvent(int scheduledTick) diff --git a/Assets/Scripts/Events/MissionEvent.cs b/Assets/Scripts/Events/MissionEvent.cs index b766c28..13c2800 100644 --- a/Assets/Scripts/Events/MissionEvent.cs +++ b/Assets/Scripts/Events/MissionEvent.cs @@ -6,7 +6,12 @@ public class MissionEvent : GameEvent public Mission Mission { get; private set; } /// - /// Initializes a new instance of the MissionEvent class. + /// Default constructor used for serialization. + /// + public MissionEvent() { } + + /// + /// Initializes a with the specified parameters. /// /// The tick at which the event is scheduled to occur. /// The mission that is being executed. diff --git a/Assets/Scripts/Events/NarrativeEvent.cs b/Assets/Scripts/Events/NarrativeEvent.cs new file mode 100644 index 0000000..1b6a2b4 --- /dev/null +++ b/Assets/Scripts/Events/NarrativeEvent.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System; + +public class NarrativeEvent : GameEvent +{ + public IConditional Conditionals { get; set; } + public SerializableDictionary> ConditionalParamsDictionary { get; set; } + /// + /// Default constructor used for serialization. + /// + public NarrativeEvent() { } + + /// + /// + /// + /// + /// + public NarrativeEvent(int scheduledTick, List conditionals) : base(scheduledTick) { } + + /// + /// + /// + /// + protected override void TriggerEvent(Game game) + { + // @TODO: Implement trigger. + } +} diff --git a/Assets/Scripts/Game/CapitalShip.cs b/Assets/Scripts/Game/CapitalShip.cs index f1a1ec6..d2ba493 100644 --- a/Assets/Scripts/Game/CapitalShip.cs +++ b/Assets/Scripts/Game/CapitalShip.cs @@ -60,9 +60,6 @@ public class CapitalShip : SceneNode, IManufacturable public int DetectionRating; // Owner Info - [CloneIgnore] - public string OwnerGameID { get; set; } - public string[] AllowedOwnerGameIDs; public string InitialParentGameID { get; set; } /// @@ -121,7 +118,7 @@ public void AddOfficer(Officer officer) /// /// The child to add /// Thrown when the child is not allowed to be added. - protected internal override void AddChild(SceneNode child) + public override void AddChild(SceneNode child) { if (child is Starfighter starfighter) { @@ -141,7 +138,7 @@ protected internal override void AddChild(SceneNode child) /// Adds a child to the capital ship. /// /// The child to remove - protected internal override void RemoveChild(SceneNode child) + public override void RemoveChild(SceneNode child) { if (child is Starfighter starfighter) { diff --git a/Assets/Scripts/Game/Fleet.cs b/Assets/Scripts/Game/Fleet.cs index 0f7ef4e..746d93b 100644 --- a/Assets/Scripts/Game/Fleet.cs +++ b/Assets/Scripts/Game/Fleet.cs @@ -6,11 +6,6 @@ public class Fleet : SceneNode { public List CapitalShips = new List(); - // Owner Info - [CloneIgnore] - public string OwnerGameID { get; set; } - public string[] AllowedOwnerGameIDs; - /// /// Default constructor. /// @@ -49,7 +44,7 @@ private void AddOfficer(Officer officer) /// /// The child node to add. /// Thrown when the child is not allowed to be added. - protected internal override void AddChild(SceneNode child) + public override void AddChild(SceneNode child) { if (child is CapitalShip) { @@ -65,7 +60,7 @@ protected internal override void AddChild(SceneNode child) /// Removes a child from the node. /// /// The child node to remove. - protected internal override void RemoveChild(SceneNode child) + public override void RemoveChild(SceneNode child) { if (child is CapitalShip capitalShip) { diff --git a/Assets/Scripts/Game/GalaxyMap.cs b/Assets/Scripts/Game/GalaxyMap.cs index ea18a50..5b1d253 100644 --- a/Assets/Scripts/Game/GalaxyMap.cs +++ b/Assets/Scripts/Game/GalaxyMap.cs @@ -19,7 +19,7 @@ public GalaxyMap() {} /// Adds a child to the node. /// /// The child node to add. - protected internal override void AddChild(SceneNode child) + public override void AddChild(SceneNode child) { if (child is PlanetSystem planetSystem) { @@ -31,7 +31,7 @@ protected internal override void AddChild(SceneNode child) /// Removes a child from the node. /// /// The child node to remove. - protected internal override void RemoveChild(SceneNode child) + public override void RemoveChild(SceneNode child) { if (child is PlanetSystem planetSystem) { diff --git a/Assets/Scripts/Game/Officer.cs b/Assets/Scripts/Game/Officer.cs index 0db71df..fadd966 100644 --- a/Assets/Scripts/Game/Officer.cs +++ b/Assets/Scripts/Game/Officer.cs @@ -51,9 +51,6 @@ public class Officer : MissionParticipant public OfficerRank CurrentRank; // Owner Info - [CloneIgnore] - public string OwnerGameID { get; set; } - public string[] AllowedOwnerGameIDs; public string InitialParentGameID; // Variance Info diff --git a/Assets/Scripts/Game/Planet.cs b/Assets/Scripts/Game/Planet.cs index 004d4da..ece8960 100644 --- a/Assets/Scripts/Game/Planet.cs +++ b/Assets/Scripts/Game/Planet.cs @@ -36,11 +36,6 @@ public class Planet : SceneNode { BuildingSlot.Orbit, new List() }, }; - // Owner Info - [CloneIgnore] - public string OwnerGameID { get; set; } - public string[] AllowedOwnerGameIDs; - /// /// Default constructor used for serialization. /// @@ -194,7 +189,7 @@ public Building[] GetBuildings(BuildingSlot slot) /// Adds a reference node to the game. /// /// The game node to add as a reference. - protected internal override void AddChild(SceneNode child) + public override void AddChild(SceneNode child) { if (child is Fleet fleet) { @@ -222,7 +217,7 @@ protected internal override void AddChild(SceneNode child) /// Removes a child node from the planet. /// /// The child node to remove. - protected internal override void RemoveChild(SceneNode child) + public override void RemoveChild(SceneNode child) { if (child is Fleet fleet) { diff --git a/Assets/Scripts/Game/PlanetSystem.cs b/Assets/Scripts/Game/PlanetSystem.cs index 5a06308..19872a2 100644 --- a/Assets/Scripts/Game/PlanetSystem.cs +++ b/Assets/Scripts/Game/PlanetSystem.cs @@ -45,7 +45,7 @@ public PlanetSystem() { } /// Adds a planet to the planet system. /// /// The planet to add. - protected internal override void AddChild(SceneNode child) + public override void AddChild(SceneNode child) { if (child is Planet planet) { @@ -57,7 +57,7 @@ protected internal override void AddChild(SceneNode child) /// Removes a planet from the planet system. /// /// The planet to remove. - protected internal override void RemoveChild(SceneNode child) + public override void RemoveChild(SceneNode child) { if (child is Planet planet) { diff --git a/Assets/Scripts/Game/Regiment.cs b/Assets/Scripts/Game/Regiment.cs index f838c08..6b1675c 100644 --- a/Assets/Scripts/Game/Regiment.cs +++ b/Assets/Scripts/Game/Regiment.cs @@ -18,10 +18,6 @@ public class Regiment : LeafNode, IManufacturable public int DetectionRating; public int BombardmentDefense; - // Owner Info - [CloneIgnore] - public string OwnerGameID { get; set; } - public string[] AllowedOwnerGameIDs; /// /// Default constructor used for serialization. diff --git a/Assets/Scripts/Game/SpecialForces.cs b/Assets/Scripts/Game/SpecialForces.cs index 8a81ee4..026e6aa 100644 --- a/Assets/Scripts/Game/SpecialForces.cs +++ b/Assets/Scripts/Game/SpecialForces.cs @@ -18,11 +18,6 @@ public class SpecialForces : MissionParticipant, IManufacturable public int Combat { get; set; } public int Leadership { get; set; } - // Owner Info - [CloneIgnore] - public string OwnerGameID { get; set; } - public string[] AllowedOwnerGameIDs; - /// /// Default constructor used for serialization. /// diff --git a/Assets/Scripts/Game/Starfighter.cs b/Assets/Scripts/Game/Starfighter.cs index f2be006..39c3227 100644 --- a/Assets/Scripts/Game/Starfighter.cs +++ b/Assets/Scripts/Game/Starfighter.cs @@ -33,11 +33,6 @@ public class Starfighter : LeafNode, IManufacturable public int IonRange; public int TorpedoRange; - // Owner Info - [CloneIgnore] - public string OwnerGameID { get; set; } - public string[] AllowedOwnerGameIDs; - /// /// Default constructor used for serialization. /// diff --git a/Assets/Scripts/Generation/OfficerGenerator.cs b/Assets/Scripts/Generation/OfficerGenerator.cs index 6ac808d..0295cfc 100644 --- a/Assets/Scripts/Generation/OfficerGenerator.cs +++ b/Assets/Scripts/Generation/OfficerGenerator.cs @@ -115,7 +115,7 @@ public override Officer[] SelectUnits(Officer[] units) .Insert(0, officer); // Add to front of list. } // Ignore officers allowed by both factions. - else if (officer.AllowedOwnerGameIDs.Length == 1) + else if (officer.AllowedOwnerGameIDs.Count == 1) { officersByFaction .GetOrAddValue(officer.AllowedOwnerGameIDs[0], new List()) diff --git a/Assets/Scripts/Managers/GameEventManager.cs b/Assets/Scripts/Managers/GameEventManager.cs index 63971bc..2fbc92c 100644 --- a/Assets/Scripts/Managers/GameEventManager.cs +++ b/Assets/Scripts/Managers/GameEventManager.cs @@ -4,11 +4,11 @@ /// /// Manages game events and their scheduling. /// -public class EventManager +public class GameEventManager { private readonly Game game; - public EventManager(Game game) + public GameEventManager(Game game) { this.game = game; } diff --git a/Assets/Scripts/Managers/GameManager.cs b/Assets/Scripts/Managers/GameManager.cs index 6d25f97..bdecac6 100644 --- a/Assets/Scripts/Managers/GameManager.cs +++ b/Assets/Scripts/Managers/GameManager.cs @@ -17,7 +17,7 @@ public enum TickSpeed public class GameManager { private Game currentGame; - public EventManager EventManager { get; private set; } + public GameEventManager EventManager { get; private set; } public MissionManager MissionManager { get; private set; } private float? tickInterval; private float tickTimer; @@ -29,7 +29,7 @@ public class GameManager public GameManager(Game game) { currentGame = game; - EventManager = new EventManager(game); + EventManager = new GameEventManager(game); MissionManager = new MissionManager(EventManager); } diff --git a/Assets/Scripts/Managers/MissionManager.cs b/Assets/Scripts/Managers/MissionManager.cs index 43de2d4..ade9508 100644 --- a/Assets/Scripts/Managers/MissionManager.cs +++ b/Assets/Scripts/Managers/MissionManager.cs @@ -8,27 +8,28 @@ /// public class MissionManager { - protected EventManager eventManager; + protected GameEventManager eventManager; /// - /// Initializes a new instance of the class. + /// /// /// The event manager. - public MissionManager(EventManager eventManager) + public MissionManager(GameEventManager eventManager) { this.eventManager = eventManager; - InitializeMissions(); + + // Initialize missions (i.e. register event handlers). + initializeMissions(); } /// - /// Starts a mission by generating a random tick for the mission and scheduling a mission event. + /// Initializes the missions by registering event handlers for mission events. /// - /// The mission to start. - private void InitializeMissions() + private void initializeMissions() { // Register event handlers for mission events. List missionEvents = eventManager - .GetEventsByType() + .GetEventsByType() .OfType() .ToList(); diff --git a/Assets/Scripts/Managers/NarrativeEventManager.cs b/Assets/Scripts/Managers/NarrativeEventManager.cs new file mode 100644 index 0000000..d1d444a --- /dev/null +++ b/Assets/Scripts/Managers/NarrativeEventManager.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Linq; +using System; + +/// +/// +/// +public class NarrativeEventManager +{ + private GameEventManager eventManager; + + public NarrativeEventManager(GameEventManager eventManager) + { + this.eventManager = eventManager; + + initializeNarrativeEvents(); + } + + /// + /// + /// + private void initializeNarrativeEvents() + { + // Get all narrative events + List narrativeEvents = eventManager + .GetEventsByType() + .OfType() + .ToList(); + + // Create conditionals for each narrative event + foreach(NarrativeEvent narrativeEvent in narrativeEvents) + { + List conditionals = narrativeEvent.ConditionalParamsDictionary.Keys + .Aggregate(new List(), (acc, key) => { + // + SerializableDictionary parameters = narrativeEvent.ConditionalParamsDictionary.TryGetValue(key, out parameters) ? parameters : null; + acc.Add(ConditionalFactory.CreateConditional(key, parameters)); + return acc; + }); + + } + + } +} diff --git a/Assets/Scripts/Missions/Mission.cs b/Assets/Scripts/Missions/Mission.cs index 6f1484a..bf6bd46 100644 --- a/Assets/Scripts/Missions/Mission.cs +++ b/Assets/Scripts/Missions/Mission.cs @@ -9,7 +9,6 @@ public abstract class Mission : SceneNode { public string Name; - public string OwnerGameID; public List MainParticipants = new List(); public List DecoyParticipants = new List(); public MissionParticipantSkill ParticipantSkill; @@ -302,7 +301,7 @@ public override IEnumerable GetChildren() /// /// No-op (missions cannot have children added). /// - protected internal override void AddChild(SceneNode child) + public override void AddChild(SceneNode child) { // No-op: Missions cannot have children added. } @@ -310,7 +309,7 @@ protected internal override void AddChild(SceneNode child) /// /// No-op (missions cannot have children removed). /// - protected internal override void RemoveChild(SceneNode child) + public override void RemoveChild(SceneNode child) { // No-op: Missions cannot have children removed. } diff --git a/Assets/Tests/EditMode/Core/GameEntityTests.cs b/Assets/Tests/EditMode/Core/GameEntityTests.cs index 5572287..d15fe78 100644 --- a/Assets/Tests/EditMode/Core/GameEntityTests.cs +++ b/Assets/Tests/EditMode/Core/GameEntityTests.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using System; +using System.Collections.Generic; [TestFixture] public class GameEntityTests @@ -9,6 +10,74 @@ public void TestInstanceIDCreated() { GameEntity entity = new GameEntity(); Assert.IsNotNull(entity.InstanceID, "InstanceID should not be null."); + + // Ensure the InstanceID is a valid GUID. Assert.IsTrue(Guid.TryParse(entity.InstanceID, out _), "InstanceID should be a valid GUID."); } -} + + [Test] + public void TestGameID() + { + GameEntity entity = new GameEntity(); + string gameID = "TestGameID"; + entity.GameID = gameID; + + // Ensure the GameID is set correctly. + Assert.AreEqual(gameID, entity.GameID, "GameID should be set correctly."); + } + + [Test] + public void TestDisplayName() + { + GameEntity entity = new GameEntity(); + string displayName = "TestDisplayName"; + entity.DisplayName = displayName; + + // Ensure the DisplayName is set correctly. + Assert.AreEqual(displayName, entity.DisplayName, "DisplayName should be set correctly."); + } + + [Test] + public void TestDescription() + { + GameEntity entity = new GameEntity(); + string description = "TestDescription"; + entity.Description = description; + + // Ensure the Description is set correctly. + Assert.AreEqual(description, entity.Description, "Description should be set correctly."); + } + + [Test] + public void TestOwnerGameID() + { + GameEntity entity = new GameEntity(); + string ownerGameID = "TestOwnerGameID"; + entity.AllowedOwnerGameIDs = new List { ownerGameID }; + entity.OwnerGameID = ownerGameID; + + // Ensure the OwnerGameID is set correctly. + Assert.AreEqual(ownerGameID, entity.OwnerGameID, "OwnerGameID should be set correctly."); + } + + [Test] + public void TestInvalidOwnerGameID() + { + GameEntity entity = new GameEntity(); + entity.AllowedOwnerGameIDs = new List { "ValidOwnerGameID" }; + + // Ensure an invalid OwnerGameID throws an exception. + Assert.Throws(() => entity.OwnerGameID = "InvalidOwnerGameID", "Setting an invalid OwnerGameID should throw an ArgumentException."); + } + + [Test] + public void TestAllowedOwnerGameIDs() + { + GameEntity entity = new GameEntity(); + var allowedOwnerGameIDs = new List { "Owner1", "Owner2" }; + entity.AllowedOwnerGameIDs = allowedOwnerGameIDs; + + // Ensure the AllowedOwnerGameIDs is set correctly. + Assert.AreEqual(allowedOwnerGameIDs, entity.AllowedOwnerGameIDs, "AllowedOwnerGameIDs should be set correctly."); + } +} \ No newline at end of file diff --git a/Assets/Tests/EditMode/Core/SceneNodeTests.cs b/Assets/Tests/EditMode/Core/SceneNodeTests.cs new file mode 100644 index 0000000..c49e0a4 --- /dev/null +++ b/Assets/Tests/EditMode/Core/SceneNodeTests.cs @@ -0,0 +1,154 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; + +// Dummy concrete class to test SceneNode. +class TestSceneNode : SceneNode +{ + private List children = new List(); + + public override void AddChild(SceneNode child) + { + children.Add(child); + } + + public override void RemoveChild(SceneNode child) + { + children.Remove(child); + } + + public override IEnumerable GetChildren() + { + return children; + } +} + +// Another concrete class to test different types of SceneNode. +class SpecialSceneNode : SceneNode +{ + private List children = new List(); + + public override void AddChild(SceneNode child) + { + children.Add(child); + } + + public override void RemoveChild(SceneNode child) + { + children.Remove(child); + } + + public override IEnumerable GetChildren() + { + return children; + } +} + +[TestFixture] +public class SceneNodeTests +{ + [Test] + public void TestSetParent() + { + // Create parent and child nodes + SceneNode parent = new TestSceneNode(); + SceneNode child = new TestSceneNode(); + + // Set parent node + child.SetParent(parent); + + // Validate that the parent is set correctly + Assert.AreEqual(parent, child.GetParent(), "Parent should be set correctly."); + Assert.AreEqual(parent.GameID, child.ParentGameID, "ParentGameID should match the parent's GameID."); + } + + [Test] + public void TestGetParent() + { + // Create parent and child nodes + SceneNode parent = new TestSceneNode(); + SceneNode child = new TestSceneNode(); + + // Set parent node + child.SetParent(parent); + + // Validate that the parent is retrieved correctly + Assert.AreEqual(parent, child.GetParent(), "GetParent should return the correct parent."); + } + + [Test] + public void TestGetClosestParentOfType() + { + // Create hierarchy: specialNode -> parentNode -> childNode + SceneNode specialNode = new SpecialSceneNode(); + SceneNode parentNode = new TestSceneNode(); + SceneNode childNode = new TestSceneNode(); + + // Set up the hierarchy + parentNode.SetParent(specialNode); + childNode.SetParent(parentNode); + + // Get the closest parent of the specified type (SpecialSceneNode) + var closestSpecialNode = childNode.GetClosestParentOfType(); + + // Validate that the closest parent is the specialNode + Assert.AreEqual(specialNode, closestSpecialNode, "GetClosestParentOfType should return specialNode."); + + // Now test finding TestSceneNode as the closest parent of the child node + var closestTestNode = childNode.GetClosestParentOfType(); + Assert.AreEqual(parentNode, closestTestNode, "GetClosestParentOfType should return parentNode."); + } + + [Test] + public void TestAddChild() + { + // Create parent and child nodes + SceneNode parent = new TestSceneNode(); + SceneNode child = new TestSceneNode(); + + // Add child to the parent node + parent.AddChild(child); + + // Validate that the child is added correctly + CollectionAssert.Contains(parent.GetChildren(), child, "Child should be added to the parent node."); + } + + [Test] + public void TestRemoveChild() + { + // Create parent and child nodes + SceneNode parent = new TestSceneNode(); + SceneNode child = new TestSceneNode(); + + // Add and then remove child from the parent node + parent.AddChild(child); + parent.RemoveChild(child); + + // Validate that the child is removed correctly + CollectionAssert.DoesNotContain(parent.GetChildren(), child, "Child should be removed from the parent node."); + } + + [Test] + public void TestTraverse() + { + // Create root, child1, and child2 nodes + SceneNode root = new TestSceneNode(); + SceneNode child1 = new TestSceneNode(); + SceneNode child2 = new TestSceneNode(); + + // Set up the hierarchy + root.AddChild(child1); + root.AddChild(child2); + + // List to track visited nodes during traversal + var visitedNodes = new List(); + + // Traverse the scene graph + root.Traverse(node => visitedNodes.Add(node)); + + // Validate that all nodes are visited + Assert.Contains(root, visitedNodes, "Traverse should visit the root node."); + Assert.Contains(child1, visitedNodes, "Traverse should visit child1."); + Assert.Contains(child2, visitedNodes, "Traverse should visit child2."); + } +} diff --git a/Assets/Tests/EditMode/Game/PlanetTests.cs b/Assets/Tests/EditMode/Game/PlanetTests.cs index 779259e..ca53a79 100644 --- a/Assets/Tests/EditMode/Game/PlanetTests.cs +++ b/Assets/Tests/EditMode/Game/PlanetTests.cs @@ -28,7 +28,6 @@ public void Setup() PlayerFactionID = "FNALL1", }; - // Save the file to disk for testing. game = new Game { Summary = summary, @@ -37,77 +36,123 @@ public void Setup() } [Test] - public void TestAddFleet() + public void TestAddOfficer() { - Fleet fleet = new Fleet { OwnerGameID = "FNALL1" }; - game.AttachNode(planet, fleet); + Officer officer = new Officer { OwnerGameID = "FNALL1" }; + game.AttachNode(planet, officer); - Assert.Contains(fleet, planet.Fleets); + Assert.Contains(officer, planet.Officers, "Officer should be added to the planet."); } [Test] - public void TestAddOfficer() + public void TestRemoveOfficer() { Officer officer = new Officer { OwnerGameID = "FNALL1" }; game.AttachNode(planet, officer); + game.DetachNode(officer); - Assert.Contains(officer, planet.Officers); + Assert.IsFalse(planet.Officers.Contains(officer), "Officer should be removed from the planet."); } [Test] - public void TestAddBuilding() + public void TestAddSpecialForces() { - Building building = new Building { Slot = BuildingSlot.Ground, DisplayName = "Test Building" }; - game.AttachNode(planet, building); - Building[] buildings = planet.GetBuildings(BuildingSlot.Ground); + SpecialForces specialForces = new SpecialForces { OwnerGameID = "FNALL1" }; + game.AttachNode(planet, specialForces); - Assert.Contains(building, buildings); + Assert.Contains(specialForces, planet.Regiments, "Special Forces should be added to the planet."); } [Test] - public void TestRemoveFleet() + public void TestRemoveSpecialForces() { - Fleet fleet = new Fleet { OwnerGameID = "FNALL1" }; - game.AttachNode(planet, fleet); - game.DetachNode(fleet); + SpecialForces specialForces = new SpecialForces { OwnerGameID = "FNALL1" }; + game.AttachNode(planet, specialForces); + game.DetachNode(specialForces); - Assert.IsFalse(planet.Fleets.Contains(fleet)); + Assert.IsFalse(planet.Regiments.Contains(specialForces), "Special Forces should be removed from the planet."); } [Test] - public void TestRemoveOfficer() + public void TestAddStarfighter() { - Officer officer = new Officer { OwnerGameID = "FNALL1" }; - game.AttachNode(planet, officer); - game.DetachNode(officer); + Starfighter starfighter = new Starfighter { SquadronSize = 12 }; + game.AttachNode(planet, starfighter); - Assert.IsFalse(planet.Officers.Contains(officer)); + Assert.Contains(starfighter, planet.GetChildren().OfType().ToList(), "Starfighter should be added to the planet."); } [Test] - public void TestRemoveBuilding() + public void TestRemoveStarfighter() { - Building building = new Building { Slot = BuildingSlot.Ground, DisplayName = "Test Building" }; - game.AttachNode(planet, building); - game.DetachNode(building); + Starfighter starfighter = new Starfighter { SquadronSize = 12 }; + game.AttachNode(planet, starfighter); + game.DetachNode(starfighter); - Assert.IsFalse(planet.Buildings[BuildingSlot.Ground].Contains(building)); + Assert.IsFalse(planet.GetChildren().OfType().Contains(starfighter), "Starfighter should be removed from the planet."); } [Test] - public void TestGetChildren() + public void TestAddMultipleChildNodes() { - Fleet fleet = new Fleet { OwnerGameID = "FNALL1" }; Officer officer = new Officer { OwnerGameID = "FNALL1" }; - Building building = new Building { Slot = BuildingSlot.Ground, DisplayName = "Test Building" }; + SpecialForces specialForces = new SpecialForces { OwnerGameID = "FNALL1" }; + Starfighter starfighter = new Starfighter { SquadronSize = 12 }; - game.AttachNode(planet, fleet); game.AttachNode(planet, officer); - game.AttachNode(planet, building); + game.AttachNode(planet, specialForces); + game.AttachNode(planet, starfighter); IEnumerable children = planet.GetChildren(); - List expectedChildren = new List { fleet, officer, building }; + List expectedChildren = new List { officer, specialForces, starfighter }; + + CollectionAssert.AreEquivalent(expectedChildren, children, "All child nodes should be added to the planet."); + } + + [Test] + public void TestRemoveMultipleChildNodes() + { + Officer officer = new Officer { OwnerGameID = "FNALL1" }; + SpecialForces specialForces = new SpecialForces { OwnerGameID = "FNALL1" }; + Starfighter starfighter = new Starfighter { SquadronSize = 12 }; + + game.AttachNode(planet, officer); + game.AttachNode(planet, specialForces); + game.AttachNode(planet, starfighter); + + game.DetachNode(officer); + game.DetachNode(specialForces); + game.DetachNode(starfighter); + + Assert.IsFalse(planet.GetChildren().Contains(officer), "Officer should be removed from the planet."); + Assert.IsFalse(planet.GetChildren().Contains(specialForces), "Special Forces should be removed from the planet."); + Assert.IsFalse(planet.GetChildren().Contains(starfighter), "Starfighter should be removed from the planet."); + } + + [Test] + public void TestSerializeAndDeserialize() + { + // Create a planet object to serialize + Planet originalPlanet = new Planet + { + DisplayName = "Test Planet", + IsColonized = true, + GroundSlots = 5, + OrbitSlots = 3, + OwnerGameID = "FNALL1" + }; + + // Serialize the planet + string serializedPlanet = SerializationHelper.Serialize(originalPlanet); + + // Deserialize the planet + Planet deserializedPlanet = SerializationHelper.Deserialize(serializedPlanet); - CollectionAssert.AreEquivalent(expectedChildren, children); + // Verify that the deserialized object matches the original + Assert.AreEqual(originalPlanet.DisplayName, deserializedPlanet.DisplayName, "Planet DisplayName should match after deserialization."); + Assert.AreEqual(originalPlanet.IsColonized, deserializedPlanet.IsColonized, "Planet IsColonized should match after deserialization."); + Assert.AreEqual(originalPlanet.GroundSlots, deserializedPlanet.GroundSlots, "Planet GroundSlots should match after deserialization."); + Assert.AreEqual(originalPlanet.OrbitSlots, deserializedPlanet.OrbitSlots, "Planet OrbitSlots should match after deserialization."); + Assert.AreEqual(originalPlanet.OwnerGameID, deserializedPlanet.OwnerGameID, "Planet OwnerGameID should match after deserialization."); } } diff --git a/Assets/Tests/EditMode/Managers/GameManagerTests.cs b/Assets/Tests/EditMode/Managers/GameManagerTests.cs index 9fd9d12..487deca 100644 --- a/Assets/Tests/EditMode/Managers/GameManagerTests.cs +++ b/Assets/Tests/EditMode/Managers/GameManagerTests.cs @@ -1,5 +1,4 @@ using NUnit.Framework; -using UnityEngine.TestTools; using System.Collections; // Mock GameEvent for testing @@ -55,12 +54,12 @@ public void TestEventExecutesAtScheduledTick() // Simulate 4 ticks (the event should not trigger yet) for (int i = 0; i < 4; i++) { - gameManager.Update(1f); // Simulate 1 second of game time (1 tick) + gameManager.Update(1f); // Simulate 1 second of game time (1 tick) Assert.IsFalse(mockEvent.WasExecuted, "Event should not have been executed yet."); } // Simulate 1 more tick (the 5th tick, where the event is scheduled) - gameManager.Update(1f); // Simulate 1 second of game time (1 tick) + gameManager.Update(1f); // Simulate 1 second of game time (1 tick) Assert.IsTrue(mockEvent.WasExecuted, "Event should have been executed at tick 5."); } diff --git a/Assets/Tests/EditMode/Managers/SaveGameManagerTests.cs b/Assets/Tests/EditMode/Managers/SaveGameManagerTests.cs index bb15b09..41804a0 100644 --- a/Assets/Tests/EditMode/Managers/SaveGameManagerTests.cs +++ b/Assets/Tests/EditMode/Managers/SaveGameManagerTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using UnityEngine; -using UnityEngine.TestTools; [TestFixture] public class SaveGameManagerTests diff --git a/Assets/Tests/EditMode/Missions/MissionTests.cs b/Assets/Tests/EditMode/Missions/MissionTests.cs index 940d61e..7a56cd9 100644 --- a/Assets/Tests/EditMode/Missions/MissionTests.cs +++ b/Assets/Tests/EditMode/Missions/MissionTests.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; // Concrete class for testing abstract Mission -public class MockMission : Mission +class MockMission : Mission { public bool WasSuccessful { get; private set; }