diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f7ee5dd4..e2c07f8d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,14 +71,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - New `GameActivity` INI properties `TeamNTechSwitchEnabled` which determine whether activity team factions are configurable by the user. This is most useful for communicating what the player is not intended to change, or what inputs would be ignored otherwise. -- Allow lua scripts to use LuaJIT's BitOp module (see https://bitop.luajit.org/api.html) - - New `Emission` INI and Lua (R/W) property `ParticleCount` which sets how many particles the Emission spawns per emission. Defaults to 1. - New `Gib` and `Emission` INI and Lua (R/W) property `InheritsAngularVel`, which determines how much of the parent MO's angular velocity they inherit. Defaults to 1 for gibs, 0 for emissions. - New `Attachable` INI and Lua (R/W) properties `InheritsVelWhenDetached` and `InheritsAngularVelWhenDetached`, which determine how much of these velocities an attachable inherits from its parent when detached. Defaults to 1. +- New `ModuleMan` to handle module management, and allow global scripts and mod modules can now be dynamically enabled or disabled mid-game. + Moved the `PresetMan` lua parameters/functions `Modules`, `GetDataModule`, `GetModuleID`, `GetModuleIDFromPath`, `GetTotalModuleCount`, `IsModuleOfficial`, `IsModuleUserdata` and `GetFullModulePath` into `ModuleMan` + +- Allow lua scripts to use LuaJIT's BitOp module (see https://bitop.luajit.org/api.html) +
Changed diff --git a/Data/Base.rte/Activities/BrainVsBrain.lua b/Data/Base.rte/Activities/BrainVsBrain.lua index bed8f531f..e465787f9 100644 --- a/Data/Base.rte/Activities/BrainVsBrain.lua +++ b/Data/Base.rte/Activities/BrainVsBrain.lua @@ -40,7 +40,7 @@ function BrainvsBrain:StartActivity(isNewGame) self.TechName[Activity.TEAM_2] = self:GetTeamTech(Activity.TEAM_2); if self.CPUTeam ~= Activity.NOTEAM then - self.CPUTechID = PresetMan:GetModuleID(self.TechName[self.CPUTeam]); + self.CPUTechID = ModuleMan:GetModuleID(self.TechName[self.CPUTeam]); end MusicMan:PlayDynamicSong("Generic Battle Music"); @@ -577,7 +577,7 @@ function BrainvsBrain:CreateHeavyDrop(xPosLZ) Craft.Pos = Vector(xPosLZ, -30); -- Set the spawn point of the craft for i = 1, Craft.MaxPassengers do - if math.random() < self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.TechName[self.CPUTeam])) then + if math.random() < self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.TechName[self.CPUTeam])) then Passenger = self:CreateCrab(self.CPUTeam); elseif RangeRand(0, 105) < self.Difficulty then Passenger = self:CreateHeavyInfantry(self.CPUTeam); @@ -862,7 +862,7 @@ end function BrainvsBrain:CreateLightInfantry(team, mode) local Passenger = RandomAHuman("Actors - Light", self.TechName[team]); - if Passenger.ModuleID ~= PresetMan:GetModuleID(self.TechName[team]) then + if Passenger.ModuleID ~= ModuleMan:GetModuleID(self.TechName[team]) then Passenger = RandomAHuman("Actors", self.TechName[team]); end @@ -887,7 +887,7 @@ end function BrainvsBrain:CreateDefender(team) local Passenger = RandomAHuman("Actors - Light", self.TechName[team]); - if Passenger.ModuleID ~= PresetMan:GetModuleID(self.TechName[team]) then + if Passenger.ModuleID ~= ModuleMan:GetModuleID(self.TechName[team]) then Passenger = RandomAHuman("Actors", self.TechName[team]); end @@ -907,7 +907,7 @@ end function BrainvsBrain:CreateHeavyInfantry(team, mode) local Passenger = RandomAHuman("Actors - Heavy", self.TechName[team]); - if Passenger.ModuleID ~= PresetMan:GetModuleID(self.TechName[team]) then + if Passenger.ModuleID ~= ModuleMan:GetModuleID(self.TechName[team]) then Passenger = RandomAHuman("Actors", self.TechName[team]); end @@ -939,7 +939,7 @@ end function BrainvsBrain:CreateMediumInfantry(team, mode) local Passenger = RandomAHuman("Actors - Heavy", self.TechName[team]); - if Passenger.ModuleID ~= PresetMan:GetModuleID(self.TechName[team]) then + if Passenger.ModuleID ~= ModuleMan:GetModuleID(self.TechName[team]) then Passenger = RandomAHuman("Actors", self.TechName[team]); end @@ -964,7 +964,7 @@ end function BrainvsBrain:CreateScoutInfantry(team, mode) local Passenger = RandomAHuman("Actors - Light", self.TechName[team]); - if Passenger.ModuleID ~= PresetMan:GetModuleID(self.TechName[team]) then + if Passenger.ModuleID ~= ModuleMan:GetModuleID(self.TechName[team]) then Passenger = RandomAHuman("Actors", self.TechName[team]); end @@ -989,7 +989,7 @@ end function BrainvsBrain:CreateEngineer(team, mode) local Passenger = RandomAHuman("Actors - Light", self.TechName[team]); - if Passenger.ModuleID ~= PresetMan:GetModuleID(self.TechName[team]) then + if Passenger.ModuleID ~= ModuleMan:GetModuleID(self.TechName[team]) then Passenger = RandomAHuman("Actors", self.TechName[team]); end diff --git a/Data/Base.rte/Activities/BunkerBreach.lua b/Data/Base.rte/Activities/BunkerBreach.lua index 7176670b2..83b6c48c4 100644 --- a/Data/Base.rte/Activities/BunkerBreach.lua +++ b/Data/Base.rte/Activities/BunkerBreach.lua @@ -138,7 +138,7 @@ function BunkerBreach:SetupDefenderBrains() end function BunkerBreach:SetupDefenderActors() - local techID = PresetMan:GetModuleID(self:GetTeamTech(self.defenderTeam)); + local techID = ModuleMan:GetModuleID(self:GetTeamTech(self.defenderTeam)); local crabToHumanSpawnRatio = self:GetCrabToHumanSpawnRatio(techID); local loadoutNames = {"Light", "Heavy", "Sniper", "Engineer", "Mecha", "Turret"}; @@ -654,7 +654,7 @@ function BunkerBreach:CreateInternalReinforcements(loadout, numberOfReinforcemen loadout = nil; end local team = self.CPUTeam; - local techID = PresetMan:GetModuleID(self:GetTeamTech(team)); + local techID = ModuleMan:GetModuleID(self:GetTeamTech(team)); local crabToHumanSpawnRatio = self:GetCrabToHumanSpawnRatio(techID); local internalReinforcementPositionsToEnemyTargets = self:CalculateInternalReinforcementPositionsToEnemyTargets(numberOfReinforcementsToCreate); @@ -675,7 +675,7 @@ function BunkerBreach:CreateInternalReinforcements(loadout, numberOfReinforcemen numberOfInternalReinforcementsToCreateAtPosition = 3; end end - + for i = 1, numberOfInternalReinforcementsToCreateAtPosition do local internalReinforcement; if loadout then @@ -716,7 +716,7 @@ function BunkerBreach:CreateDrop(loadout, aiMode, passengerCount, avoidPreviousC loadout = nil; end local team = self.CPUTeam; - local techID = PresetMan:GetModuleID(self:GetTeamTech(team)); + local techID = ModuleMan:GetModuleID(self:GetTeamTech(team)); local crabToHumanSpawnRatio = self:GetCrabToHumanSpawnRatio(techID); local craft = RandomACDropShip("Craft", techID); @@ -881,7 +881,7 @@ function BunkerBreach:CreateCrab(techID, createTurret) end function BunkerBreach:CreateBrainBot(team, techID) - local techID = PresetMan:GetModuleID(self:GetTeamTech(team)); + local techID = ModuleMan:GetModuleID(self:GetTeamTech(team)); local actor; if techID ~= -1 and team == self.attackerTeam then actor = PresetMan:GetLoadout("Infantry Brain", techID, false); diff --git a/Data/Base.rte/Activities/Harvester.lua b/Data/Base.rte/Activities/Harvester.lua index dbd919046..6eb3fc6b0 100644 --- a/Data/Base.rte/Activities/Harvester.lua +++ b/Data/Base.rte/Activities/Harvester.lua @@ -280,7 +280,7 @@ function Harvester:UpdateActivity() for i = 1, actorsInCargo do -- Get any Actor from the CPU's native tech local passenger = nil; - if math.random() >= self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.CPUTechName)) then + if math.random() >= self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.CPUTechName)) then passenger = RandomAHuman("Any", self.CPUTechName); else passenger = RandomACrab("Actors - Mecha", self.CPUTechName); diff --git a/Data/Base.rte/Activities/KeepieUppie.lua b/Data/Base.rte/Activities/KeepieUppie.lua index d9431ac23..01994db35 100644 --- a/Data/Base.rte/Activities/KeepieUppie.lua +++ b/Data/Base.rte/Activities/KeepieUppie.lua @@ -130,7 +130,7 @@ function KeepieUppie:ResumeLoadedGame() end end end - + if not self.playerRocketSpawned then for player = Activity.PLAYER_1, Activity.MAXPLAYERCOUNT - 1 do if self:PlayerActive(player) and self:PlayerHuman(player) then @@ -228,7 +228,7 @@ function KeepieUppie:UpdateActivity() for i = 1, actorsInCargo do -- Get any Actor from the CPU's native tech local passenger = nil; - if math.random() >= self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.CPUTechName)) then + if math.random() >= self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.CPUTechName)) then passenger = RandomAHuman("Any", self.CPUTechName); else passenger = RandomACrab("Any", self.CPUTechName); diff --git a/Data/Base.rte/Activities/Massacre.lua b/Data/Base.rte/Activities/Massacre.lua index aabd13247..5fff1dff5 100644 --- a/Data/Base.rte/Activities/Massacre.lua +++ b/Data/Base.rte/Activities/Massacre.lua @@ -276,7 +276,7 @@ function Massacre:UpdateActivity() for i = 1, actorsInCargo do -- Get any Actor from the CPU's native tech local passenger = nil; - if math.random() >= self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.CPUTechName)) then + if math.random() >= self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.CPUTechName)) then passenger = RandomAHuman("Any", self.CPUTechName); else passenger = RandomACrab("Actors - Mecha", self.CPUTechName); diff --git a/Data/Base.rte/Activities/OneManArmy.lua b/Data/Base.rte/Activities/OneManArmy.lua index 5fe759fad..69889111a 100644 --- a/Data/Base.rte/Activities/OneManArmy.lua +++ b/Data/Base.rte/Activities/OneManArmy.lua @@ -132,11 +132,11 @@ function OneManArmy:SetupHumanPlayerBrains(actorGroup, primaryGroup, secondaryGr --If we can't find an unassigned brain in the scene to give the player, create one if not foundBrain then - local tech = PresetMan:GetModuleID(self:GetTeamTech(team)); + local tech = ModuleMan:GetModuleID(self:GetTeamTech(team)); foundBrain = CreateAHuman(defaultActor); --If a faction was chosen, pick the first item from faction listing if tech ~= -1 then - local module = PresetMan:GetDataModule(tech); + local module = ModuleMan:GetDataModule(tech); local primaryWeapon, secondaryWeapon, throwable, actor; for entity in module.Presets do local picked; --Prevent duplicates @@ -357,9 +357,9 @@ function OneManArmy:UpdateActivity() for i = 1, actorsInCargo do --Get any Actor from the CPU's native tech local passenger = nil; - if math.random() >= self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.CPUTechName)) then + if math.random() >= self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.CPUTechName)) then passenger = RandomAHuman("Actors - Light", self.CPUTechName); - if passenger.ModuleID ~= PresetMan:GetModuleID(self.CPUTechName) then + if passenger.ModuleID ~= ModuleMan:GetModuleID(self.CPUTechName) then passenger = RandomAHuman("Actors", self.CPUTechName); end else diff --git a/Data/Base.rte/Activities/OneManArmyDiggers.lua b/Data/Base.rte/Activities/OneManArmyDiggers.lua index e826c4a0a..66843c012 100644 --- a/Data/Base.rte/Activities/OneManArmyDiggers.lua +++ b/Data/Base.rte/Activities/OneManArmyDiggers.lua @@ -133,11 +133,11 @@ function OneManArmy:SetupHumanPlayerBrains(actorGroup, primaryGroup, secondaryGr local foundBrain = MovableMan:GetUnassignedBrain(team); -- If we can't find an unassigned brain in the scene to give the player, create one if not foundBrain then - local tech = PresetMan:GetModuleID(self:GetTeamTech(team)); + local tech = ModuleMan:GetModuleID(self:GetTeamTech(team)); foundBrain = CreateAHuman(defaultActor); -- If a faction was chosen, pick the first item from faction listing if tech ~= -1 then - local module = PresetMan:GetDataModule(tech); + local module = ModuleMan:GetDataModule(tech); local primaryWeapon, secondaryWeapon, throwable, actor; for entity in module.Presets do local picked; -- Prevent duplicates @@ -308,7 +308,7 @@ function OneManArmy:UpdateActivity() -- Set the ship up with a cargo of a few armed and equipped actors for i = 1, actorsInCargo do local passenger = RandomAHuman("Actors - " .. ((self.Difficulty > 75 and math.random() > 0.5) and "Heavy" or "Light"), self.CPUTechName); - if passenger.ModuleID ~= PresetMan:GetModuleID(self.CPUTechName) then + if passenger.ModuleID ~= ModuleMan:GetModuleID(self.CPUTechName) then passenger = RandomAHuman("Actors", self.CPUTechName); end diff --git a/Data/Base.rte/Activities/OneManArmyZeroG.lua b/Data/Base.rte/Activities/OneManArmyZeroG.lua index 1073123ea..6d1dc6828 100644 --- a/Data/Base.rte/Activities/OneManArmyZeroG.lua +++ b/Data/Base.rte/Activities/OneManArmyZeroG.lua @@ -8,7 +8,7 @@ function OneManArmyZeroG:StartActivity(isNewGame) self.winTimer = Timer(); self.CPUTechName = self:GetTeamTech(self.CPUTeam); - + self.isDiggersOnly = self.PresetName:find("Diggers") ~= nil; if isNewGame then @@ -87,7 +87,7 @@ function OneManArmyZeroG:StartNewGame() self.enemySpawnTimeLimit = 500; MusicMan:PlayDynamicSong("Generic Battle Music"); - + local automoverController = CreateActor("Invisible Automover Controller", "Base.rte"); automoverController.Team = -1; automoverController:SetNumberValue("MovementSpeed", 16); @@ -123,11 +123,11 @@ function OneManArmyZeroG:SetupHumanPlayerBrains(actorGroup, primaryGroup, second --If we can't find an unassigned brain in the scene to give the player, create one if not foundBrain then - local tech = PresetMan:GetModuleID(self:GetTeamTech(team)); + local tech = ModuleMan:GetModuleID(self:GetTeamTech(team)); foundBrain = CreateAHuman(defaultActor); --If a faction was chosen, pick the first item from faction listing if tech ~= -1 then - local dataModule = PresetMan:GetDataModule(tech); + local dataModule = ModuleMan:GetDataModule(tech); local primaryWeapon, secondaryWeapon, tertiaryWeapon, actor; for entity in dataModule.Presets do local picked; --Prevent duplicates @@ -250,14 +250,14 @@ function OneManArmyZeroG:ResumeLoadedGame() end end end - + for particle in MovableMan.AddedParticles do if particle.PresetName == "Automover Node 1x1" then particle.Scale = 0; break; end end - + for actor in MovableMan.AddedActors do if actor.Team ~= Activity.TEAM_1 then actor.AIMode = Actor.AIMODE_BRAINHUNT; @@ -342,7 +342,7 @@ function OneManArmyZeroG:UpdateActivity() if self.CPUTeam ~= Activity.NOTEAM and self.enemySpawnTimer:LeftTillSimMS(self.enemySpawnTimeLimit) <= 0 then for i = 1, math.random(1, 3) do local actor = RandomAHuman("Actors - Light", self.CPUTechName); - if actor.ModuleID ~= PresetMan:GetModuleID(self.CPUTechName) then + if actor.ModuleID ~= ModuleMan:GetModuleID(self.CPUTechName) then actor = RandomAHuman("Actors", self.CPUTechName); end diff --git a/Data/Base.rte/Activities/Siege.lua b/Data/Base.rte/Activities/Siege.lua index d741cab8f..04d56294c 100644 --- a/Data/Base.rte/Activities/Siege.lua +++ b/Data/Base.rte/Activities/Siege.lua @@ -27,7 +27,7 @@ function Siege:StartActivity() self.CPUTechName = self:GetTeamTech(self.CPUTeam); -- Select a tech for the CPU player self.PlayerTechName = self:GetTeamTech(self.PlayerTeam); gPrevAITech = self.CPUTechName -- Store the AI tech in a global so we don't pick the same tech again next round - self.CPUTechID = PresetMan:GetModuleID(self.CPUTechName); + self.CPUTechID = ModuleMan:GetModuleID(self.CPUTechName); self:SetTeamFunds(math.ceil((3000 + self.Difficulty * 175) * rte.StartingFundsScale), self.CPUTeam); if self.Difficulty == 100 then @@ -496,7 +496,7 @@ function Siege:CreateHeavyDrop(xPosLZ, techName) Craft.Pos = Vector(xPosLZ, -30); -- Set the spawn point of the craft for i = 1, Craft.MaxPassengers do - if math.random() < self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(techName)) then + if math.random() < self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(techName)) then Passenger = self:CreateCrab(Actor.AIMODE_GOTO, techName); elseif RangeRand(0, 105) < self.Difficulty then Passenger = self:CreateHeavyInfantry(Actor.AIMODE_GOTO,techName); @@ -516,7 +516,7 @@ function Siege:CreateHeavyDrop(xPosLZ, techName) end -- Subtract the total value of the craft+cargo from the CPU team's funds - self:ChangeTeamFunds(-Craft:GetTotalValue(PresetMan:GetModuleID(techName), 2), self.CPUTeam); + self:ChangeTeamFunds(-Craft:GetTotalValue(ModuleMan:GetModuleID(techName), 2), self.CPUTeam); -- Spawn the Craft onto the scene MovableMan:AddActor(Craft); @@ -553,7 +553,7 @@ function Siege:CreateSWATDrop(xPosLZ, techName) end -- Subtract the total value of the craft+cargo from the CPU team's funds - self:ChangeTeamFunds(-Craft:GetTotalValue(PresetMan:GetModuleID(techName), 2), self.CPUTeam); + self:ChangeTeamFunds(-Craft:GetTotalValue(ModuleMan:GetModuleID(techName), 2), self.CPUTeam); -- Spawn the Craft onto the scene MovableMan:AddActor(Craft); @@ -590,7 +590,7 @@ function Siege:CreateArtilleryDrop(xPosLZ, techName) end -- Subtract the total value of the craft+cargo from the CPU team's funds - self:ChangeTeamFunds(-Craft:GetTotalValue(PresetMan:GetModuleID(techName), 2), self.CPUTeam); + self:ChangeTeamFunds(-Craft:GetTotalValue(ModuleMan:GetModuleID(techName), 2), self.CPUTeam); -- Spawn the Craft onto the scene MovableMan:AddActor(Craft); @@ -644,7 +644,7 @@ function Siege:CreateMediumDrop(xPosLZ, techName) end -- Subtract the total value of the craft+cargo from the CPU team's funds - self:ChangeTeamFunds(-Craft:GetTotalValue(PresetMan:GetModuleID(techName), 2), self.CPUTeam); + self:ChangeTeamFunds(-Craft:GetTotalValue(ModuleMan:GetModuleID(techName), 2), self.CPUTeam); -- Spawn the Craft onto the scene MovableMan:AddActor(Craft); @@ -696,7 +696,7 @@ function Siege:CreateLightDrop(xPosLZ, techName) end -- Subtract the total value of the craft+cargo from the CPU team's funds - self:ChangeTeamFunds(-Craft:GetTotalValue(PresetMan:GetModuleID(techName), 2), self.CPUTeam); + self:ChangeTeamFunds(-Craft:GetTotalValue(ModuleMan:GetModuleID(techName), 2), self.CPUTeam); -- Spawn the Craft onto the scene MovableMan:AddActor(Craft); @@ -744,7 +744,7 @@ function Siege:CreateEngineerDrop(xPosLZ, techName) end -- Subtract the total value of the craft+cargo from the CPU team's funds - self:ChangeTeamFunds(-Craft:GetTotalValue(PresetMan:GetModuleID(techName), 2), self.CPUTeam); + self:ChangeTeamFunds(-Craft:GetTotalValue(ModuleMan:GetModuleID(techName), 2), self.CPUTeam); -- Spawn the Craft onto the scene MovableMan:AddActor(Craft); diff --git a/Data/Base.rte/Activities/SkirmishDefense.lua b/Data/Base.rte/Activities/SkirmishDefense.lua index 49b306347..f29500d2e 100644 --- a/Data/Base.rte/Activities/SkirmishDefense.lua +++ b/Data/Base.rte/Activities/SkirmishDefense.lua @@ -57,7 +57,7 @@ function SkirmishDefense:StartActivity(isNewGame) end end - self.AI[team].TechID = PresetMan:GetModuleID(self:GetTeamTech(team)); + self.AI[team].TechID = ModuleMan:GetModuleID(self:GetTeamTech(team)); end if isNewGame then diff --git a/Data/Base.rte/Activities/Survival.lua b/Data/Base.rte/Activities/Survival.lua index 3ce153062..771c92759 100644 --- a/Data/Base.rte/Activities/Survival.lua +++ b/Data/Base.rte/Activities/Survival.lua @@ -257,7 +257,7 @@ function Survival:UpdateActivity() for i = 1, actorsInCargo do -- Get any Actor from the CPU's native tech local passenger = nil; - if math.random() >= self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.CPUTechName)) then + if math.random() >= self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.CPUTechName)) then passenger = RandomAHuman("Any", self.CPUTechName); else passenger = RandomACrab("Actors - Mecha", self.CPUTechName); diff --git a/Data/Base.rte/Activities/WaveDefense.lua b/Data/Base.rte/Activities/WaveDefense.lua index ac61109ef..fe898ade2 100644 --- a/Data/Base.rte/Activities/WaveDefense.lua +++ b/Data/Base.rte/Activities/WaveDefense.lua @@ -107,7 +107,7 @@ function WaveDefense:StartNewGame() end MovableMan:ChangeActorTeam(actor, self.playerTeam); end - + self:CheckBrains(); for player = Activity.PLAYER_1, Activity.MAXPLAYERCOUNT - 1 do @@ -137,7 +137,7 @@ function WaveDefense:ResumeLoadedGame() self.AI.lastWaveValue = self:LoadNumber("AI_lastWaveValue"); self.AI.Tech = self:GetTeamTech(self.CPUTeam); - self.AI.TechID = PresetMan:GetModuleID(self.AI.Tech); + self.AI.TechID = ModuleMan:GetModuleID(self.AI.Tech); end function WaveDefense:InitWave() @@ -149,7 +149,7 @@ function WaveDefense:InitWave() self.AI.HuntTimer:Reset(); self.AI.Tech = self:GetTeamTech(self.CPUTeam); -- Select a tech for the CPU player - self.AI.TechID = PresetMan:GetModuleID(self.AI.Tech); + self.AI.TechID = ModuleMan:GetModuleID(self.AI.Tech); local lastWavePlayerValue = self.AI.playerValue; self.AI.playerValue = self:GetTeamFunds(self.playerTeam); -- The gold value of the players @@ -623,7 +623,7 @@ function WaveDefense:CreateHeavyDrop(xPosLZ, Destination) passengers = 2; end - local crabRatio = self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.AI.Tech)); + local crabRatio = self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.AI.Tech)); for _ = 1, passengers do local Passenger; if crabRatio > 0 and math.random() < crabRatio + self.Difficulty / 800 then diff --git a/Data/Missions.rte/Activities/DecisionDay.lua b/Data/Missions.rte/Activities/DecisionDay.lua index 4513d60fb..da23b3cca 100644 --- a/Data/Missions.rte/Activities/DecisionDay.lua +++ b/Data/Missions.rte/Activities/DecisionDay.lua @@ -136,8 +136,8 @@ function DecisionDay:StartActivity(isNewGame) self.humanTeam = Activity.TEAM_1; self.aiTeam = Activity.TEAM_2; - self.humanTeamTech = PresetMan:GetModuleID(self:GetTeamTech(self.humanTeam)); - self.aiTeamTech = PresetMan:GetModuleID(self:GetTeamTech(self.aiTeam)); + self.humanTeamTech = ModuleMan:GetModuleID(self:GetTeamTech(self.humanTeam)); + self.aiTeamTech = ModuleMan:GetModuleID(self:GetTeamTech(self.aiTeam)); local bunkerRegionNames = { "Front Bunker Operations", diff --git a/Data/Missions.rte/Activities/DummyAssault.lua b/Data/Missions.rte/Activities/DummyAssault.lua index 5cd425a11..245374db0 100644 --- a/Data/Missions.rte/Activities/DummyAssault.lua +++ b/Data/Missions.rte/Activities/DummyAssault.lua @@ -189,7 +189,7 @@ function DummyAssault:UpdateActivity() self.spawnTimer:Reset(); local actor; - if math.random() > self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.CPUTech)) then + if math.random() > self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.CPUTech)) then actor = RandomAHuman("Actors - Light", self.CPUTech); if math.random() > 0.5 then actor.AIMode = Actor.AIMODE_BRAINHUNT; diff --git a/Data/Missions.rte/Activities/Maginot.lua b/Data/Missions.rte/Activities/Maginot.lua index 708c7ac81..9042cb178 100644 --- a/Data/Missions.rte/Activities/Maginot.lua +++ b/Data/Missions.rte/Activities/Maginot.lua @@ -353,7 +353,7 @@ function MaginotMission:UpdateAttackerSpawns() if self.currentFightStage >= self.fightStage.defendRight then local attackerActor; - if math.random() < self:GetCrabToHumanSpawnRatio(PresetMan:GetModuleID(self.attackerTech)) then + if math.random() < self:GetCrabToHumanSpawnRatio(ModuleMan:GetModuleID(self.attackerTech)) then attackerActor = RandomACrab("Actors - Mecha", self.attackerTech); if attackerActor then attackerActor.Team = self.attackerTeam; @@ -381,7 +381,7 @@ function MaginotMission:UpdateActivity() end self:DoGameOverCheck(); - + local enemyInsideBrainEvacuateArea = false; if self.currentFightStage < self.fightStage.evacuateBrain and self.evacuateCheckTimer:IsPastSimTimeLimit() then for movableObject in MovableMan:GetMOsInBox(self.evacuateTrigger.FirstBox, self.defenderTeam, true) do diff --git a/Data/Missions.rte/Activities/SignalHunt.lua b/Data/Missions.rte/Activities/SignalHunt.lua index 9860b2e8b..db66c1674 100644 --- a/Data/Missions.rte/Activities/SignalHunt.lua +++ b/Data/Missions.rte/Activities/SignalHunt.lua @@ -193,7 +193,7 @@ function SignalHunt:SetupHumanPlayerBrains() if not self:GetPlayerBrain(player) then self.brainDead[player] = false; - local humanTeamTechId = PresetMan:GetModuleID(self.humanTeamTechName); + local humanTeamTechId = ModuleMan:GetModuleID(self.humanTeamTechName); local actor; if humanTeamTechId ~= -1 and team == self.attackerTeam then actor = PresetMan:GetLoadout("Infantry Brain", humanTeamTechId, false); diff --git a/RTEA.vcxproj b/RTEA.vcxproj index 5d914d1a9..485841b47 100644 --- a/RTEA.vcxproj +++ b/RTEA.vcxproj @@ -762,6 +762,7 @@ + @@ -1007,6 +1008,7 @@ + diff --git a/RTEA.vcxproj.filters b/RTEA.vcxproj.filters index b4b09215b..42698060f 100644 --- a/RTEA.vcxproj.filters +++ b/RTEA.vcxproj.filters @@ -624,6 +624,9 @@ Managers + + Managers + @@ -1200,6 +1203,9 @@ Managers + + Managers + @@ -1217,4 +1223,4 @@ System\Semver200 - \ No newline at end of file + diff --git a/Source/Activities/ActorEditor.cpp b/Source/Activities/ActorEditor.cpp index 1ba8f73bd..c5f7f5a55 100644 --- a/Source/Activities/ActorEditor.cpp +++ b/Source/Activities/ActorEditor.cpp @@ -1,5 +1,6 @@ #include "ActorEditor.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "FrameMan.h" @@ -15,7 +16,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "ObjectPickerGUI.h" @@ -239,7 +239,7 @@ bool ActorEditor::ReloadActorData() { if (m_pEditedActor) { std::string presetName = m_pEditedActor->GetPresetName(); std::string className = m_pEditedActor->GetClassName(); - std::string moduleName = g_PresetMan.GetDataModuleName(m_pEditedActor->GetModuleID()); + std::string moduleName = g_ModuleMan.GetModuleName(m_pEditedActor->GetModuleID()); g_PresetMan.ReloadEntityPreset(presetName, className, moduleName, false); LoadActor(g_PresetMan.GetEntityPreset(className, presetName, moduleName)); return m_pEditedActor != nullptr; diff --git a/Source/Activities/AreaEditor.cpp b/Source/Activities/AreaEditor.cpp index aecc071d7..333467753 100644 --- a/Source/Activities/AreaEditor.cpp +++ b/Source/Activities/AreaEditor.cpp @@ -1,6 +1,7 @@ #include "AreaEditor.h" #include "WindowMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "FrameMan.h" @@ -13,7 +14,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "System.h" #include "GUI.h" @@ -452,10 +452,10 @@ bool AreaEditor::SaveScene(const std::string& saveAsName, bool forceOverwrite) { Scene* editedScene = g_SceneMan.GetScene(); editedScene->SetPresetName(saveAsName); - std::string dataModuleName = g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName(); + std::string dataModuleName = g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName(); bool savingToUserScenesModule = (dataModuleName == c_UserScenesModuleName); - std::string dataModuleFullPath = g_PresetMan.GetFullModulePath(dataModuleName); + std::string dataModuleFullPath = g_ModuleMan.GetFullModulePath(dataModuleName); std::string sceneSavePath; std::string previewSavePath; @@ -545,19 +545,19 @@ void AreaEditor::UpdateLoadDialog() { void AreaEditor::UpdateSaveDialog() { m_pSaveNameBox->SetText((g_SceneMan.GetScene()->GetPresetName() == "None" || !m_HasEverBeenSaved) ? "New Scene" : g_SceneMan.GetScene()->GetPresetName()); - if (g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) - m_pSaveModuleLabel->SetText("Will save in " + g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/"); + if (g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) + m_pSaveModuleLabel->SetText("Will save in " + g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/"); else - m_pSaveModuleLabel->SetText("Will save in " + g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes"); + m_pSaveModuleLabel->SetText("Will save in " + g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes"); } void AreaEditor::UpdateChangesDialog() { if (m_HasEverBeenSaved) { dynamic_cast(m_pGUIController->GetControl("ChangesExpLabel"))->SetText("Do you want to save your changes to:"); - if (g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) - m_pChangesNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/" + g_SceneMan.GetScene()->GetPresetName()); + if (g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) + m_pChangesNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/" + g_SceneMan.GetScene()->GetPresetName()); else - m_pChangesNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + g_SceneMan.GetScene()->GetPresetName()); + m_pChangesNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + g_SceneMan.GetScene()->GetPresetName()); } else { dynamic_cast(m_pGUIController->GetControl("ChangesExpLabel"))->SetText("Save your new Scene first?"); m_pChangesNameLabel->SetText(""); @@ -565,8 +565,8 @@ void AreaEditor::UpdateChangesDialog() { } void AreaEditor::UpdateOverwriteDialog() { - if (g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) - m_pOverwriteNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/" + g_SceneMan.GetScene()->GetPresetName()); + if (g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) + m_pOverwriteNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/" + g_SceneMan.GetScene()->GetPresetName()); else - m_pOverwriteNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + g_SceneMan.GetScene()->GetPresetName()); + m_pOverwriteNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + g_SceneMan.GetScene()->GetPresetName()); } diff --git a/Source/Activities/AssemblyEditor.cpp b/Source/Activities/AssemblyEditor.cpp index 3d103e407..7c22bccdc 100644 --- a/Source/Activities/AssemblyEditor.cpp +++ b/Source/Activities/AssemblyEditor.cpp @@ -1,6 +1,7 @@ #include "AssemblyEditor.h" #include "WindowMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "FrameMan.h" @@ -13,7 +14,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "System.h" #include "GUI.h" @@ -244,10 +244,10 @@ void AssemblyEditor::Update() { // Get the Module ID that the scene exists in, so we can limit the picker to only show objects from that DataModule space if (g_SceneMan.GetScene()) { // m_ModuleSpaceID = g_SceneMan.GetScene()->GetModuleID(); - m_ModuleSpaceID = g_PresetMan.GetModuleID(m_pModuleCombo->GetSelectedItem()->m_Name); + m_ModuleSpaceID = g_ModuleMan.GetModuleID(m_pModuleCombo->GetSelectedItem()->m_Name); RTEAssert(m_ModuleSpaceID >= 0, "Loaded Scene's DataModule ID is negative? Should always be a specific one.."); m_pEditorGUI->Destroy(); - if (m_ModuleSpaceID == g_PresetMan.GetModuleID(c_UserScenesModuleName)) + if (m_ModuleSpaceID == g_ModuleMan.GetModuleID(c_UserScenesModuleName)) m_pEditorGUI->Create(&(m_PlayerController[0]), AssemblyEditorGUI::ONLOADEDIT, -1); else m_pEditorGUI->Create(&(m_PlayerController[0]), AssemblyEditorGUI::ONLOADEDIT, m_ModuleSpaceID); @@ -457,10 +457,10 @@ BunkerAssembly* AssemblyEditor::BuildAssembly(std::string saveAsName) { bool AssemblyEditor::SaveAssembly(const std::string& saveAsName, bool forceOverwrite) { std::unique_ptr editedAssembly(BuildAssembly(saveAsName)); - std::string dataModuleName = g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName(); + std::string dataModuleName = g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName(); bool savingToUserScenesModule = (dataModuleName == c_UserScenesModuleName); - std::string dataModuleFullPath = g_PresetMan.GetFullModulePath(dataModuleName); + std::string dataModuleFullPath = g_ModuleMan.GetFullModulePath(dataModuleName); std::string assemblySavePath; if (savingToUserScenesModule) { @@ -529,16 +529,16 @@ void AssemblyEditor::UpdateLoadDialog() { int scenesIndex = 0; if (m_pModuleCombo->GetCount() <= 0) { - for (int module = 0; module < g_PresetMan.GetTotalModuleCount(); ++module) { + for (int module = 0; module < g_ModuleMan.GetTotalModuleCount(); ++module) { // Cut-off vanilla modules except Base.rte bool isValid = false; // If metascenes are visible then allow to save assemblies to Base.rte if (g_SettingsMan.ShowMetascenes()) { - if ((module == 0 || module > 8) && g_PresetMan.GetDataModule(module)->GetFileName() != c_UserConquestSavesModuleName && g_PresetMan.GetDataModule(module)->GetFileName() != "Missions.rte") + if ((module == 0 || module > 8) && g_ModuleMan.GetDataModule(module)->GetFileName() != c_UserConquestSavesModuleName && g_ModuleMan.GetDataModule(module)->GetFileName() != "Missions.rte") isValid = true; } else { - if (module > 8 && g_PresetMan.GetDataModule(module)->GetFileName() != c_UserConquestSavesModuleName && g_PresetMan.GetDataModule(module)->GetFileName() != "Missions.rte" && g_PresetMan.GetDataModule(module)->GetFileName() != c_UserScriptedSavesModuleName) + if (module > 8 && g_ModuleMan.GetDataModule(module)->GetFileName() != c_UserConquestSavesModuleName && g_ModuleMan.GetDataModule(module)->GetFileName() != "Missions.rte" && g_ModuleMan.GetDataModule(module)->GetFileName() != c_UserScriptedSavesModuleName) isValid = true; } @@ -547,14 +547,14 @@ void AssemblyEditor::UpdateLoadDialog() { isValid = true; if (isValid) { - m_pModuleCombo->AddItem(g_PresetMan.GetDataModule(module)->GetFileName()); + m_pModuleCombo->AddItem(g_ModuleMan.GetDataModule(module)->GetFileName()); if (g_SettingsMan.AllowSavingToBase()) { // If editors are in dev-mode then select Base.rte as default module to save stuff - if (g_PresetMan.GetDataModule(module)->GetFileName() == "Base.rte") + if (g_ModuleMan.GetDataModule(module)->GetFileName() == "Base.rte") scenesIndex = m_pModuleCombo->GetCount() - 1; } else { - if (g_PresetMan.GetDataModule(module)->GetFileName() == c_UserScenesModuleName) + if (g_ModuleMan.GetDataModule(module)->GetFileName() == c_UserScenesModuleName) scenesIndex = m_pModuleCombo->GetCount() - 1; } } @@ -593,7 +593,7 @@ void AssemblyEditor::UpdateSaveDialog() { defaultName = pScheme->GetPresetName() + " - "; m_pSaveNameBox->SetText(m_pEditorGUI->GetCurrentAssemblyName() == "" ? defaultName : m_pEditorGUI->GetCurrentAssemblyName()); - m_pSaveModuleLabel->SetText("Will save in " + g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName()); + m_pSaveModuleLabel->SetText("Will save in " + g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName()); } void AssemblyEditor::UpdateChangesDialog() { diff --git a/Source/Activities/BaseEditor.cpp b/Source/Activities/BaseEditor.cpp index aabb7cca8..8b6b54857 100644 --- a/Source/Activities/BaseEditor.cpp +++ b/Source/Activities/BaseEditor.cpp @@ -17,7 +17,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "SceneEditorGUI.h" @@ -245,7 +244,7 @@ bool BaseEditor::SaveScene(std::string saveAsName, bool forceOverwrite) { // Set the name of the current scene in effect g_SceneMan.GetScene()->SetPresetName(saveAsName); // Try to save to the data module - string sceneFilePath(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + saveAsName + ".ini"); + string sceneFilePath(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + saveAsName + ".ini"); if (g_PresetMan.AddEntityPreset(g_SceneMan.GetScene(), m_ModuleSpaceID, forceOverwrite, sceneFilePath)) { // Does ini already exist? If yes, then no need to add it to a scenes.ini etc @@ -260,7 +259,7 @@ bool BaseEditor::SaveScene(std::string saveAsName, bool forceOverwrite) { if (!sceneFileExisted) { // First find/create a .rte/Scenes.ini file to include the new .ini into - string scenesFilePath(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes.ini"); + string scenesFilePath(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes.ini"); bool scenesFileExisted = System::PathExistsCaseSensitive(scenesFilePath.c_str()); Writer scenesWriter(scenesFilePath.c_str(), true); scenesWriter.NewProperty("\nIncludeFile"); @@ -270,7 +269,7 @@ bool BaseEditor::SaveScene(std::string saveAsName, bool forceOverwrite) { // If it's already included, it doens't matter, the definitions will just bounce the second time if (!scenesFileExisted) { - string indexFilePath(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Index.ini"); + string indexFilePath(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Index.ini"); Writer indexWriter(indexFilePath.c_str(), true); // Add extra tab since the DataModule has everything indented indexWriter.NewProperty("\tIncludeFile"); diff --git a/Source/Activities/EditorActivity.cpp b/Source/Activities/EditorActivity.cpp index 4a904c60f..02a23dece 100644 --- a/Source/Activities/EditorActivity.cpp +++ b/Source/Activities/EditorActivity.cpp @@ -12,7 +12,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "GUI.h" #include "AllegroScreen.h" @@ -302,7 +301,7 @@ void EditorActivity::Update() { GUIListPanel::Item *pItem = m_pNewModuleCombo->GetItem(m_pNewModuleCombo->GetSelectedIndex()); if (pItem && !pItem->m_Name.empty()) { - m_ModuleSpaceID = g_PresetMan.GetModuleID(pItem->m_Name); + m_ModuleSpaceID = g_ModuleMan.GetModuleID(pItem->m_Name); // Allocate Scene Scene *pNewScene = new Scene(); diff --git a/Source/Activities/GAScripted.cpp b/Source/Activities/GAScripted.cpp index bcc7d2c7e..59c3f83cf 100644 --- a/Source/Activities/GAScripted.cpp +++ b/Source/Activities/GAScripted.cpp @@ -1,6 +1,7 @@ #include "GAScripted.h" #include "SceneMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "UInputMan.h" @@ -89,7 +90,7 @@ int GAScripted::ReadProperty(const std::string_view& propName, Reader& reader) { StartPropertyList(return GameActivity::ReadProperty(propName, reader)); MatchProperty("ScriptPath", { - m_ScriptPath = g_PresetMan.GetFullModulePath(reader.ReadPropValue()); + m_ScriptPath = g_ModuleMan.GetFullModulePath(reader.ReadPropValue()); }); MatchProperty("LuaClassName", { reader >> m_LuaClassName; diff --git a/Source/Activities/GameActivity.cpp b/Source/Activities/GameActivity.cpp index ea32f69a0..7c93d44dc 100644 --- a/Source/Activities/GameActivity.cpp +++ b/Source/Activities/GameActivity.cpp @@ -1,6 +1,7 @@ #include "GameActivity.h" #include "CameraMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "WindowMan.h" @@ -11,7 +12,6 @@ #include "ConsoleMan.h" #include "PresetMan.h" #include "SceneMan.h" -#include "DataModule.h" #include "PostProcessMan.h" #include "Controller.h" #include "Scene.h" @@ -287,7 +287,7 @@ void GameActivity::SetTeamTech(int team, std::string tech) { if (tech == "-All-" || tech == "-Random-") m_TeamTech[team] = tech; else { - int id = g_PresetMan.GetModuleID(tech); + int id = g_ModuleMan.GetModuleID(tech); if (id != -1) m_TeamTech[team] = tech; else @@ -298,7 +298,7 @@ void GameActivity::SetTeamTech(int team, std::string tech) { float GameActivity::GetCrabToHumanSpawnRatio(int moduleid) { if (moduleid > -1) { - const DataModule* pDataModule = g_PresetMan.GetDataModule(moduleid); + const DataModule* pDataModule = g_ModuleMan.GetDataModule(moduleid); if (pDataModule) return pDataModule->GetCrabToHumanSpawnRatio(); } @@ -773,7 +773,7 @@ int GameActivity::Start() { // Load correct loadouts into buy menu if we're starting a non meta-game activity if (m_pBuyGUI[player]->GetMetaPlayer() == Players::NoPlayer) { - int techModuleID = g_PresetMan.GetModuleID(GetTeamTech(GetTeamOfPlayer(player))); + int techModuleID = g_ModuleMan.GetModuleID(GetTeamTech(GetTeamOfPlayer(player))); m_pBuyGUI[player]->SetNativeTechModule(techModuleID); m_pBuyGUI[player]->SetForeignCostMultiplier(1.0); diff --git a/Source/Activities/GibEditor.cpp b/Source/Activities/GibEditor.cpp index 16fc69c41..b3c4de64e 100644 --- a/Source/Activities/GibEditor.cpp +++ b/Source/Activities/GibEditor.cpp @@ -1,6 +1,7 @@ #include "GibEditor.h" #include "WindowMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "FrameMan.h" @@ -15,7 +16,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "GUI.h" #include "AllegroBitmap.h" @@ -331,7 +331,7 @@ void GibEditor::Update() { GUIListPanel::Item *pItem = m_pNewModuleCombo->GetItem(m_pNewModuleCombo->GetSelectedIndex()); if (pItem && !pItem->m_Name.empty()) { - m_ModuleSpaceID = g_PresetMan.GetModuleID(pItem->m_Name); + m_ModuleSpaceID = g_ModuleMan.GetModuleID(pItem->m_Name); // Allocate Scene Scene *pNewScene = new Scene(); @@ -567,8 +567,8 @@ bool GibEditor::SaveObject(const std::string& saveAsName, bool forceOverwrite) { // Replace the gibs of the object with the proxies that have been edited in the GUI. StuffEditedGibs(m_pEditedObject); - std::string dataModuleName = g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName(); - std::string dataModuleFullPath = g_PresetMan.GetFullModulePath(dataModuleName); + std::string dataModuleName = g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName(); + std::string dataModuleFullPath = g_ModuleMan.GetFullModulePath(dataModuleName); std::string newDataDir = dataModuleFullPath + "/NewData"; std::string objectSavePath = newDataDir + "/" + saveAsName + ".ini"; @@ -652,8 +652,8 @@ void GibEditor::UpdateNewDialog() { // Only refill modules if empty if (m_pNewModuleCombo->GetCount() <= 0) { - for (int module = 0; module < g_PresetMan.GetTotalModuleCount(); ++module) - m_pNewModuleCombo->AddItem(g_PresetMan.GetDataModule(module)->GetFileName()); + for (int module = 0; module < g_ModuleMan.GetTotalModuleCount(); ++module) + m_pNewModuleCombo->AddItem(g_ModuleMan.GetDataModule(module)->GetFileName()); // Select the first one m_pNewModuleCombo->SetSelectedIndex(0); @@ -663,7 +663,7 @@ void GibEditor::UpdateNewDialog() { int selectedModuleID = -1; GUIListPanel::Item *pItem = m_pNewModuleCombo->GetItem(m_pNewModuleCombo->GetSelectedIndex()); if (pItem && !pItem->m_Name.empty()) - selectedModuleID = g_PresetMan.GetModuleID(pItem->m_Name); + selectedModuleID = g_ModuleMan.GetModuleID(pItem->m_Name); // Refill Terrains m_pNewTerrainCombo->ClearList(); @@ -711,7 +711,7 @@ void GibEditor::UpdateSaveDialog() { m_pSaveNameBox->SetText((m_pEditedObject->GetPresetName() == "None" || !m_HasEverBeenSaved) ? "New Object" : m_pEditedObject->GetPresetName()); // TODO: Really? - m_pSaveModuleLabel->SetText("Will save in " + g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/NewData/"); + m_pSaveModuleLabel->SetText("Will save in " + g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/NewData/"); } void GibEditor::UpdateChangesDialog() { @@ -720,7 +720,7 @@ void GibEditor::UpdateChangesDialog() { if (m_HasEverBeenSaved) { dynamic_cast(m_pGUIController->GetControl("ChangesExpLabel"))->SetText("Do you want to save your changes to:"); - m_pChangesNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/NewData/" + m_pEditedObject->GetPresetName() + ".ini"); + m_pChangesNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/NewData/" + m_pEditedObject->GetPresetName() + ".ini"); } else { dynamic_cast(m_pGUIController->GetControl("ChangesExpLabel"))->SetText("Save your new Object first?"); m_pChangesNameLabel->SetText(""); @@ -729,7 +729,7 @@ void GibEditor::UpdateChangesDialog() { void GibEditor::UpdateOverwriteDialog() { if (m_pEditedObject) - m_pOverwriteNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/NewData/" + m_pEditedObject->GetPresetName() + ".ini"); + m_pOverwriteNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/NewData/" + m_pEditedObject->GetPresetName() + ".ini"); } void GibEditor::ClearTestArea() const { diff --git a/Source/Activities/MultiplayerGame.cpp b/Source/Activities/MultiplayerGame.cpp index b685d1ce4..71b7c205b 100644 --- a/Source/Activities/MultiplayerGame.cpp +++ b/Source/Activities/MultiplayerGame.cpp @@ -13,7 +13,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "AudioMan.h" #include "GUI.h" diff --git a/Source/Activities/MultiplayerServerLobby.cpp b/Source/Activities/MultiplayerServerLobby.cpp index 07cff8c9d..e10338068 100644 --- a/Source/Activities/MultiplayerServerLobby.cpp +++ b/Source/Activities/MultiplayerServerLobby.cpp @@ -1,5 +1,6 @@ #include "MultiplayerServerLobby.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "FrameMan.h" @@ -12,7 +13,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "MetaMan.h" #include "AudioMan.h" #include "LuaMan.h" @@ -234,8 +234,8 @@ int MultiplayerServerLobby::Start() { m_pCPULockLabel = dynamic_cast(m_pGUIController->GetControl("CPULockLabel")); // Populate the tech comboboxes with the available tech modules - for (int moduleID = 0; moduleID < g_PresetMan.GetTotalModuleCount(); ++moduleID) { - if (const DataModule* dataModule = g_PresetMan.GetDataModule(moduleID)) { + for (int moduleID = 0; moduleID < g_ModuleMan.GetTotalModuleCount(); ++moduleID) { + if (const DataModule* dataModule = g_ModuleMan.GetDataModule(moduleID)) { if (dataModule->IsFaction()) { for (int team = Activity::Teams::TeamOne; team < Activity::Teams::MaxTeamCount; ++team) { m_apTeamTechSelect[team]->GetListPanel()->AddItem(dataModule->GetFriendlyName(), "", nullptr, nullptr, moduleID); @@ -787,7 +787,7 @@ bool MultiplayerServerLobby::StartGame() { if (pTechItem->m_ExtraIndex == -2) pGameActivity->SetTeamTech(team, "-All-"); else - pGameActivity->SetTeamTech(team, g_PresetMan.GetDataModuleName(pTechItem->m_ExtraIndex)); + pGameActivity->SetTeamTech(team, g_ModuleMan.GetModuleName(pTechItem->m_ExtraIndex)); } } diff --git a/Source/Activities/SceneEditor.cpp b/Source/Activities/SceneEditor.cpp index 6680766a7..7d703e1d3 100644 --- a/Source/Activities/SceneEditor.cpp +++ b/Source/Activities/SceneEditor.cpp @@ -1,6 +1,7 @@ #include "SceneEditor.h" #include "WindowMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "FrameMan.h" @@ -13,7 +14,6 @@ #include "ACRocket.h" #include "HeldDevice.h" #include "Scene.h" -#include "DataModule.h" #include "SLBackground.h" #include "GUI.h" @@ -291,7 +291,7 @@ void SceneEditor::Update() { // Get the selected Module GUIListPanel::Item* pItem = m_pNewModuleCombo->GetItem(m_pNewModuleCombo->GetSelectedIndex()); if (pItem && !pItem->m_Name.empty()) { - m_ModuleSpaceID = g_PresetMan.GetModuleID(pItem->m_Name); + m_ModuleSpaceID = g_ModuleMan.GetModuleID(pItem->m_Name); // Allocate Scene Scene* pNewScene = new Scene(); @@ -333,7 +333,7 @@ void SceneEditor::Update() { // Reset the rest of the editor GUI m_pEditorGUI->Destroy(); - if (m_ModuleSpaceID == g_PresetMan.GetModuleID(c_UserScenesModuleName)) + if (m_ModuleSpaceID == g_ModuleMan.GetModuleID(c_UserScenesModuleName)) m_pEditorGUI->Create(&(m_PlayerController[0]), SceneEditorGUI::ONLOADEDIT, -1); else m_pEditorGUI->Create(&(m_PlayerController[0]), SceneEditorGUI::ONLOADEDIT, m_ModuleSpaceID); @@ -368,7 +368,7 @@ void SceneEditor::Update() { m_ModuleSpaceID = g_SceneMan.GetScene()->GetModuleID(); RTEAssert(m_ModuleSpaceID >= 0, "Loaded Scene's DataModule ID is negative? Should always be a specific one.."); m_pEditorGUI->Destroy(); - if (m_ModuleSpaceID == g_PresetMan.GetModuleID(c_UserScenesModuleName)) + if (m_ModuleSpaceID == g_ModuleMan.GetModuleID(c_UserScenesModuleName)) m_pEditorGUI->Create(&(m_PlayerController[0]), SceneEditorGUI::ONLOADEDIT, -1); else m_pEditorGUI->Create(&(m_PlayerController[0]), SceneEditorGUI::ONLOADEDIT, m_ModuleSpaceID); @@ -504,10 +504,10 @@ bool SceneEditor::SaveScene(const std::string& saveAsName, bool forceOverwrite) Scene* editedScene = g_SceneMan.GetScene(); editedScene->SetPresetName(saveAsName); - std::string dataModuleName = g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName(); + std::string dataModuleName = g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName(); bool savingToUserScenesModule = (dataModuleName == c_UserScenesModuleName); - std::string dataModuleFullPath = g_PresetMan.GetFullModulePath(dataModuleName); + std::string dataModuleFullPath = g_ModuleMan.GetFullModulePath(dataModuleName); std::string sceneSavePath; std::string previewSavePath; @@ -573,10 +573,10 @@ void SceneEditor::UpdateNewDialog() { // Only refill modules if empty if (m_pNewModuleCombo->GetCount() <= 0) { - for (int module = 0; module < g_PresetMan.GetTotalModuleCount(); ++module) { - m_pNewModuleCombo->AddItem(g_PresetMan.GetDataModule(module)->GetFileName()); + for (int module = 0; module < g_ModuleMan.GetTotalModuleCount(); ++module) { + m_pNewModuleCombo->AddItem(g_ModuleMan.GetDataModule(module)->GetFileName()); - if (g_PresetMan.GetDataModule(module)->GetFileName() == c_UserScenesModuleName) + if (g_ModuleMan.GetDataModule(module)->GetFileName() == c_UserScenesModuleName) scenesIndex = m_pNewModuleCombo->GetCount() - 1; } @@ -588,7 +588,7 @@ void SceneEditor::UpdateNewDialog() { int selectedModuleID = -1; GUIListPanel::Item* pItem = m_pNewModuleCombo->GetItem(m_pNewModuleCombo->GetSelectedIndex()); if (pItem && !pItem->m_Name.empty()) - selectedModuleID = g_PresetMan.GetModuleID(pItem->m_Name); + selectedModuleID = g_ModuleMan.GetModuleID(pItem->m_Name); // Refill Terrains m_pNewTerrainCombo->ClearList(); @@ -663,19 +663,19 @@ void SceneEditor::UpdateLoadDialog() { void SceneEditor::UpdateSaveDialog() { m_pSaveNameBox->SetText((g_SceneMan.GetScene()->GetPresetName() == "None" || !m_HasEverBeenSaved) ? "New Scene" : g_SceneMan.GetScene()->GetPresetName()); - if (g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) - m_pSaveModuleLabel->SetText("Will save in " + g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/"); + if (g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) + m_pSaveModuleLabel->SetText("Will save in " + g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/"); else - m_pSaveModuleLabel->SetText("Will save in " + g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes"); + m_pSaveModuleLabel->SetText("Will save in " + g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes"); } void SceneEditor::UpdateChangesDialog() { if (m_HasEverBeenSaved) { dynamic_cast(m_pGUIController->GetControl("ChangesExpLabel"))->SetText("Do you want to save your changes to:"); - if (g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) - m_pChangesNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/" + g_SceneMan.GetScene()->GetPresetName()); + if (g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) + m_pChangesNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/" + g_SceneMan.GetScene()->GetPresetName()); else - m_pChangesNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + g_SceneMan.GetScene()->GetPresetName()); + m_pChangesNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + g_SceneMan.GetScene()->GetPresetName()); } else { dynamic_cast(m_pGUIController->GetControl("ChangesExpLabel"))->SetText("Save your new Scene first?"); m_pChangesNameLabel->SetText(""); @@ -683,8 +683,8 @@ void SceneEditor::UpdateChangesDialog() { } void SceneEditor::UpdateOverwriteDialog() { - if (g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) - m_pOverwriteNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/" + g_SceneMan.GetScene()->GetPresetName()); + if (g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() == c_UserScenesModuleName) + m_pOverwriteNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/" + g_SceneMan.GetScene()->GetPresetName()); else - m_pOverwriteNameLabel->SetText(g_PresetMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + g_SceneMan.GetScene()->GetPresetName()); + m_pOverwriteNameLabel->SetText(g_ModuleMan.GetDataModule(m_ModuleSpaceID)->GetFileName() + "/Scenes/" + g_SceneMan.GetScene()->GetPresetName()); } diff --git a/Source/Entities/Deployment.cpp b/Source/Entities/Deployment.cpp index 5251b1313..662548774 100644 --- a/Source/Entities/Deployment.cpp +++ b/Source/Entities/Deployment.cpp @@ -1,4 +1,5 @@ #include "Deployment.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MetaMan.h" #include "ContentFile.h" @@ -7,7 +8,6 @@ #include "Actor.h" #include "ACraft.h" #include "ActivityMan.h" -#include "DataModule.h" using namespace RTE; @@ -141,20 +141,20 @@ Actor* Deployment::CreateDeployedActor(int player, float& costTally) { if (activity) { // Also set the team of this Deployable to match the player's // m_Team = activity->GetTeamOfPlayer(player); - nativeModule = g_PresetMan.GetModuleID(activity->GetTeamTech(m_Team)); + nativeModule = g_ModuleMan.GetModuleID(activity->GetTeamTech(m_Team)); // Select some random module if player selected all or something else if (nativeModule < 0) { std::vector moduleList; - for (int moduleID = 0; moduleID < g_PresetMan.GetTotalModuleCount(); ++moduleID) { - if (const DataModule* dataModule = g_PresetMan.GetDataModule(moduleID)) { + for (int moduleID = 0; moduleID < g_ModuleMan.GetTotalModuleCount(); ++moduleID) { + if (const DataModule* dataModule = g_ModuleMan.GetDataModule(moduleID)) { if (dataModule->IsFaction()) { moduleList.emplace_back(dataModule->GetFileName()); } } } int selection = RandomNum(1, moduleList.size() - 1); - nativeModule = g_PresetMan.GetModuleID(moduleList.at(selection)); + nativeModule = g_ModuleMan.GetModuleID(moduleList.at(selection)); } foreignCostMult = 1.0; nativeCostMult = 1.0; @@ -203,20 +203,20 @@ SceneObject* Deployment::CreateDeployedObject(int player, float& costTally) { if (activity) { // Also set the team of this Deployable to match the player's // m_Team = activity->GetTeamOfPlayer(player); - nativeModule = g_PresetMan.GetModuleID(activity->GetTeamTech(m_Team)); + nativeModule = g_ModuleMan.GetModuleID(activity->GetTeamTech(m_Team)); // Select some random module if player selected all or something else if (nativeModule < 0) { std::vector moduleList; - for (int moduleID = 0; moduleID < g_PresetMan.GetTotalModuleCount(); ++moduleID) { - if (const DataModule* dataModule = g_PresetMan.GetDataModule(moduleID)) { + for (int moduleID = 0; moduleID < g_ModuleMan.GetTotalModuleCount(); ++moduleID) { + if (const DataModule* dataModule = g_ModuleMan.GetDataModule(moduleID)) { if (dataModule->IsFaction()) { moduleList.emplace_back(dataModule->GetFileName()); } } } int selection = RandomNum(1, moduleList.size() - 1); - nativeModule = g_PresetMan.GetModuleID(moduleList.at(selection)); + nativeModule = g_ModuleMan.GetModuleID(moduleList.at(selection)); } foreignCostMult = 1.0; nativeCostMult = 1.0; diff --git a/Source/Entities/MetaPlayer.cpp b/Source/Entities/MetaPlayer.cpp index 61bded513..27fc0e203 100644 --- a/Source/Entities/MetaPlayer.cpp +++ b/Source/Entities/MetaPlayer.cpp @@ -1,6 +1,5 @@ #include "MetaPlayer.h" -#include "DataModule.h" -#include "PresetMan.h" +#include "ModuleMan.h" #include "ActivityMan.h" using namespace RTE; @@ -82,7 +81,7 @@ int MetaPlayer::ReadProperty(const std::string_view& propName, Reader& reader) { // Need to match the name to the index }); MatchProperty("NativeTechModule", { - m_NativeTechModule = g_PresetMan.GetModuleID(reader.ReadPropValue()); + m_NativeTechModule = g_ModuleMan.GetModuleID(reader.ReadPropValue()); // Default to no native tech if the one we're looking for couldn't be found if (m_NativeTechModule < 0) { m_NativeTechModule = 0; @@ -117,7 +116,7 @@ int MetaPlayer::Save(Writer& writer) const { // Need to write out the name, and not just the index of the module. it might change writer.NewProperty("NativeTechModule"); - writer << g_PresetMan.GetDataModule(m_NativeTechModule)->GetFileName(); + writer << g_ModuleMan.GetDataModule(m_NativeTechModule)->GetFileName(); writer.NewProperty("NativeCostMultiplier"); writer << m_NativeCostMult; writer.NewProperty("ForeignCostMultiplier"); diff --git a/Source/Entities/MovableObject.cpp b/Source/Entities/MovableObject.cpp index 7ef5ba1b3..9887b2999 100644 --- a/Source/Entities/MovableObject.cpp +++ b/Source/Entities/MovableObject.cpp @@ -1,6 +1,7 @@ #include "MovableObject.h" #include "ActivityMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "SceneMan.h" #include "ConsoleMan.h" @@ -318,7 +319,7 @@ int MovableObject::ReadProperty(const std::string_view& propName, Reader& reader MatchProperty("CanBeSquished", { reader >> m_CanBeSquished; }); MatchProperty("HUDVisible", { reader >> m_HUDVisible; }); MatchProperty("ScriptPath", { - std::string scriptPath = g_PresetMan.GetFullModulePath(reader.ReadPropValue()); + std::string scriptPath = g_ModuleMan.GetFullModulePath(reader.ReadPropValue()); switch (LoadScript(scriptPath)) { case 0: break; diff --git a/Source/Entities/SLTerrain.cpp b/Source/Entities/SLTerrain.cpp index 5d7bca955..5f6ef65e1 100644 --- a/Source/Entities/SLTerrain.cpp +++ b/Source/Entities/SLTerrain.cpp @@ -1,4 +1,5 @@ #include "SLTerrain.h" +#include "ModuleMan.h" #include "TerrainFrosting.h" #include "TerrainDebris.h" #include "TerrainObject.h" @@ -6,8 +7,6 @@ #include "MOSprite.h" #include "MOPixel.h" #include "Atom.h" -#include "DataModule.h" -#include "PresetMan.h" #include #include @@ -188,7 +187,7 @@ void SLTerrain::TexturizeTerrain() { BITMAP* bgLayerTexture = m_BGColorLayer->GetBitmap(); const std::array& materialPalette = g_SceneMan.GetMaterialPalette(); - const std::array& materialMappings = g_PresetMan.GetDataModule(m_BitmapFile.GetDataModuleID())->GetAllMaterialMappings(); + const std::array& materialMappings = g_ModuleMan.GetDataModule(g_ModuleMan.GetModuleIDFromPath(m_BitmapFile.GetDataPath()))->GetAllMaterialMappings(); std::array materialFGTextures; materialFGTextures.fill(nullptr); diff --git a/Source/Entities/Scene.cpp b/Source/Entities/Scene.cpp index 2216c5586..0f5bb804e 100644 --- a/Source/Entities/Scene.cpp +++ b/Source/Entities/Scene.cpp @@ -1,5 +1,6 @@ #include "Scene.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "MovableMan.h" #include "FrameMan.h" @@ -809,7 +810,7 @@ int Scene::ExpandAIPlanAssemblySchemes() { } int Scene::SaveData(std::string pathBase, bool doAsyncSaves) { - const std::string fullPathBase = g_PresetMan.GetFullModulePath(pathBase); + const std::string fullPathBase = g_ModuleMan.GetFullModulePath(pathBase); if (fullPathBase.empty()) return -1; diff --git a/Source/GUI/GUIControlManager.cpp b/Source/GUI/GUIControlManager.cpp index 7a2f0fa76..800fe9704 100644 --- a/Source/GUI/GUIControlManager.cpp +++ b/Source/GUI/GUIControlManager.cpp @@ -1,5 +1,5 @@ #include "GUI.h" -#include "PresetMan.h" +#include "ModuleMan.h" #include @@ -378,7 +378,7 @@ bool GUIControlManager::Save(GUIWriter* W) { bool GUIControlManager::Load(const std::string& Filename, bool keepOld) { GUIReader reader; - const std::string pathFile = g_PresetMan.GetFullModulePath(Filename); + const std::string pathFile = g_ModuleMan.GetFullModulePath(Filename); if (reader.Create(pathFile.c_str()) != 0) { return false; } diff --git a/Source/GUI/GUISkin.cpp b/Source/GUI/GUISkin.cpp index 4a2c0a18d..76ad56df7 100644 --- a/Source/GUI/GUISkin.cpp +++ b/Source/GUI/GUISkin.cpp @@ -1,6 +1,6 @@ #include "GUI.h" #include "GUIReader.h" -#include "PresetMan.h" +#include "ModuleMan.h" #include @@ -31,11 +31,11 @@ bool GUISkin::Load(const std::string& directory, const std::string& fileName) { std::string dirTemp; if (!directory.empty()) { - m_Directory = g_PresetMan.GetFullModulePath(directory) + "/"; + m_Directory = g_ModuleMan.GetFullModulePath(directory) + "/"; dirTemp = m_Directory; } else { // Empty directory means file can be loaded from anywhere in the working directory so need to figure out in what data directory the file actually is from fileName. - std::string fileFullPath = g_PresetMan.GetFullModulePath(fileName); + std::string fileFullPath = g_ModuleMan.GetFullModulePath(fileName); dirTemp = fileFullPath.substr(0, fileFullPath.find_first_of("/\\") + 1); // Make sure to clear any existing top level directory and not store the new one we got from fileName otherwise everything will be on fire when trying to load assets from Data/ while the skin file exists in Mods/. m_Directory = ""; diff --git a/Source/Lua/LuaAdapterDefinitions.h b/Source/Lua/LuaAdapterDefinitions.h index 5c0f32c5a..2427d087c 100644 --- a/Source/Lua/LuaAdapterDefinitions.h +++ b/Source/Lua/LuaAdapterDefinitions.h @@ -12,6 +12,7 @@ #include "MovableMan.h" #include "PerformanceMan.h" #include "PostProcessMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "PrimitiveMan.h" #include "SceneMan.h" @@ -21,7 +22,6 @@ #include "Box.h" #include "Controller.h" -#include "DataModule.h" #include "GraphicalPrimitive.h" #include "PathFinder.h" diff --git a/Source/Lua/LuaAdapters.cpp b/Source/Lua/LuaAdapters.cpp index fd4d140bb..da9bfc55d 100644 --- a/Source/Lua/LuaAdapters.cpp +++ b/Source/Lua/LuaAdapters.cpp @@ -25,22 +25,22 @@ std::unordered_map(entityPreset->Clone()); \ } \ TYPE* LuaAdaptersEntityCreate::Random##TYPE(std::string groupName, std::string dataModuleName) { \ - int moduleSpaceID = g_PresetMan.GetModuleID(dataModuleName); \ + int moduleSpaceID = g_ModuleMan.GetModuleID(dataModuleName); \ const Entity* entityPreset = g_PresetMan.GetRandomBuyableOfGroupFromTech(groupName, #TYPE, moduleSpaceID); \ if (!entityPreset) { \ - entityPreset = g_PresetMan.GetRandomBuyableOfGroupFromTech(groupName, #TYPE, g_PresetMan.GetModuleID("Base.rte")); \ + entityPreset = g_PresetMan.GetRandomBuyableOfGroupFromTech(groupName, #TYPE, g_ModuleMan.GetModuleID("Base.rte")); \ } \ if (!entityPreset) { \ entityPreset = g_PresetMan.GetRandomBuyableOfGroupFromTech("Any", #TYPE, moduleSpaceID); \ @@ -336,11 +336,11 @@ void LuaAdaptersActivity::SendMessage2(Activity* luaSelfObject, const std::strin } bool LuaAdaptersMovableObject::HasScript(MovableObject* luaSelfObject, const std::string& scriptPath) { - return luaSelfObject->HasScript(g_PresetMan.GetFullModulePath(scriptPath)); + return luaSelfObject->HasScript(g_ModuleMan.GetFullModulePath(scriptPath)); } bool LuaAdaptersMovableObject::AddScript(MovableObject* luaSelfObject, const std::string& scriptPath) { - switch (std::string correctedScriptPath = g_PresetMan.GetFullModulePath(scriptPath); luaSelfObject->LoadScript(correctedScriptPath)) { + switch (std::string correctedScriptPath = g_ModuleMan.GetFullModulePath(scriptPath); luaSelfObject->LoadScript(correctedScriptPath)) { case 0: return true; case -1: @@ -366,7 +366,7 @@ bool LuaAdaptersMovableObject::AddScript(MovableObject* luaSelfObject, const std } bool LuaAdaptersMovableObject::EnableScript(MovableObject* luaSelfObject, const std::string& scriptPath) { - return luaSelfObject->EnableOrDisableScript(g_PresetMan.GetFullModulePath(scriptPath), true); + return luaSelfObject->EnableOrDisableScript(g_ModuleMan.GetFullModulePath(scriptPath), true); } bool LuaAdaptersMovableObject::DisableScript1(MovableObject* luaSelfObject) { @@ -375,7 +375,7 @@ bool LuaAdaptersMovableObject::DisableScript1(MovableObject* luaSelfObject) { } bool LuaAdaptersMovableObject::DisableScript2(MovableObject* luaSelfObject, const std::string& scriptPath) { - return luaSelfObject->EnableOrDisableScript(g_PresetMan.GetFullModulePath(scriptPath), false); + return luaSelfObject->EnableOrDisableScript(g_ModuleMan.GetFullModulePath(scriptPath), false); } void LuaAdaptersMovableObject::SendMessage1(MovableObject* luaSelfObject, const std::string& message) { diff --git a/Source/Lua/LuaBindingRegisterDefinitions.h b/Source/Lua/LuaBindingRegisterDefinitions.h index 70dd73392..602267ccc 100644 --- a/Source/Lua/LuaBindingRegisterDefinitions.h +++ b/Source/Lua/LuaBindingRegisterDefinitions.h @@ -193,6 +193,7 @@ namespace RTE { LuaBindingRegisterFunctionDeclarationForType(ConsoleMan); LuaBindingRegisterFunctionDeclarationForType(FrameMan); LuaBindingRegisterFunctionDeclarationForType(MetaMan); + LuaBindingRegisterFunctionDeclarationForType(ModuleMan); LuaBindingRegisterFunctionDeclarationForType(MovableMan); LuaBindingRegisterFunctionDeclarationForType(PerformanceMan); LuaBindingRegisterFunctionDeclarationForType(PostProcessMan); diff --git a/Source/Lua/LuaBindingsManagers.cpp b/Source/Lua/LuaBindingsManagers.cpp index 455f02d8d..b08a0453b 100644 --- a/Source/Lua/LuaBindingsManagers.cpp +++ b/Source/Lua/LuaBindingsManagers.cpp @@ -109,6 +109,21 @@ LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, MetaMan) { .def("GetMetaPlayerOfInGamePlayer", &MetaMan::GetMetaPlayerOfInGamePlayer); } +LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, ModuleMan) { + return luabind::class_("ModuleManager") + + .def_readwrite("Modules", &ModuleMan::m_LoadedDataModules, luabind::return_stl_iterator) + + .def("GetDataModule", (DataModule * (ModuleMan::*)(int)) & ModuleMan::GetDataModule) + .def("GetDataModule", (DataModule * (ModuleMan::*)(const std::string_view&)) & ModuleMan::GetDataModule) + .def("GetModuleID", &ModuleMan::GetModuleID) + .def("GetModuleIDFromPath", &ModuleMan::GetModuleIDFromPath) + .def("GetTotalModuleCount", &ModuleMan::GetTotalModuleCount) + .def("IsModuleOfficial", &ModuleMan::IsModuleOfficial) + .def("IsModuleUserdata", &ModuleMan::IsModuleUserdata) + .def("GetFullModulePath", &ModuleMan::GetFullModulePath); +} + LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, MovableMan) { return luabind::class_("MovableManager") @@ -192,19 +207,11 @@ LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PostProcessMan) LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PresetMan) { return luabind::class_("PresetManager") - .def_readwrite("Modules", &PresetMan::m_pDataModules, luabind::return_stl_iterator) - - .def("LoadDataModule", (bool(PresetMan::*)(const std::string&)) & PresetMan::LoadDataModule) - .def("GetDataModule", &PresetMan::GetDataModule) - .def("GetModuleID", &PresetMan::GetModuleID) - .def("GetModuleIDFromPath", &PresetMan::GetModuleIDFromPath) - .def("GetTotalModuleCount", &PresetMan::GetTotalModuleCount) - .def("GetOfficialModuleCount", &PresetMan::GetOfficialModuleCount) .def("AddPreset", &PresetMan::AddEntityPreset) - .def("GetPreset", (const Entity* (PresetMan::*)(std::string, std::string, int)) & PresetMan::GetEntityPreset) - .def("GetPreset", (const Entity* (PresetMan::*)(std::string, std::string, std::string)) & PresetMan::GetEntityPreset) - .def("GetLoadout", (Actor * (PresetMan::*)(std::string, std::string, bool)) & PresetMan::GetLoadout, luabind::adopt(luabind::result)) - .def("GetLoadout", (Actor * (PresetMan::*)(std::string, int, bool)) & PresetMan::GetLoadout, luabind::adopt(luabind::result)) + .def("GetPreset", (const Entity* (PresetMan::*)(const std::string&, std::string, int) const) & PresetMan::GetEntityPreset) + .def("GetPreset", (const Entity* (PresetMan::*)(const std::string&, const std::string&, const std::string&) const) & PresetMan::GetEntityPreset) + .def("GetLoadout", (Actor * (PresetMan::*)(const std::string&, const std::string&, bool)) & PresetMan::GetLoadout, luabind::adopt(luabind::result)) + .def("GetLoadout", (Actor * (PresetMan::*)(const std::string&, int, bool)) & PresetMan::GetLoadout, luabind::adopt(luabind::result)) .def("GetRandomOfGroup", &PresetMan::GetRandomOfGroup) .def("GetRandomOfGroupInModuleSpace", &PresetMan::GetRandomOfGroupInModuleSpace) .def("GetEntityDataLocation", &PresetMan::GetEntityDataLocation) @@ -215,10 +222,7 @@ LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PresetMan) { .def("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup, luabind::adopt(luabind::result) + luabind::return_stl_iterator) .def("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup2, luabind::adopt(luabind::result) + luabind::return_stl_iterator) .def("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup3, luabind::adopt(luabind::result) + luabind::return_stl_iterator) - .def("ReloadAllScripts", &PresetMan::ReloadAllScripts) - .def("IsModuleOfficial", &PresetMan::IsModuleOfficial) - .def("IsModuleUserdata", &PresetMan::IsModuleUserdata) - .def("GetFullModulePath", &PresetMan::GetFullModulePath); + .def("ReloadAllScripts", &PresetMan::ReloadAllScripts); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PrimitiveMan) { diff --git a/Source/Main.cpp b/Source/Main.cpp index e2ee2153f..3ae7229ce 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -35,6 +35,7 @@ #include "MenuMan.h" #include "ConsoleMan.h" #include "SettingsMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "UInputMan.h" #include "PerformanceMan.h" @@ -66,6 +67,7 @@ void InitializeManagers() { ThreadMan::Construct(); TimerMan::Construct(); PresetMan::Construct(); + ModuleMan::Construct(); SettingsMan::Construct(); WindowMan::Construct(); LuaMan::Construct(); @@ -133,7 +135,7 @@ void DestroyManagers() { g_GUISound.Destroy(); g_AudioMan.Destroy(); g_MusicMan.Destroy(); - g_PresetMan.Destroy(); + g_ModuleMan.Destroy(); g_UInputMan.Destroy(); g_PostProcessMan.Destroy(); g_FrameMan.Destroy(); @@ -164,21 +166,20 @@ void HandleMainArgs(int argCount, char** argValue) { bool singleModuleSet = false; for (int i = 0; i < argCount;) { - std::string currentArg = argValue[i]; + std::string_view currentArg = argValue[i]; bool lastArg = i + 1 == argCount; if (currentArg == "-cout") { System::EnableLoggingToCLI(); } - if (currentArg == "-ext-validate") { System::EnableExternalModuleValidationMode(); } if (!lastArg && !singleModuleSet && currentArg == "-module") { - std::string moduleToLoad = argValue[++i]; - if (moduleToLoad.find(System::GetModulePackageExtension()) == moduleToLoad.length() - System::GetModulePackageExtension().length()) { - g_PresetMan.SetSingleModuleToLoad(moduleToLoad); + std::string_view moduleToLoad = argValue[++i]; + if (moduleToLoad.ends_with(System::GetModulePackageExtension())) { + g_ModuleMan.SetSingleModuleToLoad(moduleToLoad); singleModuleSet = true; } } @@ -462,7 +463,11 @@ int main(int argc, char** argv) { SDL_ShowCursor(SDL_ENABLE); } - g_PresetMan.LoadAllDataModules(); + int64_t moduleLoadStartTime = g_TimerMan.GetAbsoluteTime(); + g_ModuleMan.LoadAllDataModules(); + if (g_SettingsMan.IsMeasuringModuleLoadTime()) { + g_ConsoleMan.PrintString("SYSTEM: Module load duration is: " + std::to_string((g_TimerMan.GetAbsoluteTime() - moduleLoadStartTime) / 1000) + "ms"); + } if (!System::IsInExternalModuleValidationMode()) { // Load the different input device icons. This can't be done during UInputMan::Create() because the icon presets don't exist so we need to do this after modules are loaded. diff --git a/Source/Managers/ActivityMan.cpp b/Source/Managers/ActivityMan.cpp index 259a26be4..010de5c84 100644 --- a/Source/Managers/ActivityMan.cpp +++ b/Source/Managers/ActivityMan.cpp @@ -4,6 +4,7 @@ #include "CameraMan.h" #include "ConsoleMan.h" #include "PresetMan.h" +#include "ModuleMan.h" #include "UInputMan.h" #include "AudioMan.h" #include "WindowMan.h" @@ -85,7 +86,7 @@ bool ActivityMan::SaveCurrentGame(const std::string& fileName) { } // TODO, save to a zip instead of a directory - std::filesystem::create_directory(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/" + fileName); + std::filesystem::create_directory(g_ModuleMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/" + fileName); if (scene->SaveData(c_UserScriptedSavesModuleName + "/" + fileName + "/Save") < 0) { // This print is actually pointless because game will abort if it fails to save layer bitmaps. It stays here for now because in reality the game doesn't properly abort if the layer bitmaps fail to save. It is what it is. @@ -101,15 +102,15 @@ bool ActivityMan::SaveCurrentGame(const std::string& fileName) { // Become our own original preset, instead of being a copy of the Scene we got cloned from, so we don't still pick up the PlacedObjectSets from our parent when loading. modifiableScene->SetPresetName(fileName); - modifiableScene->MigrateToModule(g_PresetMan.GetModuleID(c_UserScriptedSavesModuleName)); + modifiableScene->MigrateToModule(g_ModuleMan.GetModuleID(c_UserScriptedSavesModuleName)); modifiableScene->SetSavedGameInternal(true); // Make sure the terrain is also treated as an original preset, otherwise it will screw up if we save then load then save again, since it'll try to be a CopyOf of itself. modifiableScene->GetTerrain()->SetPresetName(fileName); - modifiableScene->GetTerrain()->MigrateToModule(g_PresetMan.GetModuleID(c_UserScriptedSavesModuleName)); + modifiableScene->GetTerrain()->MigrateToModule(g_ModuleMan.GetModuleID(c_UserScriptedSavesModuleName)); // Block the main thread for a bit to let the Writer access the relevant data. - std::unique_ptr writer(std::make_unique(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/" + fileName + "/Save.ini")); + std::unique_ptr writer(std::make_unique(g_ModuleMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/" + fileName + "/Save.ini")); writer->NewPropertyWithValue("Activity", activity); // Pull all stuff from MovableMan into the Scene for saving, so existing Actors/ADoors are saved, without transferring ownership, so the game can continue. @@ -144,7 +145,7 @@ bool ActivityMan::SaveCurrentGame(const std::string& fileName) { bool ActivityMan::LoadAndLaunchGame(const std::string& fileName) { m_SaveGameTask.wait(); - std::string saveFilePath = g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/" + fileName + "/Save.ini"; + std::string saveFilePath = g_ModuleMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/" + fileName + "/Save.ini"; if (!std::filesystem::exists(saveFilePath)) { RTEError::ShowMessageBox("Game loading failed! Make sure you have a saved game called \"" + fileName + "\""); diff --git a/Source/Managers/AudioMan.cpp b/Source/Managers/AudioMan.cpp index a3a334701..efc743fbc 100644 --- a/Source/Managers/AudioMan.cpp +++ b/Source/Managers/AudioMan.cpp @@ -1,5 +1,6 @@ #include "AudioMan.h" +#include "ModuleMan.h" #include "CameraMan.h" #include "ConsoleMan.h" #include "FrameMan.h" @@ -8,7 +9,6 @@ #include "ActivityMan.h" #include "SoundContainer.h" #include "GUISound.h" -#include "PresetMan.h" #include "SoundSet.h" #include diff --git a/Source/Managers/FrameMan.cpp b/Source/Managers/FrameMan.cpp index 1d211651f..a670f96c8 100644 --- a/Source/Managers/FrameMan.cpp +++ b/Source/Managers/FrameMan.cpp @@ -2,7 +2,7 @@ #include "WindowMan.h" #include "PostProcessMan.h" -#include "PresetMan.h" +#include "ModuleMan.h" #include "PrimitiveMan.h" #include "PerformanceMan.h" #include "ActivityMan.h" @@ -469,7 +469,7 @@ void FrameMan::CreateNewNetworkPlayerBackBuffer(int player, int width, int heigh } bool FrameMan::LoadPalette(const std::string& palettePath) { - const std::string fullPalettePath = g_PresetMan.GetFullModulePath(palettePath); + const std::string fullPalettePath = g_ModuleMan.GetFullModulePath(palettePath); BITMAP* tempBitmap = load_bitmap(fullPalettePath.c_str(), m_Palette); RTEAssert(tempBitmap, ("Failed to load palette from bitmap with following path:\n\n" + fullPalettePath).c_str()); diff --git a/Source/Managers/FrameMan.h b/Source/Managers/FrameMan.h index b6da8605c..ac763b391 100644 --- a/Source/Managers/FrameMan.h +++ b/Source/Managers/FrameMan.h @@ -70,7 +70,7 @@ namespace RTE { BITMAP* GetOverlayBitmap32() const { return m_OverlayBitmap32.get(); } #pragma endregion -#pragma region Split - Screen Handling +#pragma region Split-Screen Handling /// Gets whether the screen is split horizontally across the screen, ie as two splitscreens one above the other. /// @return Whether or not screen has a horizontal split. bool GetHSplit() const { return m_HSplit; } diff --git a/Source/Managers/LuaMan.cpp b/Source/Managers/LuaMan.cpp index 8ecfb38ed..801217be7 100644 --- a/Source/Managers/LuaMan.cpp +++ b/Source/Managers/LuaMan.cpp @@ -3,6 +3,7 @@ #include "LuabindObjectWrapper.h" #include "LuaBindingRegisterDefinitions.h" #include "ThreadMan.h" +#include "ModuleMan.h" #include "System.h" #include "tracy/Tracy.hpp" @@ -176,6 +177,7 @@ void LuaStateWrapper::Initialize() { RegisterLuaBindingsOfType(ManagerLuaBindings, ConsoleMan), RegisterLuaBindingsOfType(ManagerLuaBindings, FrameMan), RegisterLuaBindingsOfType(ManagerLuaBindings, MetaMan), + RegisterLuaBindingsOfType(ManagerLuaBindings, ModuleMan), RegisterLuaBindingsOfType(ManagerLuaBindings, MovableMan), RegisterLuaBindingsOfType(ManagerLuaBindings, PerformanceMan), RegisterLuaBindingsOfType(ManagerLuaBindings, PostProcessMan), @@ -220,6 +222,7 @@ void LuaStateWrapper::Initialize() { luabind::globals(m_State)["PerformanceMan"] = &g_PerformanceMan; luabind::globals(m_State)["PostProcessMan"] = &g_PostProcessMan; luabind::globals(m_State)["PrimitiveMan"] = &g_PrimitiveMan; + luabind::globals(m_State)["ModuleMan"] = &g_ModuleMan; luabind::globals(m_State)["PresetMan"] = &g_PresetMan; luabind::globals(m_State)["AudioMan"] = &g_AudioMan; luabind::globals(m_State)["MusicMan"] = &g_MusicMan; @@ -249,8 +252,8 @@ void LuaStateWrapper::Initialize() { // Override "math.random" in the lua state to use RTETools MT19937 implementation. Preserve return types of original to not break all the things. "math.random = function(lower, upper) if lower ~= nil and upper ~= nil then return LuaMan:SelectRand(lower, upper); elseif lower ~= nil then return LuaMan:SelectRand(1, lower); else return LuaMan:PosRand(); end end\n" // Override "dofile"/"loadfile" to be able to account for Data/ or Mods/ directory. - "do local OriginalDoFile = dofile; dofile = function(filePath) filePath = PresetMan:GetFullModulePath(filePath); if filePath ~= '' then return OriginalDoFile(filePath); end end; end\n" - "do local OriginalLoadFile = loadfile; loadfile = function(filePath) filePath = PresetMan:GetFullModulePath(filePath); if filePath ~= '' then return OriginalLoadFile(filePath); end end; end\n" + "do local OriginalDoFile = dofile; dofile = function(filePath) filePath = ModuleMan:GetFullModulePath(filePath); if filePath ~= '' then return OriginalDoFile(filePath); end end; end\n" + "do local OriginalLoadFile = loadfile; loadfile = function(filePath) filePath = ModuleMan:GetFullModulePath(filePath); if filePath ~= '' then return OriginalLoadFile(filePath); end end; end\n" // Override "require" to be able to track loaded packages so we can clear them when scripts are reloaded. "_RequiredPackages = {};\n" "do local OriginalRequire = require; require = function(filePath) _RequiredPackages[filePath] = true; return OriginalRequire(filePath); end; end\n" @@ -447,8 +450,8 @@ void LuaStateWrapper::SetTempEntityVector(const std::vector& enti } void LuaStateWrapper::SetLuaPath(const std::string& filePath) { - const std::string moduleName = g_PresetMan.GetModuleNameFromPath(filePath); - const std::string moduleFolder = g_PresetMan.IsModuleOfficial(moduleName) ? System::GetDataDirectory() : System::GetModDirectory(); + const std::string moduleName = g_ModuleMan.GetModuleNameFromPath(filePath); + const std::string moduleFolder = g_ModuleMan.IsModuleOfficial(moduleName) ? System::GetDataDirectory() : System::GetModDirectory(); const std::string scriptPath = moduleFolder + moduleName + "/?.lua"; lua_getglobal(m_State, "package"); @@ -702,7 +705,7 @@ int LuaStateWrapper::RunScriptConditionalTestFunctionObject(const LuabindObjectW } int LuaStateWrapper::RunScriptFile(const std::string& filePath, bool consoleErrors, bool doInSandboxedEnvironment) { - const std::string fullScriptPath = g_PresetMan.GetFullModulePath(filePath); + const std::string fullScriptPath = g_ModuleMan.GetFullModulePath(filePath); if (fullScriptPath.empty()) { m_LastError = "Can't run a script file with an empty filepath!"; return -1; @@ -1008,7 +1011,7 @@ const std::vector* LuaMan::FileList(const std::string& path) { } bool LuaMan::FileExists(const std::string& path) { - std::string fullPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(path); + std::string fullPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(path); if (fullPath.find("..") == std::string::npos) { #ifndef _WIN32 fullPath = GetCaseInsensitiveFullPath(fullPath); @@ -1019,7 +1022,7 @@ bool LuaMan::FileExists(const std::string& path) { } bool LuaMan::DirectoryExists(const std::string& path) { - std::string fullPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(path); + std::string fullPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(path); if (fullPath.find("..") == std::string::npos) { #ifndef _WIN32 fullPath = GetCaseInsensitiveFullPath(fullPath); @@ -1052,7 +1055,7 @@ int LuaMan::FileOpen(const std::string& path, const std::string& accessMode) { return -1; } - std::string fullPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(path); + std::string fullPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(path); if (IsValidModulePath(fullPath)) { #ifdef _WIN32 FILE* file = fopen(fullPath.c_str(), accessMode.c_str()); @@ -1119,7 +1122,7 @@ void LuaMan::FileCloseAll() { } bool LuaMan::FileRemove(const std::string& path) { - std::string fullPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(path); + std::string fullPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(path); if (IsValidModulePath(fullPath)) { #ifndef _WIN32 fullPath = GetCaseInsensitiveFullPath(fullPath); @@ -1133,7 +1136,7 @@ bool LuaMan::FileRemove(const std::string& path) { } bool LuaMan::DirectoryCreate(const std::string& path, bool recursive) { - std::string fullPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(path); + std::string fullPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(path); if (fullPath.find("..") == std::string::npos) { #ifndef _WIN32 fullPath = GetCaseInsensitiveFullPath(fullPath); @@ -1151,7 +1154,7 @@ bool LuaMan::DirectoryCreate(const std::string& path, bool recursive) { } bool LuaMan::DirectoryRemove(const std::string& path, bool recursive) { - std::string fullPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(path); + std::string fullPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(path); if (fullPath.find("..") == std::string::npos) { #ifndef _WIN32 fullPath = GetCaseInsensitiveFullPath(fullPath); @@ -1171,8 +1174,8 @@ bool LuaMan::DirectoryRemove(const std::string& path, bool recursive) { } bool LuaMan::FileRename(const std::string& oldPath, const std::string& newPath) { - std::string fullOldPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(oldPath); - std::string fullNewPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(newPath); + std::string fullOldPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(oldPath); + std::string fullNewPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(newPath); if (IsValidModulePath(fullOldPath) && IsValidModulePath(fullNewPath)) { #ifndef _WIN32 fullOldPath = GetCaseInsensitiveFullPath(fullOldPath); @@ -1192,8 +1195,8 @@ bool LuaMan::FileRename(const std::string& oldPath, const std::string& newPath) } bool LuaMan::DirectoryRename(const std::string& oldPath, const std::string& newPath) { - std::string fullOldPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(oldPath); - std::string fullNewPath = System::GetWorkingDirectory() + g_PresetMan.GetFullModulePath(newPath); + std::string fullOldPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(oldPath); + std::string fullNewPath = System::GetWorkingDirectory() + g_ModuleMan.GetFullModulePath(newPath); if (fullOldPath.find("..") == std::string::npos && fullNewPath.find("..") == std::string::npos) { #ifndef _WIN32 fullOldPath = GetCaseInsensitiveFullPath(fullOldPath); diff --git a/Source/Managers/LuaMan.h b/Source/Managers/LuaMan.h index 5a11b4b1f..62502714c 100644 --- a/Source/Managers/LuaMan.h +++ b/Source/Managers/LuaMan.h @@ -335,7 +335,7 @@ namespace RTE { const std::unordered_map GetScriptTimings() const; #pragma endregion -#pragma region File I / O Handling +#pragma region File I/O Handling /// Returns a vector of all the directories in path, which is relative to the working directory. /// @param path Directory path relative to the working directory. /// @return A vector of the directories in path. diff --git a/Source/Managers/MetaMan.cpp b/Source/Managers/MetaMan.cpp index 5d2b8cbc2..008e03ebf 100644 --- a/Source/Managers/MetaMan.cpp +++ b/Source/Managers/MetaMan.cpp @@ -1,5 +1,6 @@ #include "MetaMan.h" #include "MetaSave.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "UInputMan.h" #include "ConsoleMan.h" @@ -115,7 +116,7 @@ int MetaMan::NewGame(int gameSize) { // Make sure they are all hidden at game start m_Scenes.back()->SetRevealed(false); // Make them unique presets in their own Data Module so they don't get referenced from the original presets they were made from - m_Scenes.back()->MigrateToModule(g_PresetMan.GetModuleID(METASAVEMODULENAME)); + m_Scenes.back()->MigrateToModule(g_ModuleMan.GetModuleID(METASAVEMODULENAME)); // Make them unexplored by all teams for (int team = Activity::TeamOne; team < m_TeamCount; ++team) m_Scenes.back()->FillUnseenLayer(Vector(4, 4), team, false); diff --git a/Source/Managers/ModuleMan.cpp b/Source/Managers/ModuleMan.cpp new file mode 100644 index 000000000..67c90f307 --- /dev/null +++ b/Source/Managers/ModuleMan.cpp @@ -0,0 +1,258 @@ +#include "ModuleMan.h" +#include "SettingsMan.h" +#include "ConsoleMan.h" + +#include "LoadingScreen.h" +#include "RTETools.h" +#include "System.h" + +using namespace RTE; + +const std::array ModuleMan::c_OfficialModules = {"Base.rte", "Coalition.rte", "Imperatus.rte", "Techion.rte", "Dummy.rte", "Ronin.rte", "Browncoats.rte", "Uzira.rte", "MuIlaak.rte", "Missions.rte"}; +const std::array, 3> ModuleMan::c_UserdataModules = {{{c_UserScenesModuleName, "User Scenes"}, + {c_UserConquestSavesModuleName, "Conquest Saves"}, + {c_UserScriptedSavesModuleName, "Scripted Activity Saves"}}}; + +void ModuleMan::Clear() { + m_LoadedDataModules.clear(); + m_UnloadedDataModules.clear(); + m_DisabledDataModuleNames.clear(); +} + +void ModuleMan::Destroy() { + for (const auto& [moduleID, dataModule]: m_LoadedDataModules) { + delete dataModule; + } + for (const auto& [moduleID, dataModule]: m_UnloadedDataModules) { + delete dataModule; + } + Clear(); +} + +bool ModuleMan::IsModuleEnabled(const std::string_view& moduleName) const { + return std::none_of(m_DisabledDataModuleNames.begin(), m_DisabledDataModuleNames.end(), + [&moduleName](const std::string_view& disabledModuleName) { + return disabledModuleName == moduleName; + }); +} + +bool ModuleMan::IsModuleOfficial(const std::string_view& moduleName) const { + return std::any_of(c_OfficialModules.begin(), c_OfficialModules.end(), + [&moduleName](const std::string_view& officialModuleName) { + return officialModuleName == moduleName; + }); +} + +bool ModuleMan::IsModuleUserdata(const std::string_view& moduleName) const { + return std::any_of(c_UserdataModules.begin(), c_UserdataModules.end(), + [&moduleName](const std::pair& userdataModuleEntry) { + return userdataModuleEntry.first == moduleName; + }); +} + +DataModule* ModuleMan::GetDataModule(int whichModule) { + if (whichModule < 0 || whichModule >= GetTotalModuleCount()) { + return nullptr; + } + + auto loadedModulesItr = std::find_if(m_LoadedDataModules.begin(), m_LoadedDataModules.end(), + [&whichModule](const auto& loadedModuleEntry) { + return loadedModuleEntry.first == whichModule; + }); + return (*loadedModulesItr).second; +} + +int ModuleMan::GetModuleID(const std::string_view& moduleName) const { + if (moduleName.empty()) { + return -1; + } + + auto loadedModulesItr = std::find_if(m_LoadedDataModules.begin(), m_LoadedDataModules.end(), + [&moduleName](const auto& loadedModuleEntry) { + return loadedModuleEntry.second->GetFileName() == moduleName; + }); + return (loadedModulesItr != m_LoadedDataModules.end()) ? (*loadedModulesItr).first : -1; +} + +std::string ModuleMan::GetModuleName(int whichModule) { + if (const DataModule* dataModule = GetDataModule(whichModule)) { + return dataModule->GetFileName(); + } + return ""; +} + +std::string ModuleMan::GetModuleNameFromPath(const std::string& dataPath) const { + if (dataPath.empty()) { + return ""; + } + size_t slashPos = dataPath.find_first_of("/\\"); + + // Include trailing slash in the substring range in case we need to match against the Data/Mods/Userdata directory. + std::string moduleName = (slashPos != std::string::npos) ? dataPath.substr(0, slashPos + 1) : dataPath; + + // Check if path starts with Data/ or the Mods/Userdata dir names and remove that part to get to the actual module name. + if (moduleName == System::GetDataDirectory() || moduleName == System::GetModDirectory() || moduleName == System::GetUserdataDirectory()) { + std::string shortenPath = dataPath.substr(slashPos + 1); + slashPos = shortenPath.find_first_of("/\\"); + moduleName = shortenPath.substr(0, slashPos + 1); + } + + if (!moduleName.empty() && moduleName.back() == '/') { + moduleName.pop_back(); + } + return moduleName; +} + +std::string ModuleMan::GetFullModulePath(const std::string& modulePath) const { + // Note: Mods may use mixed path separators, which aren't supported on non Windows systems. + // Since Windows supports both forward and backslash separators it's safe to replace all backslashes with forward slashes. + std::string modulePathGeneric = std::filesystem::path(modulePath).generic_string(); + std::replace(modulePathGeneric.begin(), modulePathGeneric.end(), '\\', '/'); + + const std::string pathTopDir = modulePathGeneric.substr(0, modulePathGeneric.find_first_of("/") + 1); + const std::string moduleName = GetModuleNameFromPath(modulePathGeneric); + + std::string moduleTopDir = System::GetModDirectory(); + + if (IsModuleOfficial(moduleName)) { + moduleTopDir = System::GetDataDirectory(); + } else if (IsModuleUserdata(moduleName)) { + moduleTopDir = System::GetUserdataDirectory(); + } + return (pathTopDir == moduleTopDir) ? modulePathGeneric : moduleTopDir + modulePathGeneric; +} + +bool ModuleMan::LoadDataModule(const std::string& moduleName, DataModule::DataModuleType moduleType, const ProgressCallback& progressCallback) { + if (moduleName.empty()) { + return false; + } + + // First check that we aren't trying to load another module with the same name. If not, check the unloaded map and load from there if it exists. + if (const DataModule* dataModule = GetDataModule(GetModuleID(moduleName)); dataModule) { + return true; + } else if (moduleType == DataModule::DataModuleType::Unofficial) { + auto unloadedModulesItr = std::find_if(m_UnloadedDataModules.begin(), m_UnloadedDataModules.end(), + [&moduleName](const auto& unloadedModuleEntry) { + return unloadedModuleEntry.second->GetFileName() == moduleName; + }); + if (unloadedModulesItr != m_UnloadedDataModules.end()) { + m_LoadedDataModules.emplace(*unloadedModulesItr); + m_UnloadedDataModules.erase(unloadedModulesItr); + return true; + } + } + + // Only instantiate it here, because it needs to be in the lists of this before being created. + DataModule* newModule = new DataModule(); + newModule->m_ModuleType = moduleType; + newModule->m_ModuleID = static_cast(m_LoadedDataModules.size()); + + m_LoadedDataModules.try_emplace(newModule->m_ModuleID, newModule); + + if (newModule->Create(moduleName, progressCallback) < 0) { + RTEAbort("Failed to find the " + moduleName + " Data Module!"); + return false; + } + return true; +} + +bool ModuleMan::UnloadDataModule(const std::string& moduleName) { + if (!IsModuleOfficial(moduleName) && !IsModuleUserdata(moduleName)) { + auto loadedModulesItr = std::find_if(m_LoadedDataModules.begin(), m_LoadedDataModules.end(), + [&moduleName](const auto& loadedModuleEntry) { + return loadedModuleEntry.second->GetFileName() == moduleName; + }); + + if (loadedModulesItr != m_LoadedDataModules.end()) { + m_UnloadedDataModules.emplace(*loadedModulesItr); + m_LoadedDataModules.erase(loadedModulesItr); + return true; + } + } else { + g_ConsoleMan.PrintString("Official and Userdata modules cannot be unloaded!"); + } + return false; +} + +bool ModuleMan::LoadAllDataModules() { + LoadOfficialModules(); + + // If a single module is specified, skip loading all other unofficial modules and load specified module only. + if (!m_SingleModuleToLoad.empty() && !IsModuleOfficial(m_SingleModuleToLoad) && !IsModuleUserdata(m_SingleModuleToLoad)) { + if (!LoadDataModule(m_SingleModuleToLoad, DataModule::DataModuleType::Unofficial, LoadingScreen::LoadingSplashProgressReport)) { + g_ConsoleMan.PrintString("ERROR: Failed to load DataModule \"" + m_SingleModuleToLoad + "\"! Only official modules were loaded!"); + g_ConsoleMan.SetEnabled(true); + return false; + } + } else { + FindAndExtractZippedModules(); + LoadUnofficialModules(); + + // Load userdata modules AFTER all other techs etc are loaded; might be referring to stuff in user mods. + return LoadUserdataModules(); + } + return true; +} + +void ModuleMan::LoadOfficialModules() { + for (const std::string& officialModule: c_OfficialModules) { + if (!LoadDataModule(officialModule, DataModule::DataModuleType::Official, LoadingScreen::LoadingSplashProgressReport)) { + RTEAbort("Failed to load official DataModule \"" + officialModule + "\"!"); + } + } +} + +bool ModuleMan::LoadUserdataModules() { + for (const auto& [userdataModuleName, userdataModuleFriendlyName]: c_UserdataModules) { + if (std::string userDataModulePath = System::GetWorkingDirectory() + System::GetUserdataDirectory() + userdataModuleName; !std::filesystem::exists(userDataModulePath)) { + if (Writer writer(userDataModulePath + "/Index.ini", false, true); writer.WriterOK()) { + DataModule newUserdataModule; + newUserdataModule.m_FriendlyName = userdataModuleFriendlyName; + newUserdataModule.m_ModuleType = DataModule::DataModuleType::Userdata; + + if (userdataModuleName == c_UserScenesModuleName) { + newUserdataModule.m_IgnoreMissingItems = true; + newUserdataModule.m_ScanFolderContents = true; + } + newUserdataModule.Save(writer); + writer.EndWrite(); + } + } + if (!LoadDataModule(userdataModuleName, DataModule::DataModuleType::Userdata, LoadingScreen::LoadingSplashProgressReport)) { + RTEAbort("Failed to load userdata DataModule \"" + userdataModuleName + "\"!\n\nThis generally shouldn't happen, but it looks like it did.\nPlease delete this module in the Userdata directory to rebuild it."); + } + } + return true; +} + +void ModuleMan::LoadUnofficialModules() { + std::vector modDirectoryFolders; + const std::string modDirectory = System::GetWorkingDirectory() + System::GetModDirectory(); + std::copy_if(std::filesystem::directory_iterator(modDirectory), std::filesystem::directory_iterator(), std::back_inserter(modDirectoryFolders), + [](auto dirEntry) { + return std::filesystem::is_directory(dirEntry); + }); + std::sort(modDirectoryFolders.begin(), modDirectoryFolders.end()); + + for (const std::filesystem::directory_entry& directoryEntry: modDirectoryFolders) { + std::string directoryEntryPath = directoryEntry.path().generic_string(); + if (directoryEntryPath.ends_with(".rte")) { + std::string moduleName = directoryEntryPath.substr(directoryEntryPath.find_last_of('/') + 1, std::string::npos); + if (g_ModuleMan.IsModuleEnabled(moduleName) && !IsModuleOfficial(moduleName) && !IsModuleUserdata(moduleName)) { + // NOTE: LoadDataModule can return false (especially since it may try to load already loaded modules, which is okay) and shouldn't cause stop, so we can ignore its return value here. + LoadDataModule(moduleName, DataModule::DataModuleType::Unofficial, LoadingScreen::LoadingSplashProgressReport); + } + } + } +} + +void ModuleMan::FindAndExtractZippedModules() const { + const std::string modDirectory = System::GetWorkingDirectory() + System::GetModDirectory(); + for (const std::filesystem::directory_entry& directoryEntry: std::filesystem::directory_iterator(modDirectory)) { + std::string zippedModulePath = std::filesystem::path(directoryEntry).generic_string(); + if (zippedModulePath.ends_with(System::GetZippedModulePackageExtension())) { + LoadingScreen::LoadingSplashProgressReport("Extracting Data Module from: " + directoryEntry.path().filename().generic_string(), true); + LoadingScreen::LoadingSplashProgressReport(System::ExtractZippedDataModule(zippedModulePath), true); + } + } +} diff --git a/Source/Managers/ModuleMan.h b/Source/Managers/ModuleMan.h new file mode 100644 index 000000000..6d24fd8b7 --- /dev/null +++ b/Source/Managers/ModuleMan.h @@ -0,0 +1,151 @@ +#ifndef _RTEMODULEMAN_ +#define _RTEMODULEMAN_ + +#include "Singleton.h" +#include "DataModule.h" + +#include + +#define g_ModuleMan ModuleMan::Instance() + +namespace RTE { + + /// Manager responsible for loading and unloading of DataModules. + class ModuleMan : public Singleton { + friend class SettingsMan; + friend struct ManagerLuaBindings; + + public: +#pragma region Creation + /// Constructor method used to instantiate a ModuleMan object in system memory. Initialize() should be called before using the object. + ModuleMan() { Clear(); } +#pragma endregion + +#pragma region Destruction + /// Destroys and resets (through Clear()) the ModuleMan object. + void Destroy(); +#pragma endregion + +#pragma region Getters and Setters + /// Sets the single module to be loaded after the official modules. This will be the ONLY non-official module to be loaded. + /// @param moduleName Name of the module to load. + void SetSingleModuleToLoad(const std::string_view& moduleName) { m_SingleModuleToLoad = moduleName; } + + /// Gets the total number of loaded DataModules. + /// @return The total number of loaded DataModules. + int GetTotalModuleCount() const { return static_cast(m_LoadedDataModules.size()); } + + /// Gets whether the specified mod is disabled in the settings. + /// @param moduleName Mod to check. + /// @return Whether the module is disabled via settings. + bool IsModuleEnabled(const std::string_view& moduleName) const; + + /// Gets whether a module name is of an official DataModule. + /// @param moduleName The name of the module to check, in the form "moduleName.rte" + /// @return True if the module is an official DataModule, otherwise false. + bool IsModuleOfficial(const std::string_view& moduleName) const; + + /// Gets whether a module name is of a userdata DataModule. + /// @param moduleName The name of the module to check, in the form "moduleName.rte" + /// @return True if the module is a userdata DataModule, otherwise false. + bool IsModuleUserdata(const std::string_view& moduleName) const; +#pragma endregion + +#pragma region DataModule Getters + /// Gets all the loaded DataModules. + /// @return Reference to the loaded DataModules map. + std::unordered_map& GetLoadedDataModules() { return m_LoadedDataModules; } + + /// Gets a specific loaded DataModule. + /// @param whichModule The ID of the module to get. + /// @return The requested DataModule. Ownership is NOT transferred! + DataModule* GetDataModule(int whichModule = 0); + + /// Gets a specific loaded DataModule. + /// @param whichModule The name of the DataModule to get, including the ".rte". + /// @return The requested DataModule. Ownership is NOT transferred! + DataModule* GetDataModule(const std::string_view& moduleName) { return GetDataModule(GetModuleID(moduleName)); } +#pragma endregion + +#pragma region DataModule Info Getters + /// Gets the DataModule names that are disabled and should not be loaded at startup. + /// @return Map of mods which are disabled. + std::unordered_set& GetDisabledDataModuleNames() { return m_DisabledDataModuleNames; } + + /// Gets the ID of a loaded DataModule. + /// @param moduleName The name of the DataModule to get the ID from, including the ".rte". + /// @return The requested ID. If no module of the name was found, -1 will be returned. + int GetModuleID(const std::string_view& moduleName) const; + + /// Gets the name of a specific loaded DataModule. + /// @param whichModule The ID of the module to get. + /// @return The requested DataModule name. + std::string GetModuleName(int whichModule = 0); + + /// Gets the ID of a loaded DataModule from a full data file path. + /// @param dataPath The full path to a data file inside the data module ID you want to get. + /// @return The requested ID. If no module of the name was found, -1 will be returned. + int GetModuleIDFromPath(const std::string& dataPath) const { return GetModuleID(GetModuleNameFromPath(dataPath)); } + + /// Gets the name of a loaded DataModule from a full data file path. + /// @param dataPath The full path to a data file inside the data module id you want to get. + /// @return The requested Name. If no module of the name was found, "" will be returned. + std::string GetModuleNameFromPath(const std::string& dataPath) const; + + /// Gets the full path to a DataModule including Data/, Userdata/ or Mods/. + /// @param modulePath The Path to be completed. + /// @return The complete path to the file, including Data/, Userdata/ or Mods/ based on whether or not it's part of an official module or userdata. + std::string GetFullModulePath(const std::string& modulePath) const; +#pragma endregion + +#pragma region Contrete Methods + /// Reads an entire DataModule and adds it to this. NOTE that official modules can't be loaded after any non-official ones! + /// @param moduleName The module name to read, e.g. "Base.rte". + /// @param moduleType The type of module that is being read. See DataModule::DataModuleType enumeration. + /// @param progressCallback A function pointer to a function that will be called and sent a string with information about the progress of this DataModule's creation. + /// @return Whether the DataModule was read and added correctly. + bool LoadDataModule(const std::string& moduleName, DataModule::DataModuleType moduleType, const ProgressCallback& progressCallback = nullptr); + + /// Unloads a DataModule by removing it from the loaded modules list. Does not actually erase it from memory. + /// @param moduleName The DataModule name to unload. + /// @return Whether the DataModule was successfully unloaded. + bool UnloadDataModule(const std::string& moduleName); + + /// Loads all the official data modules individually with LoadDataModule, then proceeds to look for any non-official modules and loads them as well. + bool LoadAllDataModules(); +#pragma endregion + + private: + static const std::array c_OfficialModules; //!< Array storing the names of all the official modules. + static const std::array, 3> c_UserdataModules; //!< Array storing the names of all the userdata modules. + + std::unordered_map m_LoadedDataModules; //!< Map of all loaded DataModules by their ID. Owned by this. + std::unordered_map m_UnloadedDataModules; //!< Map of DataModules that are loaded but disabled through the Mod Manager GUI. Treated as not loaded at all. + + std::unordered_set m_DisabledDataModuleNames; //!< The DataModule names that are disabled and should not be loaded at startup. + std::string m_SingleModuleToLoad; //!< Name of the single module to load after the official modules. + +#pragma region Module Loading Breakdown + /// Loads all the official DataModules individually with LoadDataModule. + void LoadOfficialModules(); + + /// Loads all the userdata DataModules individually with LoadDataModule. Creates any missing userdata DataModules on disk if necessary. + /// @return + bool LoadUserdataModules(); + + /// Loads all the unofficial DataModules individually with LoadDataModule. + void LoadUnofficialModules(); + + /// Iterates through the working directory to find any files matching the zipped module package extension (.rte.zip) and proceeds to extract them. + void FindAndExtractZippedModules() const; +#pragma endregion + + /// Clears all the member variables of this ModuleMan. + void Clear(); + + // Disallow the use of some implicit methods. + ModuleMan(const ModuleMan& reference) = delete; + ModuleMan& operator=(const ModuleMan& rhs) = delete; + }; +} // namespace RTE +#endif diff --git a/Source/Managers/PostProcessMan.cpp b/Source/Managers/PostProcessMan.cpp index 4222e8419..c3f1766bf 100644 --- a/Source/Managers/PostProcessMan.cpp +++ b/Source/Managers/PostProcessMan.cpp @@ -7,7 +7,7 @@ #include "ContentFile.h" #include "Matrix.h" -#include "PresetMan.h" +#include "ModuleMan.h" #include "GLCheck.h" #include "glad/gl.h" @@ -52,8 +52,8 @@ int PostProcessMan::Initialize() { InitializeGLPointers(); CreateGLBackBuffers(); - m_Blit8 = std::make_unique(g_PresetMan.GetFullModulePath("Base.rte/Shaders/Blit8.vert"), g_PresetMan.GetFullModulePath("Base.rte/Shaders/Blit8.frag")); - m_PostProcessShader = std::make_unique(g_PresetMan.GetFullModulePath("Base.rte/Shaders/PostProcess.vert"), g_PresetMan.GetFullModulePath("Base.rte/Shaders/PostProcess.frag")); + m_Blit8 = std::make_unique(g_ModuleMan.GetFullModulePath("Base.rte/Shaders/Blit8.vert"), g_ModuleMan.GetFullModulePath("Base.rte/Shaders/Blit8.frag")); + m_PostProcessShader = std::make_unique(g_ModuleMan.GetFullModulePath("Base.rte/Shaders/PostProcess.vert"), g_ModuleMan.GetFullModulePath("Base.rte/Shaders/PostProcess.frag")); // TODO: Make more robust and load more glows! ContentFile glowFile("Base.rte/Effects/Glows/YellowTiny.png"); m_YellowGlow = glowFile.GetAsBitmap(); diff --git a/Source/Managers/PresetMan.cpp b/Source/Managers/PresetMan.cpp index 5d7a6a599..decfc942a 100644 --- a/Source/Managers/PresetMan.cpp +++ b/Source/Managers/PresetMan.cpp @@ -1,719 +1,386 @@ -// Suppress compiler warning about unrecognized escape sequence on line 183 -#pragma warning(disable : 4129) - #include "PresetMan.h" -#include "DataModule.h" + +#include "LuaMan.h" +#include "ModuleMan.h" +#include "SettingsMan.h" +#include "ConsoleMan.h" + #include "SceneObject.h" #include "Loadout.h" #include "ACraft.h" -#include "LuaMan.h" -// #include "AHuman.h" -// #include "MOPixel.h" -// #include "SLTerrain.h" -// #include "AtomGroup.h" -// #include "Atom.h" - -#include "ConsoleMan.h" -#include "LoadingScreen.h" -#include "SettingsMan.h" #include "System.h" using namespace RTE; -const std::array PresetMan::c_OfficialModules = {"Base.rte", "Coalition.rte", "Imperatus.rte", "Techion.rte", "Dummy.rte", "Ronin.rte", "Browncoats.rte", "Uzira.rte", "MuIlaak.rte", "Missions.rte"}; -const std::array, 3> PresetMan::c_UserdataModules = {{{c_UserScenesModuleName, "User Scenes"}, - {c_UserConquestSavesModuleName, "Conquest Saves"}, - {c_UserScriptedSavesModuleName, "Scripted Activity Saves"}}}; - PresetMan::PresetMan() { Clear(); } -PresetMan::~PresetMan() { - Destroy(); -} - void PresetMan::Clear() { - m_pDataModules.clear(); - m_DataModuleIDs.clear(); - m_OfficialModuleCount = 0; - m_TotalGroupRegister.clear(); - m_LastReloadedEntityPresetInfo.fill(""); m_ReloadEntityPresetCalledThisUpdate = false; + m_LastReloadedEntityPresetInfo.fill(""); } -/* -int PresetMan::Save(Writer &writer) const -{ - writer << m_Actors.size(); - for (list::const_iterator itr = m_Actors.begin(); itr != m_Actors.end(); ++itr) - writer << **itr; - - writer << m_Particles.size(); - for (list::const_iterator itr2 = m_Particles.begin(); itr2 != m_Particles.end(); ++itr2) - writer << **itr2; - - return 0; +void PresetMan::RegisterGroup(const std::string& newGroup, int whichModule) const { + g_ModuleMan.GetDataModule(whichModule)->RegisterGroup(newGroup); } -*/ - -void PresetMan::Destroy() { - for (std::vector::iterator dmItr = m_pDataModules.begin(); dmItr != m_pDataModules.end(); ++dmItr) { - delete (*dmItr); - } - Clear(); -} - -bool PresetMan::LoadDataModule(const std::string& moduleName, bool official, bool userdata, const ProgressCallback& progressCallback) { - if (moduleName.empty()) { - return false; - } - // Make a lowercase-version of the module name so it makes it easier to compare to and find case-agnostically. - std::string lowercaseName = moduleName; - std::transform(lowercaseName.begin(), lowercaseName.end(), lowercaseName.begin(), ::tolower); - - // Make sure we don't add the same module twice. - for (const DataModule* dataModule: m_pDataModules) { - if (dataModule->GetFileName() == moduleName) { - return false; - } - } - - // Only instantiate it here, because it needs to be in the lists of this before being created. - DataModule* newModule = new DataModule(); - - // Official modules are stacked in the beginning of the vector. - if (official && !userdata) { - // Halt if an official module is being loaded after any non-official ones! - // RTEAssert(m_pDataModules.size() == m_OfficialModuleCount, "Trying to load an official module after a non-official one has been loaded!"); +bool PresetMan::GetGroups(std::list& groupList, int whichModule, const std::string& withType, bool moduleSpace) const { + bool foundAny = false; - // Find where the official modules end in the vector. - std::vector::iterator moduleItr = m_pDataModules.begin(); - size_t newModuleID = 0; - for (; newModuleID < m_OfficialModuleCount; ++newModuleID) { - moduleItr++; + if (whichModule < 0) { + for (const auto& [moduleName, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + foundAny = dataModule->GetGroupsWithType(groupList, withType) || foundAny; } - // Insert into after the last official one. - m_pDataModules.emplace(moduleItr, newModule); - m_DataModuleIDs.try_emplace(lowercaseName, newModuleID); - m_OfficialModuleCount++; } else { - if (userdata) { - newModule->SetAsUserdata(); - } - m_pDataModules.emplace_back(newModule); - m_DataModuleIDs.try_emplace(lowercaseName, m_pDataModules.size() - 1); - } + RTEAssert(whichModule < g_ModuleMan.GetTotalModuleCount(), "Trying to get from an out of bounds DataModule ID in PresetMan::GetGroups!"); - if (newModule->Create(moduleName, progressCallback) < 0) { - RTEAbort("Failed to find the " + moduleName + " Data Module!"); - return false; - } - newModule = nullptr; - return true; -} - -bool PresetMan::LoadAllDataModules() { - auto moduleLoadTimerStart = std::chrono::steady_clock::now(); - - // Destroy any possible loaded modules - Destroy(); - - FindAndExtractZippedModules(); - - // Load all the official modules first! - for (const std::string& officialModule: c_OfficialModules) { - if (!LoadDataModule(officialModule, true, false, LoadingScreen::LoadingSplashProgressReport)) { - return false; - } - } - - // If a single module is specified, skip loading all other unofficial modules and load specified module only. - if (!m_SingleModuleToLoad.empty() && !IsModuleOfficial(m_SingleModuleToLoad)) { - if (!LoadDataModule(m_SingleModuleToLoad, false, false, LoadingScreen::LoadingSplashProgressReport)) { - g_ConsoleMan.PrintString("ERROR: Failed to load DataModule \"" + m_SingleModuleToLoad + "\"! Only official modules were loaded!"); - return false; - } - } else { - std::vector modDirectoryFolders; - const std::string modDirectory = System::GetWorkingDirectory() + System::GetModDirectory(); - std::copy_if(std::filesystem::directory_iterator(modDirectory), std::filesystem::directory_iterator(), std::back_inserter(modDirectoryFolders), - [](auto dirEntry) { return std::filesystem::is_directory(dirEntry); }); - std::sort(modDirectoryFolders.begin(), modDirectoryFolders.end()); - - for (const std::filesystem::directory_entry& directoryEntry: modDirectoryFolders) { - std::string directoryEntryPath = directoryEntry.path().generic_string(); - if (directoryEntryPath.ends_with(".rte")) { - std::string moduleName = directoryEntryPath.substr(directoryEntryPath.find_last_of('/') + 1, std::string::npos); - if (!g_SettingsMan.IsModDisabled(moduleName) && !IsModuleOfficial(moduleName) && !IsModuleUserdata(moduleName)) { - int moduleID = GetModuleID(moduleName); - // NOTE: LoadDataModule can return false (especially since it may try to load already loaded modules, which is okay) and shouldn't cause stop, so we can ignore its return value here. - if (moduleID < 0 || moduleID >= GetOfficialModuleCount()) { - LoadDataModule(moduleName, false, false, LoadingScreen::LoadingSplashProgressReport); - } + if (moduleSpace) { + for (const auto& [moduleName, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + if (dataModule->IsOfficial()) { + foundAny = dataModule->GetGroupsWithType(groupList, withType) || foundAny; } } } - - // Load userdata modules AFTER all other techs etc are loaded; might be referring to stuff in user mods. - for (const auto& [userdataModuleName, userdataModuleFriendlyName]: c_UserdataModules) { - if (!std::filesystem::exists(System::GetWorkingDirectory() + System::GetUserdataDirectory() + userdataModuleName)) { - bool scanContentsAndIgnoreMissing = userdataModuleName == c_UserScenesModuleName; - DataModule::CreateOnDiskAsUserdata(userdataModuleName, userdataModuleFriendlyName, scanContentsAndIgnoreMissing, scanContentsAndIgnoreMissing); - } - if (!LoadDataModule(userdataModuleName, false, true, LoadingScreen::LoadingSplashProgressReport)) { - return false; - } - } - } - - if (g_SettingsMan.IsMeasuringModuleLoadTime()) { - std::chrono::milliseconds moduleLoadElapsedTime = std::chrono::duration_cast(std::chrono::steady_clock::now() - moduleLoadTimerStart); - g_ConsoleMan.PrintString("Module load duration is: " + std::to_string(moduleLoadElapsedTime.count()) + "ms"); - } - return true; -} - -const DataModule* PresetMan::GetDataModule(int whichModule) { - RTEAssert(whichModule >= 0 && whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); - return m_pDataModules[whichModule]; -} - -const std::string PresetMan::GetDataModuleName(int whichModule) { - RTEAssert(whichModule >= 0 && whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); - return m_pDataModules[whichModule]->GetFileName(); -} - -int PresetMan::GetModuleID(std::string moduleName) { - // Lower-case search name so we can match up against the already-lowercase names in m_DataModuleIDs - std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), ::tolower); - - // First pass - std::map::iterator itr = m_DataModuleIDs.find(moduleName); - if (itr != m_DataModuleIDs.end()) - return (*itr).second; - - // Try with or without the .rte on the end before giving up - int dotPos = moduleName.find_last_of('.'); - // Wasnt, so try adding it - if (dotPos == std::string::npos) - moduleName = moduleName + System::GetModulePackageExtension(); - // There was ".rte", so try to shave it off the name - else - moduleName = moduleName.substr(0, dotPos); - - // Try to find the module again! - itr = m_DataModuleIDs.find(moduleName); - if (itr != m_DataModuleIDs.end()) - return (*itr).second; - - /* No need to do this second pass now; we immediately do the case-agnostic search - // Add .rte and try to find the module in case-agnostic fashion - moduleName += ".rte"; - std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), ::tolower); - - itr = m_DataModuleIDs.find(moduleName); - if (itr != m_DataModuleIDs.end()) - return (*itr).second; - - // Try with or without the .rte on the end before giving up - dotPos = moduleName.find_last_of('.'); - // Wasnt, so try adding it - if (dotPos == string::npos) - moduleName = moduleName + System::GetModulePackageExtension(); - // There was ".rte", so try to shave it off the name - else - moduleName = moduleName.substr(0, dotPos); - - // Try to find the module again! - itr = m_DataModuleIDs.find(moduleName); - if (itr != m_DataModuleIDs.end()) - return (*itr).second; - */ - return -1; -} - -std::string PresetMan::GetModuleNameFromPath(const std::string& dataPath) const { - if (dataPath.empty()) { - return ""; - } - size_t slashPos = dataPath.find_first_of("/\\"); - - // Include trailing slash in the substring range in case we need to match against the Data/Mods/Userdata directory. - std::string moduleName = (slashPos != std::string::npos) ? dataPath.substr(0, slashPos + 1) : dataPath; - - // Check if path starts with Data/ or the Mods/Userdata dir names and remove that part to get to the actual module name. - if (moduleName == System::GetDataDirectory() || moduleName == System::GetModDirectory() || moduleName == System::GetUserdataDirectory()) { - std::string shortenPath = dataPath.substr(slashPos + 1); - slashPos = shortenPath.find_first_of("/\\"); - moduleName = shortenPath.substr(0, slashPos + 1); + foundAny = g_ModuleMan.GetDataModule(whichModule)->GetGroupsWithType(groupList, withType) || foundAny; } - - if (!moduleName.empty() && moduleName.back() == '/') { - moduleName.pop_back(); - } - return moduleName; -} - -int PresetMan::GetModuleIDFromPath(const std::string& dataPath) { - if (dataPath.empty()) { - return -1; - } - return GetModuleID(GetModuleNameFromPath(dataPath)); -} - -bool PresetMan::IsModuleOfficial(const std::string& moduleName) const { - return std::find(c_OfficialModules.begin(), c_OfficialModules.end(), moduleName) != c_OfficialModules.end(); -} - -bool PresetMan::IsModuleUserdata(const std::string& moduleName) const { - auto userdataModuleItr = std::find_if(c_UserdataModules.begin(), c_UserdataModules.end(), - [&moduleName](const auto& userdataModulesEntry) { - return userdataModulesEntry.first == moduleName; - }); - return userdataModuleItr != c_UserdataModules.end(); -} - -std::string PresetMan::GetFullModulePath(const std::string& modulePath) const { - // Note: Mods may use mixed path separators, which aren't supported on non Windows systems. - // Since Windows supports both forward and backslash separators it's safe to replace all backslashes with forward slashes. - std::string modulePathGeneric = std::filesystem::path(modulePath).generic_string(); - std::replace(modulePathGeneric.begin(), modulePathGeneric.end(), '\\', '/'); - - const std::string pathTopDir = modulePathGeneric.substr(0, modulePathGeneric.find_first_of("/") + 1); - const std::string moduleName = GetModuleNameFromPath(modulePathGeneric); - - std::string moduleTopDir = System::GetModDirectory(); - - if (IsModuleOfficial(moduleName)) { - moduleTopDir = System::GetDataDirectory(); - } else if (IsModuleUserdata(moduleName)) { - moduleTopDir = System::GetUserdataDirectory(); - } - return (pathTopDir == moduleTopDir) ? modulePathGeneric : moduleTopDir + modulePathGeneric; -} - -bool PresetMan::AddEntityPreset(Entity* pEntToAdd, int whichModule, bool overwriteSame, std::string readFromFile) { - RTEAssert(whichModule >= 0 && whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); - - return m_pDataModules[whichModule]->AddEntityPreset(pEntToAdd, overwriteSame, readFromFile); -} - -const Entity* PresetMan::GetEntityPreset(std::string type, std::string preset, int whichModule) { - RTEAssert(whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); - - const Entity* pRetEntity = 0; - - // Preset name might have "[ModuleName]/" preceding it, detect it here and select proper module! - int slashPos = preset.find_first_of('/'); - if (slashPos != std::string::npos) { - // Get the module ID and cut off the module specifier in the string - whichModule = GetModuleID(preset.substr(0, slashPos)); - preset = preset.substr(slashPos + 1); - } - - // All modules - if (whichModule < 0) { - // Search all modules - for (int i = 0; i < m_pDataModules.size() && !pRetEntity; ++i) - pRetEntity = m_pDataModules[i]->GetEntityPreset(type, preset); - } - // Specific module - else { - // Try to get it from the asked for module - pRetEntity = m_pDataModules[whichModule]->GetEntityPreset(type, preset); - - // If couldn't find it in there, then try all the official modules! - if (!pRetEntity) { - RTEAssert(m_OfficialModuleCount <= m_pDataModules.size(), "More official modules than modules loaded?!"); - for (int i = 0; i < m_OfficialModuleCount && !pRetEntity; ++i) { - pRetEntity = m_pDataModules[i]->GetEntityPreset(type, preset); - } - } + if (!groupList.empty() && (withType == "All" || withType.empty())) { + // DataModule::GetGroupsWithType doesn't sort and filter dupes when getting all groups, so do it here. + groupList.sort(); + groupList.unique(); } - - return pRetEntity; + return foundAny; } const Entity* PresetMan::GetEntityPreset(Reader& reader) { // The reader is aware of which DataModule it is reading within int whichModule = reader.GetReadModuleID(); - RTEAssert(whichModule >= 0 && whichModule < (int)m_pDataModules.size(), "Reader has an out of bounds module number!"); + RTEAssert(whichModule >= 0 && whichModule < g_ModuleMan.GetTotalModuleCount(), "Reader has an out of bounds module number!"); std::string ClassName; - const Entity::ClassInfo* pClass = 0; - Entity* pNewInstance = 0; - const Entity* pReturnPreset = 0; + const Entity::ClassInfo* pClass = nullptr; + Entity* newInstance = nullptr; + const Entity* pReturnPreset = nullptr; // Load class name and then preset instance reader >> ClassName; pClass = Entity::ClassInfo::GetClass(ClassName); + DataModule* dataModule = g_ModuleMan.GetDataModule(whichModule); + if (pClass && pClass->IsConcrete()) { // Instantiate - pNewInstance = pClass->NewInstance(); + newInstance = pClass->NewInstance(); // Get this before reading entity, since if it's the last one in its datafile, the stream will show the parent file instead std::string entityFilePath = reader.GetCurrentFilePath(); // Try to read in the preset instance's data from the reader - if (pNewInstance && pNewInstance->Create(reader, false) < 0) { + if (newInstance && newInstance->Create(reader, false) < 0) { // Abort loading if we can't create entity and it's not in a module that allows ignoring missing items. - if (!g_PresetMan.GetDataModule(whichModule)->GetIgnoreMissingItems()) - RTEAbort("Reading of a preset instance \"" + pNewInstance->GetPresetName() + "\" of class " + pNewInstance->GetClassName() + " failed in file " + reader.GetCurrentFilePath() + ", shortly before line #" + reader.GetCurrentFileLine()); - } else if (pNewInstance) { + if (!dataModule->GetIgnoreMissingItems()) { + RTEAbort("Reading of a preset instance \"" + newInstance->GetPresetName() + "\" of class " + newInstance->GetClassName() + " failed in file " + reader.GetCurrentFilePath() + ", shortly before line #" + reader.GetCurrentFileLine()); + } + } else if (newInstance) { // Try to add the instance to the collection - m_pDataModules[whichModule]->AddEntityPreset(pNewInstance, reader.GetPresetOverwriting(), entityFilePath); + dataModule->AddEntityPreset(newInstance, reader.GetPresetOverwriting(), entityFilePath); // Regardless of whether there was a collision or not, use whatever now exists in the instance map of that class and name - pReturnPreset = m_pDataModules[whichModule]->GetEntityPreset(pNewInstance->GetClassName(), pNewInstance->GetPresetName()); + pReturnPreset = dataModule->GetEntityPreset(newInstance->GetClassName(), newInstance->GetPresetName()); // If the instance wasn't found in the specific DataModule, try to find it in all the official ones instead if (!pReturnPreset) { - RTEAssert(m_OfficialModuleCount <= m_pDataModules.size(), "More official modules than modules loaded?!"); - for (int i = 0; i < m_OfficialModuleCount && !pReturnPreset; ++i) - pReturnPreset = m_pDataModules[i]->GetEntityPreset(pNewInstance->GetClassName(), pNewInstance->GetPresetName()); + for (const auto& [moduleID, loadedModule]: g_ModuleMan.GetLoadedDataModules()) { + if (loadedModule->IsOfficial()) { + pReturnPreset = loadedModule->GetEntityPreset(newInstance->GetClassName(), newInstance->GetPresetName()); + if (pReturnPreset) { + break; + } + } + } } } // Get rid of the read-in instance as its copy is now either added to the map, or discarded as there already was somehting in there of the same name. - delete pNewInstance; - pNewInstance = 0; - } else - pReturnPreset = 0; - + delete newInstance; + newInstance = nullptr; + } else { + pReturnPreset = nullptr; + } return pReturnPreset; } -Entity* PresetMan::ReadReflectedPreset(Reader& reader) { - // The reader is aware of which DataModule it's reading within - int whichModule = reader.GetReadModuleID(); - RTEAssert(whichModule >= 0 && whichModule < (int)m_pDataModules.size(), "Reader has an out of bounds module number!"); +const Entity* PresetMan::GetEntityPreset(const std::string& typeName, std::string presetName, int whichModule) const { + RTEAssert(whichModule < g_ModuleMan.GetTotalModuleCount(), "Tried to access an out of bounds data module number!"); - std::string ClassName; - const Entity::ClassInfo* pClass = 0; - Entity* pNewInstance = 0; - // Load class name and then preset instance - reader >> ClassName; - pClass = Entity::ClassInfo::GetClass(ClassName); + const Entity* pRetEntity = nullptr; - if (pClass && pClass->IsConcrete()) { - // Instantiate - pNewInstance = pClass->NewInstance(); + // Preset name might have "[ModuleName]/" preceding it, detect it here and select proper module! + int slashPos = presetName.find_first_of('/'); + if (slashPos != std::string::npos) { + // Get the module ID and cut off the module specifier in the string + whichModule = g_ModuleMan.GetModuleID(presetName.substr(0, slashPos)); + presetName = presetName.substr(slashPos + 1); + } - // Get this before reading entity, since if it's the last one in its datafile, the stream will show the parent file instead - std::string entityFilePath = reader.GetCurrentFilePath(); + // All modules + if (whichModule < 0) { + // Search all modules + for (const auto& [moduleID, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + pRetEntity = dataModule->GetEntityPreset(typeName, presetName); + if (pRetEntity) { + break; + } + } + } else { + // Try to get it from the asked for module + DataModule* dataModule = g_ModuleMan.GetDataModule(whichModule); + pRetEntity = dataModule ? dataModule->GetEntityPreset(typeName, presetName) : nullptr; - // Try to read in the preset instance's data from the reader - if (pNewInstance && pNewInstance->Create(reader, false) < 0) { - if (!g_PresetMan.GetDataModule(whichModule)->GetIgnoreMissingItems()) - RTEAbort("Reading of a preset instance \"" + pNewInstance->GetPresetName() + "\" of class " + pNewInstance->GetClassName() + " failed in file " + reader.GetCurrentFilePath() + ", shortly before line #" + reader.GetCurrentFileLine()); - } else { - // Try to add the instance to the collection. - // Note that we'll return this instance regardless of whether the adding was succesful or not - m_pDataModules[whichModule]->AddEntityPreset(pNewInstance, reader.GetPresetOverwriting(), entityFilePath); - return pNewInstance; + // If couldn't find it in there, then try all the official modules! + if (!pRetEntity) { + for (const auto& [moduleID, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + if (dataModule->IsOfficial()) { + pRetEntity = dataModule->GetEntityPreset(typeName, presetName); + if (pRetEntity) { + break; + } + } + } } } - return 0; + return pRetEntity; } -bool PresetMan::GetAllOfType(std::list& entityList, std::string type, int whichModule) { - if (type.empty()) - return false; +const Entity* PresetMan::GetEntityPreset(const std::string& typeName, const std::string& presetName, const std::string& whichModule) const { + return GetEntityPreset(typeName, presetName, g_ModuleMan.GetModuleID(whichModule)); +} - bool foundAny = false; +std::string PresetMan::GetEntityDataLocation(const std::string& type, const std::string& preset, int whichModule) const { + RTEAssert(whichModule < g_ModuleMan.GetTotalModuleCount(), "Tried to access an out of bounds data module number!"); + + std::string pRetPath = ""; + + auto& loadedModules = g_ModuleMan.GetLoadedDataModules(); // All modules if (whichModule < 0) { - // Send the list to each module - for (int i = 0; i < m_pDataModules.size(); ++i) - foundAny = m_pDataModules[i]->GetAllOfType(entityList, type) || foundAny; - } - // Specific module - else { - RTEAssert(whichModule < (int)m_pDataModules.size(), "Trying to get from an out of bounds DataModule ID!"); - foundAny = m_pDataModules[whichModule]->GetAllOfType(entityList, type); + // Search all modules + for (int i = 0; i < loadedModules.size() && pRetPath.empty(); ++i) { + pRetPath = loadedModules[i]->GetEntityDataLocation(type, preset); + } + } else { + // Try to get it from the asked for module + pRetPath = loadedModules[whichModule]->GetEntityDataLocation(type, preset); + + // If couldn't find it in there, then try all the official modules! + if (pRetPath.empty()) { + for (const auto& [moduleID, dataModule]: loadedModules) { + if (dataModule->IsOfficial()) { + pRetPath = dataModule->GetEntityDataLocation(type, preset); + if (!pRetPath.empty()) { + break; + } + } + } + } } - return foundAny; + return pRetPath; } -bool PresetMan::GetAllOfTypeInModuleSpace(std::list& entityList, std::string type, int whichModuleSpace) { - if (type.empty()) +bool PresetMan::GetAllOfType(std::list& entityList, const std::string& typeName, int whichModule, bool moduleSpace) const { + if (typeName.empty()) { return false; + } bool foundAny = false; - // All modules - if (whichModuleSpace < 0) - foundAny = GetAllOfType(entityList, type, whichModuleSpace); - // Specific module space - else { - // Get all entitys of the specific type in the official modules loaded before the specified one - for (int module = 0; module < m_OfficialModuleCount && module < whichModuleSpace; ++module) - foundAny = GetAllOfType(entityList, type, module) || foundAny; - - // Now get the groups of the specified module (official or not) - foundAny = GetAllOfType(entityList, type, whichModuleSpace) || foundAny; - } + if (whichModule < 0) { + for (const auto& [moduleName, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + foundAny = dataModule->GetAllOfType(entityList, typeName) || foundAny; + } + } else { + RTEAssert(whichModule < g_ModuleMan.GetTotalModuleCount(), "Trying to get from an out of bounds DataModule ID in PresetMan::GetAllOfType!"); + if (moduleSpace) { + for (const auto& [moduleName, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + if (dataModule->IsOfficial()) { + foundAny = dataModule->GetAllOfType(entityList, typeName) || foundAny; + } + } + } + foundAny = g_ModuleMan.GetDataModule(whichModule)->GetAllOfType(entityList, typeName); + } return foundAny; } -bool PresetMan::GetAllOfGroups(std::list& entityList, const std::vector& groups, const std::string& type, int whichModule) { - RTEAssert(!groups.empty(), "Looking for empty groups in PresetMan::GetAllOfGroups!"); +bool PresetMan::GetAllOfGroups(std::list& entityList, const std::vector& groupNames, const std::string& typeName, int whichModule, bool moduleSpace) const { + RTEAssert(!groupNames.empty(), "Looking for empty groups in PresetMan::GetAllOfGroups!"); + bool foundAny = false; if (whichModule < 0) { - for (DataModule* dataModule: m_pDataModules) { - foundAny = dataModule->GetAllOfGroups(entityList, groups, type) || foundAny; + for (const auto& [moduleName, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + foundAny = dataModule->GetAllOfGroups(entityList, groupNames, typeName) || foundAny; } } else { - RTEAssert(whichModule < (int)m_pDataModules.size(), "Trying to get from an out of bounds DataModule ID in PresetMan::GetAllOfGroups!"); - foundAny = m_pDataModules[whichModule]->GetAllOfGroups(entityList, groups, type); + RTEAssert(whichModule < g_ModuleMan.GetTotalModuleCount(), "Trying to get from an out of bounds DataModule ID in PresetMan::GetAllOfGroups!"); + + if (moduleSpace) { + for (const auto& [moduleName, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + if (dataModule->IsOfficial()) { + foundAny = dataModule->GetAllOfGroups(entityList, groupNames, typeName) || foundAny; + } + } + } + foundAny = g_ModuleMan.GetDataModule(whichModule)->GetAllOfGroups(entityList, groupNames, typeName); } return foundAny; } -bool PresetMan::GetAllNotOfGroups(std::list& entityList, const std::vector& groups, const std::string& type, int whichModule) { - if (groups.empty()) { +bool PresetMan::GetAllNotOfGroups(std::list& entityList, const std::vector& groupNames, const std::string& typeName, int whichModule) const { + if (groupNames.empty()) { RTEAbort("Looking for empty groups in PresetMan::GetAllNotOfGroups!"); - } else if (std::find(groups.begin(), groups.end(), "All") != groups.end()) { + } else if (std::find(groupNames.begin(), groupNames.end(), "All") != groupNames.end()) { RTEAbort("Trying to exclude all groups while looking for presets in PresetMan::GetAllNotOfGroups!"); } bool foundAny = false; if (whichModule < 0) { - for (DataModule* dataModule: m_pDataModules) { - foundAny = dataModule->GetAllNotOfGroups(entityList, groups, type) || foundAny; + for (const auto& [moduleID, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + foundAny = dataModule->GetAllNotOfGroups(entityList, groupNames, typeName) || foundAny; } } else { - RTEAssert(whichModule < (int)m_pDataModules.size(), "Trying to get from an out of bounds DataModule ID in PresetMan::GetAllNotOfGroups!"); - foundAny = m_pDataModules[whichModule]->GetAllNotOfGroups(entityList, groups, type); + RTEAssert(whichModule < g_ModuleMan.GetTotalModuleCount(), "Trying to get from an out of bounds DataModule ID in PresetMan::GetAllNotOfGroups!"); + foundAny = g_ModuleMan.GetDataModule(whichModule)->GetAllNotOfGroups(entityList, groupNames, typeName); } return foundAny; } -Entity* PresetMan::GetRandomOfGroup(std::string group, std::string type, int whichModule) { - RTEAssert(!group.empty(), "Looking for empty group!"); +Entity* PresetMan::GetRandomOfGroup(const std::string& groupName, const std::string& typeName, int whichModule, bool moduleSpace) { + RTEAssert(!groupName.empty(), "Looking for empty group in PresetMan::GetRandomOfGroup!"); - bool foundAny = false; - // The total list we'll select a random one from - std::list entityList; - - // All modules - if (whichModule < 0) { - // Get from all modules - for (int i = 0; i < m_pDataModules.size(); ++i) - // Send the list to each module, let them add - foundAny = m_pDataModules[i]->GetAllOfGroups(entityList, {group}, type) || foundAny; - } - // Specific one - else { - RTEAssert(whichModule < m_pDataModules.size(), "Trying to get from an out of bounds DataModule ID!"); - foundAny = m_pDataModules[whichModule]->GetAllOfGroups(entityList, {group}, type); - } + if (std::list entityList; GetAllOfGroups(entityList, {groupName}, typeName, whichModule, moduleSpace)) { + auto entityItr = entityList.begin(); + std::advance(entityItr, RandomNum(0, entityList.size() - 1)); - // Didn't find any of that group in those module(s) - if (!foundAny) - return 0; - - // Pick one and return it - int current = 0; - int selection = RandomNum(0, entityList.size() - 1); - for (std::list::iterator itr = entityList.begin(); itr != entityList.end(); ++itr) { - if (current == selection) - return (*itr); - current++; + return (*entityItr); } - - RTEAssert(0, "Tried selecting randomly but didn't?"); - return 0; + return nullptr; } -Entity* PresetMan::GetRandomBuyableOfGroupFromTech(std::string group, std::string type, int whichModule) { - RTEAssert(!group.empty(), "Looking for empty group!"); +Entity* PresetMan::GetRandomBuyableOfGroupFromTech(const std::string& groupName, const std::string& typeName, int whichModule) { + RTEAssert(!groupName.empty(), "Looking for empty group in PresetMan::GetRandomBuyableOfGroupFromTech!"); bool foundAny = false; - // The total list we'll select a random one from std::list entityList; std::list tempList; - // All modules if (whichModule < 0) { - for (DataModule* dataModule: m_pDataModules) { + for (const auto& [moduleID, dataModule]: g_ModuleMan.GetLoadedDataModules()) { if (dataModule->IsFaction()) { - foundAny = dataModule->GetAllOfGroups(tempList, {group}, type) || foundAny; + foundAny = dataModule->GetAllOfGroups(tempList, {groupName}, typeName) || foundAny; } } } else { - RTEAssert(whichModule < m_pDataModules.size(), "Trying to get from an out of bounds DataModule ID!"); - foundAny = m_pDataModules[whichModule]->GetAllOfGroups(tempList, {group}, type); + RTEAssert(whichModule < g_ModuleMan.GetTotalModuleCount(), "Trying to get from an out of bounds DataModule ID in PresetMan::GetRandomBuyableOfGroupFromTech!"); + foundAny = g_ModuleMan.GetDataModule(whichModule)->GetAllOfGroups(tempList, {groupName}, typeName); } - // Filter found entities, we need only buyables + // Filter found entities, we need only buyables. if (foundAny) { - // Do not filter anything if we're looking for brains - if (group == "Brains") { - foundAny = false; - for (std::list::iterator oItr = tempList.begin(); oItr != tempList.end(); ++oItr) { - entityList.push_back(*oItr); + foundAny = false; + + if (groupName == "Brains") { + // Do not filter anything if we're looking for brains. + for (Entity* entity: tempList) { + entityList.emplace_back(entity); foundAny = true; } } else { - foundAny = false; - for (std::list::iterator oItr = tempList.begin(); oItr != tempList.end(); ++oItr) { - SceneObject* pSObject = dynamic_cast(*oItr); - // Buyable and not brain? - if (pSObject && pSObject->IsBuyable() && !pSObject->IsBuyableInObjectPickerOnly() && !pSObject->IsInGroup("Brains")) { - entityList.push_back(*oItr); + for (Entity* entity: tempList) { + const SceneObject* entityAsSceneObject = dynamic_cast(entity); + if (entityAsSceneObject && entityAsSceneObject->IsBuyable() && !entityAsSceneObject->IsBuyableInObjectPickerOnly() && !entityAsSceneObject->IsInGroup("Brains")) { + entityList.emplace_back(entity); foundAny = true; } } } } - // Didn't find any of that group in those module(s) - if (!foundAny) - return 0; - - // Pick one and return it - int current = 0; - int selection = RandomNum(0, entityList.size() - 1); - - int totalWeight = 0; - for (std::list::iterator itr = entityList.begin(); itr != entityList.end(); ++itr) - totalWeight += (*itr)->GetRandomWeight(); - - // Use random weights if looking in specific modules - if (whichModule >= 0) { - if (totalWeight == 0) - return 0; - - selection = RandomNum(0, totalWeight - 1); - - for (std::list::iterator itr = entityList.begin(); itr != entityList.end(); ++itr) { - bool found = false; - int bucketCounter = 0; + if (foundAny) { + if (whichModule < 0) { + auto entityItr = entityList.begin(); + std::advance(entityItr, RandomNum(0, entityList.size() - 1)); + return (*entityItr); + } else { + // Use random weights if looking in specific modules. + int totalWeight = 0; + for (const Entity* entity: entityList) { + totalWeight += entity->GetRandomWeight(); + } + if (totalWeight == 0) { + return nullptr; + } - if ((*itr)->GetRandomWeight() > 0) { - while (bucketCounter < (*itr)->GetRandomWeight()) { - if (current == selection) { - found = true; - break; + int current = 0; + int selection = RandomNum(0, totalWeight - 1); + for (Entity* entity: entityList) { + bool found = false; + + if (entity->GetRandomWeight() > 0) { + int bucketCounter = 0; + + while (bucketCounter < entity->GetRandomWeight()) { + if (current == selection) { + found = true; + break; + } + current++; + bucketCounter++; } - - current++; - bucketCounter++; + } + if (found) { + return entity; } } - - if (found) - return (*itr); - } - } else { - for (std::list::iterator itr = entityList.begin(); itr != entityList.end(); ++itr) { - if (current == selection) - return (*itr); - - current++; } } - - RTEAssert(0, "Tried selecting randomly but didn't?"); - return 0; -} - -bool PresetMan::GetAllOfGroupInModuleSpace(std::list& entityList, std::string group, std::string type, int whichModuleSpace) { - RTEAssert(!group.empty(), "Looking for empty group!"); - - bool foundAny = false; - - // All modules - if (whichModuleSpace < 0) - foundAny = GetAllOfGroup(entityList, group, type, whichModuleSpace); - // Specific module space - else { - // Get all entitys of the specific group the official modules loaded before the specified one - for (int module = 0; module < m_OfficialModuleCount && module < whichModuleSpace; ++module) - foundAny = GetAllOfGroup(entityList, group, type, module) || foundAny; - - // Now get the groups of the specified module (official or not) - foundAny = GetAllOfGroup(entityList, group, type, whichModuleSpace) || foundAny; - } - - return foundAny; -} - -Entity* PresetMan::GetRandomOfGroupInModuleSpace(std::string group, std::string type, int whichModuleSpace) { - RTEAssert(!group.empty(), "Looking for empty group!"); - - bool foundAny = false; - // The total list we'll select a random one from - std::list entityList; - - // All modules - if (whichModuleSpace < 0) - foundAny = GetAllOfGroup(entityList, group, type, whichModuleSpace); - // Specific module space - else { - // Get all entitys of the specific group the official modules loaded before the specified one - for (int module = 0; module < m_OfficialModuleCount && module < whichModuleSpace; ++module) - foundAny = GetAllOfGroup(entityList, group, type, module) || foundAny; - - // Now get the groups of the specified module (official or not) - foundAny = GetAllOfGroup(entityList, group, type, whichModuleSpace) || foundAny; - } - - // Didn't find any of that group in those module(s) - if (!foundAny) - return 0; - - // Pick one and return it - int current = 0; - int selection = RandomNum(0, entityList.size() - 1); - for (std::list::iterator itr = entityList.begin(); itr != entityList.end(); ++itr) { - if (current == selection) - return (*itr); - current++; - } - - RTEAssert(0, "Tried selecting randomly but didn't?"); - return 0; + return nullptr; } -std::string PresetMan::GetEntityDataLocation(std::string type, std::string preset, int whichModule) { - RTEAssert(whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); +Actor* PresetMan::GetLoadout(const std::string& loadoutName, int whichModule, bool spawnDeliveryCraft) { + if (const Loadout* loadout = dynamic_cast(GetEntityPreset("Loadout", loadoutName, whichModule)); loadout) { + float costTally = 0.0F; - std::string pRetPath = ""; - - // All modules - if (whichModule < 0) { - // Search all modules - for (int i = 0; i < m_pDataModules.size() && pRetPath.empty(); ++i) - pRetPath = m_pDataModules[i]->GetEntityDataLocation(type, preset); - } - // Specific module - else { - // Try to get it from the asked for module - pRetPath = m_pDataModules[whichModule]->GetEntityDataLocation(type, preset); + // Create and pass along the first Actor and his inventory defined in the Loadout. + Actor* newActor = loadout->CreateFirstActor(whichModule, 1.0F, 1.0F, costTally); - // If couldn't find it in there, then try all the official modules! - if (pRetPath.empty()) { - RTEAssert(m_OfficialModuleCount <= m_pDataModules.size(), "More official modules than modules loaded?!"); - for (int i = 0; i < m_OfficialModuleCount && pRetPath.empty(); ++i) { - pRetPath = m_pDataModules[i]->GetEntityDataLocation(type, preset); + if (spawnDeliveryCraft) { + const ACraft* craftPreset = loadout->GetDeliveryCraft(); + if (craftPreset) { + ACraft* deliveryCraft = dynamic_cast(craftPreset->Clone()); + if (deliveryCraft) { + if (newActor) { + deliveryCraft->AddInventoryItem(newActor); + } + return deliveryCraft; + } } + } else { + return newActor; } } + return nullptr; +} - return pRetPath; +Actor* PresetMan::GetLoadout(const std::string& loadoutName, const std::string& moduleName, bool spawnDeliveryCraft) { + return GetLoadout(loadoutName, g_ModuleMan.GetModuleID(moduleName), spawnDeliveryCraft); } void PresetMan::ReloadAllScripts() const { g_LuaMan.ClearUserModuleCache(); - for (const DataModule* dataModule: m_pDataModules) { + for (const auto& [moduleID, dataModule]: g_ModuleMan.GetLoadedDataModules()) { dataModule->ReloadAllScripts(); } g_MovableMan.ReloadLuaScripts(); @@ -728,7 +395,7 @@ bool PresetMan::ReloadEntityPreset(const std::string& presetName, const std::str int moduleId = -1; if (moduleName != "") { - moduleId = GetModuleID(moduleName); + moduleId = g_ModuleMan.GetModuleID(moduleName); if (moduleId < 0) { g_ConsoleMan.PrintString("ERROR: Failed to find data module with name \"" + moduleName + "\" while attempting to reload an Entity preset with name \"" + presetName + "\" of type \"" + className + "\"!"); return false; @@ -755,7 +422,7 @@ bool PresetMan::ReloadEntityPreset(const std::string& presetName, const std::str Reader reader(presetDataLocation.c_str(), true); while (reader.NextProperty()) { reader.ReadPropName(); - g_PresetMan.GetEntityPreset(reader); + GetEntityPreset(reader); } g_ConsoleMan.PrintString("SYSTEM: Entity preset with name \"" + presetName + "\" of type \"" + className + "\" defined in \"" + actualDataModuleOfPreset + "\" was successfully reloaded"); @@ -777,143 +444,47 @@ bool PresetMan::QuickReloadEntityPreset() { return ReloadEntityPreset(m_LastReloadedEntityPresetInfo[0], m_LastReloadedEntityPresetInfo[1], m_LastReloadedEntityPresetInfo[2]); } -bool PresetMan::AddMaterialMapping(int fromID, int toID, int whichModule) { - RTEAssert(whichModule >= m_OfficialModuleCount && whichModule < m_pDataModules.size(), "Tried to make a material mapping in an offical or out-of-bounds DataModule!"); - - return m_pDataModules[whichModule]->AddMaterialMapping(fromID, toID); -} - -void PresetMan::RegisterGroup(std::string newGroup, int whichModule) { - RTEAssert(whichModule >= 0 && whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); - - // Register in the handy total list - m_TotalGroupRegister.push_back(newGroup); - m_TotalGroupRegister.sort(); - m_TotalGroupRegister.unique(); - - // Register in the specified module too - m_pDataModules[whichModule]->RegisterGroup(newGroup); -} - -bool PresetMan::GetGroups(std::list& groupList, int whichModule, std::string withType) const { - RTEAssert(whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); - - bool foundAny = false; - - // Asked for ALL groups ever registered - if (whichModule < 0) { - // Get all applicable groups - if (withType == "All" || withType.empty()) { - for (std::list::const_iterator gItr = m_TotalGroupRegister.begin(); gItr != m_TotalGroupRegister.end(); ++gItr) - groupList.push_back(*gItr); +bool PresetMan::AddMaterialMapping(uint8_t fromID, uint8_t toID, int whichModule) const { + // RTEAssert(whichModule >= g_ModuleMan.GetOfficialModuleCount() && whichModule < g_ModuleMan.GetTotalModuleCount(), "Tried to make a material mapping in an official or out-of-bounds DataModule!"); - foundAny = !m_TotalGroupRegister.empty(); - } - // Filter out groups without any entitys of the specified type - else { - for (int module = 0; module < (int)m_pDataModules.size(); ++module) - foundAny = m_pDataModules[module]->GetGroupsWithType(groupList, withType) || foundAny; - } + if (DataModule* dataModule = g_ModuleMan.GetDataModule(whichModule); dataModule->IsOfficial()) { + return dataModule->AddMaterialMapping(fromID, toID); } - // Asked for specific DataModule's groups - else if (!m_pDataModules[whichModule]->GetGroupRegister()->empty()) { - // Get ALL groups of that module - if (withType == "All" || withType.empty()) { - const std::list* pGroupList = m_pDataModules[whichModule]->GetGroupRegister(); - for (std::list::const_iterator gItr = pGroupList->begin(); gItr != pGroupList->end(); ++gItr) - groupList.push_back(*gItr); - - foundAny = !pGroupList->empty(); - } - // Get only modules that contain an entity of valid type - else - foundAny = m_pDataModules[whichModule]->GetGroupsWithType(groupList, withType) || foundAny; - } - - return foundAny; + return false; } -bool PresetMan::GetModuleSpaceGroups(std::list& groupList, int whichModule, std::string withType) const { - RTEAssert(whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); +bool PresetMan::AddEntityPreset(Entity* entityToAdd, int whichModule, bool overwriteSame, const std::string& readFromFile) const { + RTEAssert(whichModule >= 0 && whichModule < g_ModuleMan.GetTotalModuleCount(), "Tried to access an out of bounds data module number!"); - bool foundAny = false; - - // If all, then just copy the total register - if (whichModule < 0) { - // Just get all groups ever registered - if (withType == "All" || withType.empty()) { - for (std::list::const_iterator gItr = m_TotalGroupRegister.begin(); gItr != m_TotalGroupRegister.end(); ++gItr) - groupList.push_back(*gItr); - - foundAny = !m_TotalGroupRegister.empty(); - } - // Get type filtered groups from ALL data modules - else { - for (int module = 0; module < (int)m_pDataModules.size(); ++module) - foundAny = GetGroups(groupList, module, withType) || foundAny; - } - } - // Getting modulespace of specific module - else { - // Get all groups of the official modules that are loaded before the specified one - for (int module = 0; module < m_OfficialModuleCount && module < whichModule; ++module) - foundAny = GetGroups(groupList, module, withType) || foundAny; + return g_ModuleMan.GetDataModule(whichModule)->AddEntityPreset(entityToAdd, overwriteSame, readFromFile); +} - // Now get the groups of the specified module (official or not) - foundAny = GetGroups(groupList, whichModule, withType) || foundAny; +Entity* PresetMan::ReadReflectedPreset(Reader& reader) { + int whichModule = reader.GetReadModuleID(); + RTEAssert(whichModule >= 0 && whichModule < g_ModuleMan.GetTotalModuleCount(), "Reader has an out of bounds module number!"); - // Make sure there are no dupe groups in the list - groupList.sort(); - groupList.unique(); - } + std::string className; + const Entity::ClassInfo* classInfo = nullptr; + Entity* newInstance = nullptr; + reader >> className; + classInfo = Entity::ClassInfo::GetClass(className); - return foundAny; -} + if (classInfo && classInfo->IsConcrete()) { + // Instantiate + newInstance = classInfo->NewInstance(); -Actor* PresetMan::GetLoadout(std::string loadoutName, std::string module, bool spawnDropShip) { - return GetLoadout(loadoutName, GetModuleID(module), spawnDropShip); -} + // Get this before reading entity, since if it's the last one in its datafile, the stream will show the parent file instead. + std::string entityFilePath = reader.GetCurrentFilePath(); -Actor* PresetMan::GetLoadout(std::string loadoutName, int moduleNumber, bool spawnDropShip) { - if (spawnDropShip) { - // Find the Loadout that this Deployment is referring to - const Loadout* pLoadout = dynamic_cast(g_PresetMan.GetEntityPreset("Loadout", loadoutName, moduleNumber)); - if (pLoadout) { - const ACraft* pCraftPreset = pLoadout->GetDeliveryCraft(); - if (pCraftPreset) { - ACraft* pCraft = dynamic_cast(pCraftPreset->Clone()); - if (pCraft) { - float tally = 0; - // Create and pass along the first Actor and his inventory defined in the Loadout - Actor* pActor = pLoadout->CreateFirstActor(moduleNumber, 1, 1, tally); - // Set the position and team etc for the Actor we are prepping to spawn - if (pActor) - pCraft->AddInventoryItem(pActor); - } - return pCraft; + if (newInstance && newInstance->Create(reader, false) < 0) { + if (!g_ModuleMan.GetDataModule(whichModule)->GetIgnoreMissingItems()) { + RTEAbort("Reading of a preset instance \"" + newInstance->GetPresetName() + "\" of class " + newInstance->GetClassName() + " failed in file " + reader.GetCurrentFilePath() + ", shortly before line #" + reader.GetCurrentFileLine()); } - } - } else { - // Find the Loadout that this Deployment is referring to - const Loadout* pLoadout = dynamic_cast(g_PresetMan.GetEntityPreset("Loadout", loadoutName, moduleNumber)); - if (pLoadout) { - float tally = 0; - // Create and pass along the first Actor and his inventory defined in the Loadout - Actor* pReturnActor = pLoadout->CreateFirstActor(moduleNumber, 1, 1, tally); - // Set the position and team etc for the Actor we are prepping to spawn - return pReturnActor; - } - } - - return 0; -} - -void PresetMan::FindAndExtractZippedModules() const { - for (const std::filesystem::directory_entry& directoryEntry: std::filesystem::directory_iterator(System::GetWorkingDirectory() + System::GetModDirectory())) { - std::string zippedModulePath = std::filesystem::path(directoryEntry).generic_string(); - if (zippedModulePath.ends_with(System::GetZippedModulePackageExtension())) { - LoadingScreen::LoadingSplashProgressReport("Extracting Data Module from: " + directoryEntry.path().filename().generic_string(), true); - LoadingScreen::LoadingSplashProgressReport(System::ExtractZippedDataModule(zippedModulePath), true); + } else { + // Note that we'll return this instance regardless of whether the adding was successful or not. + g_ModuleMan.GetDataModule(whichModule)->AddEntityPreset(newInstance, reader.GetPresetOverwriting(), entityFilePath); + return newInstance; } } + return nullptr; } diff --git a/Source/Managers/PresetMan.h b/Source/Managers/PresetMan.h index b9f4f6bb2..8d1cfdf03 100644 --- a/Source/Managers/PresetMan.h +++ b/Source/Managers/PresetMan.h @@ -5,8 +5,8 @@ /// data@datarealms.com /// http://www.datarealms.com /// Inclusions of header files -#include "Entity.h" #include "Singleton.h" +#include "Entity.h" #include #include @@ -21,22 +21,17 @@ namespace RTE { class Actor; class DataModule; - /// The singleton manager of all presets of Entity:s in the RTE. - /// The presets serve as a respository of Entity instances with specific - /// and unique and initial runtime data. + /// The singleton manager of all presets of Entities in the RTE. + /// The presets serve as a repository of Entity instances with specific, unique and initial runtime data. class PresetMan : public Singleton { friend struct ManagerLuaBindings; - /// Public member variable, method and friend function declarations public: +#pragma region Creation /// Constructor method used to instantiate a PresetMan entity in system /// memory. Create() should be called before using the entity. PresetMan(); - /// Destructor method used to clean up a PresetMan entity before deletion - /// from system memory. - ~PresetMan(); - /// Makes the PresetMan entity ready for use. /// @return An error return value signaling sucess or any particular failure. /// Anything below 0 is an error signal. @@ -45,235 +40,160 @@ namespace RTE { /// Resets the entire PresetMan, including its inherited members, to /// their default settings or values. void Reset() { Clear(); } +#pragma endregion + +#pragma region Group Register Handling + /// Registers the existence of an Entity group, and in which module. + /// @param groupName The group to register. + /// @param whichModule The ID of the module in which at least one Entity of this group can be found. + void RegisterGroup(const std::string& groupName, int whichModule) const; - /// Destroys and resets (through Clear()) the PresetMan entity. - void Destroy(); - - /// Reads an entire DataModule and adds it to this. NOTE that official modules can't be loaded after any non-official ones! - /// @param moduleName The module name to read, e.g. "Base.rte". - /// @param official Whether this module is 'official' or third party. If official, it has to not have any name conflicts with any other official module. - /// @param userdata Whether this module is a userdata module. If true, will be treated as an unofficial module. - /// @param progressCallback A function pointer to a function that will be called and sent a string with information about the progress of this DataModule's creation. - /// @return Whether the DataModule was read and added correctly. - bool LoadDataModule(const std::string& moduleName, bool official, bool userdata = false, const ProgressCallback& progressCallback = nullptr); - - /// Reads an entire DataModule and adds it to this. NOTE that official modules can't be loaded after any non-official ones! - /// @param moduleName The module name to read, e.g. "Base.rte". - /// @return Whether the DataModule was read and added correctly. - bool LoadDataModule(const std::string& moduleName) { return LoadDataModule(moduleName, false); } - - /// Loads all the official data modules individually with LoadDataModule, then proceeds to look for any non-official modules and loads them as well. - /// @return - bool LoadAllDataModules(); - - /// Sets the single module to be loaded after the official modules. This will be the ONLY non-official module to be loaded. - /// @param moduleName Name of the module to load. - void SetSingleModuleToLoad(std::string moduleName) { m_SingleModuleToLoad = moduleName; } - - /// Gets a specific loaded DataModule - /// @param whichModule The ID of the module to get. (default: 0) - /// @return The requested DataModule. Ownership is NOT transferred! - const DataModule* GetDataModule(int whichModule = 0); - - /// Gets a name specific loaded DataModule - /// @param whichModule The ID of the module to get. (default: 0) - /// @return The requested DataModule name. - const std::string GetDataModuleName(int whichModule = 0); - - /// Gets the ID of a loaded DataModule. - /// @param moduleName The name of the DataModule to get the ID from, including the ".rte" - /// @return The requested ID. If no module of the name was found, -1 will be returned. - int GetModuleID(std::string moduleName); - - /// Gets the Name of a loaded DataModule, from a full data file path. - /// @param dataPath The full path to a data file inside the data module id you want to get. - /// @return The requested Name. If no module of the name was found, "" will be returned. - std::string GetModuleNameFromPath(const std::string& dataPath) const; - - /// Gets the ID of a loaded DataModule from a full data file path. - /// @param dataPath The full path to a data file inside the data module ID you want to get. - /// @return The requested ID. If no module of the name was found, -1 will be returned. - int GetModuleIDFromPath(const std::string& dataPath); - - /// Returns whether or not the module is vanilla. - /// @param moduleName The name of the module to check, in the form "[moduleName].rte" - /// @return True if the module is an official data module, otherwise false. - bool IsModuleOfficial(const std::string& moduleName) const; - - /// Returns whether or not the module is vanilla. - /// @param moduleName The name of the module to check, in the form "[moduleName].rte" - /// @return True if the module is a listed user data module, otherwise false. - bool IsModuleUserdata(const std::string& moduleName) const; - - /// Returns the Full path to the module including Data/, Userdata/ or Mods/. - /// @param modulePath The Path to be completed. - /// @return The complete path to the file, including Data/, Userdata/ or Mods/ based on whether or not it's part of an official module or userdata. - std::string GetFullModulePath(const std::string& modulePath) const; - - /// Gets the total number of modules loaded so far, official or not. - /// @return The number of modules loaded so far, both official and non. - int GetTotalModuleCount() { return m_pDataModules.size(); } - - /// Gets the total number of OFFICIAL modules loaded so far. - /// @return The number of official modules loaded so far. - int GetOfficialModuleCount() { return m_OfficialModuleCount; } - - /// Adds an Entity instance's pointer and name associations to the - /// internal list of already read in Entity:s. Ownership is NOT transferred! - /// If there already is an instance defined, nothing happens. If there - /// is not, a clone is made of the passed-in Entity and added to the library. - /// @param pEntToAdd A pointer to the Entity derived instance to add. It should be created - /// from a Reader. Ownership is NOT transferred! - /// @param whichModule Which module to add the entity to. (default: 0) - /// @param overwriteSame Whether to overwrite if an instance of the EXACT same TYPE and name (default: false) - /// was found. If one of the same name but not the exact type, false - /// is returned regardless and nothing will have been added. - /// @param readFromFile The file this instance was read from, or where it should be written. (default: "Same") - /// If "Same" is passed as the file path read from, an overwritten instance - /// will keep the old one's file location entry. - /// @return Whether or not a copy of the passed-in instance was successfully inserted - /// into the module. False will be returned if there already was an instance - /// of that class and instance name inserted previously, unless overwritten. - bool AddEntityPreset(Entity* pEntToAdd, int whichModule = 0, bool overwriteSame = false, std::string readFromFile = "Same"); - - /// Gets a previously read in (defined) Entity, by type and instance name. - /// @param type The type name of the derived Entity. Ownership is NOT transferred! - /// @param preset The instance name of the derived Entity instance. - /// @param whichModule Which module to try to get the entity from. If it's not found there, (default: -1) - /// the official modules will be searched also. -1 means search ALL modules! - /// @return A pointer to the requested Entity instance. 0 if no Entity with that - /// derived type or instance name was found. Ownership is NOT transferred! - const Entity* GetEntityPreset(std::string type, std::string preset, int whichModule = -1); - // Helper for passing in string module name instead of ID - const Entity* GetEntityPreset(std::string type, std::string preset, std::string module) { return GetEntityPreset(type, preset, GetModuleID(module)); } - - /// Reads an instance of an Entity that will be used as preset - /// to later on be used to generate more instances of the same state. - /// Will check if there was already one of the same class and instance - /// name read in previously, and will return that one if found, or - /// add the newly read in one to this PresetMan's list if not found to - /// exist there previously. Ownership is NOT transferred! - /// @param reader The Reader which is about to read in an instance reference. It'll make - /// this look in the same module as it's reading from. - /// @return A const pointer to the Entity instance read in. 0 if there was an - /// error, or the instance name was 'None'. Ownership is NOT transferred! + /// Fills out a list with all groups registered in a specific module. + /// @param groupList The list that all found groups will be added to. OWNERSHIP IS NOT TRANSFERRED! + /// @param whichModule Which module to get the groups for. -1 means get ALL groups ever registered. + /// @param withType Pass a type name here and only groups with Entities of that type will be included. "All" means don't consider what types are in the groups. + /// @param moduleSpace Whether to get all groups in official modules, in addition to the specified module. + /// @return Whether any groups were found and added to the list. + bool GetGroups(std::list& groupList, int whichModule = -1, const std::string& withType = "All", bool moduleSpace = false) const; + + /// Fills out a list with all groups registered in all official modules, PLUS a specific non-official module as well. + /// @param groupList The list that all found groups will be added to. OWNERSHIP IS NOT TRANSFERRED! + /// @param whichModule Which module to get the groups for, in addition to all groups in official modules. -1 means get ALL groups ever registered. + /// @param withType Pass a type name here and only groups with Entities of that type will be included. "All" means don't consider what types are in the groups. + /// @return Whether any groups were found and added to the list. + bool GetModuleSpaceGroups(std::list& groupList, int whichModuleSpace, const std::string& withType = "All") const { return GetGroups(groupList, whichModuleSpace, withType, true); } +#pragma endregion + +#pragma region Preset Getters + /// Reads an instance of an Entity that will be used as preset to later on be used to generate more instances of the same state. Ownership is NOT transferred! + /// Will check if there was already one of the same class and instance name read in previously, and will return that one if found, or add the newly read in one to this PresetMan's list if not found to exist there previously. + /// @param reader The Reader which is about to read in an instance reference. It'll make this look in the same module as it's reading from. + /// @return A pointer to const of the Entity instance read in. nullptr if there was an error, or the instance name was 'None'. Ownership is NOT transferred! const Entity* GetEntityPreset(Reader& reader); - /// Reads a preset of an Entity and tries to add it to the list of - /// read-in instances. Regardless of whether there is a name collision, - /// the read-in preset will be returned, ownership TRANSFERRED! - /// @param reader The Reader which is about to read in a preset. - /// @return A pointer to the Entity preset read in. 0 if there was an - /// error, or the instance name was 'None'. Ownership IS transferred! - Entity* ReadReflectedPreset(Reader& reader); + /// Gets a previously read in (defined) Entity, by type and instance name. Ownership is NOT transferred! + /// @param typeName The type name of the derived Entity. + /// @param presetName The instance name of the derived Entity instance. + /// @param whichModule Which module to try to get the entity from. If it's not found there, the official modules will be searched also. -1 means search ALL modules! + /// @return A pointer to const of the requested Entity instance. nullptr if no Entity with that derived type or instance name was found. Ownership is NOT transferred! + const Entity* GetEntityPreset(const std::string& typeName, std::string presetName, int whichModule = -1) const; + + /// Gets a previously read in (defined) Entity, by type and instance name. Ownership is NOT transferred! + /// @param typeName The type name of the derived Entity. + /// @param presetName The instance name of the derived Entity instance. + /// @param whichModule Which module to try to get the entity from. If it's not found there, the official modules will be searched also. + /// @return A pointer to const of the requested Entity instance. nullptr if no Entity with that derived type or instance name was found. Ownership is NOT transferred! + const Entity* GetEntityPreset(const std::string& typeName, const std::string& presetName, const std::string& whichModule) const; + + /// Gets the data file path of a previously read in (defined) Entity. Ownership is NOT transferred! + /// @param typeName The type name of the derived Entity. + /// @param presetName The preset name of the derived Entity preset. + /// @param whichModule Which module to try to get the entity from. If it's not found there, the official modules will be searched also. + /// @return The file path of the data file that the specified Entity was read from. If no Entity of that description was found, an empty string is returned. + std::string GetEntityDataLocation(const std::string& typeName, const std::string& presetName, int whichModule) const; +#pragma endregion + +#pragma region Preset-by-Type Getters + /// Adds to a list all previously read in (defined) Entities, by type. + /// @param entityList Reference to a list which will get all matching Entities added to it. Ownership of the list or the Entities placed in it are NOT transferred! + /// @param typeName The type name of the Entities to get. + /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). + /// @param moduleSpace Whether to get all instances in official modules, in addition to the specified module. + /// @return Whether any Entities were found and added to the list. + bool GetAllOfType(std::list& entityList, const std::string& typeName, int whichModule = -1, bool moduleSpace = false) const; - /// Adds to a list all previously read in (defined) Entitys, by type. - /// @param entityList Reference to a list which will get all matching Entity:s added to it. - /// @param type Ownership of the list or the Entitys placed in it are NOT transferred! - /// @param whichModule The type name of the Entitys you want. (default: -1) - /// Whether to only get those of one specific DataModule (0-n), or all (-1). - /// @return Whether any Entity:s were found and added to the list. - bool GetAllOfType(std::list& entityList, std::string type, int whichModule = -1); - - /// Adds to a list all previously read in (defined) Entitys which are - /// of a specific type, and only exist in a specific module space. - /// @param entityList Reference to a list which will get all matching Entity:s added to it. - /// @param type Ownership of the list or the Entitys placed in it are NOT transferred! - /// @param whichModuleSpace The type name of the Entitys you want. - /// Which module to get the instances for, in addition to all groups in - /// official modules loaded earlier than the one specified here. -1 means - /// get ALL groups ever reg'd. - /// @return Whether any Entity:s were found and added to the list. - bool GetAllOfTypeInModuleSpace(std::list& entityList, std::string type, int whichModuleSpace); + /// Adds to a list all previously read in (defined) Entities which are of a specific type, and only exist in a specific module space. + /// @param entityList Reference to a list which will get all matching Entities added to it. Ownership of the list or the Entities placed in it are NOT transferred! + /// @param typeName The type name of the Entities to get. + /// @param whichModuleSpace Which module to get the instances for, in addition to all groups in official modules. -1 means get ALL groups ever registered. + /// @return Whether any Entities were found and added to the list. + bool GetAllOfTypeInModuleSpace(std::list& entityList, const std::string& typeName, int whichModuleSpace) const { return GetAllOfType(entityList, typeName, whichModuleSpace, true); } +#pragma endregion +#pragma region Preset-by-Group Getters /// Adds to a list all previously read in (defined) Entities which are associated with a specific group. /// @param entityList Reference to a list which will get all matching Entities added to it. Ownership of the list or the Entities placed in it are NOT transferred! - /// @param group The group to look for. "All" will look in all. - /// @param type The name of the least common denominator type of the Entities you want. "All" will look at all types. + /// @param groupName The group to look for. "All" will look in all. + /// @param typeName The name of the least common denominator type of the Entities you want. "All" will look at all types. /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). /// @return Whether any Entities were found and added to the list. - bool GetAllOfGroup(std::list& entityList, const std::string& group, const std::string& type = "All", int whichModule = -1) { return GetAllOfGroups(entityList, {group}, type, whichModule); } + bool GetAllOfGroup(std::list& entityList, const std::string& groupName, const std::string& typeName = "All", int whichModule = -1) const { return GetAllOfGroups(entityList, {groupName}, typeName, whichModule); } + + /// Adds to a list all previously read in (defined) Entities which are associated with a specific group, and only exist in a specific module space. + /// @param entityList Reference to a list which will get all matching Entities added to it. Ownership of the list or the Entities placed in it are NOT transferred! + /// @param groupName The group to look for. "All" will look in all. + /// @param typeName The name of the least common denominator type of the Entities to get. "All" will look at all types. + /// @param whichModuleSpace Which module to get the instances for, in addition to all groups in official modules. -1 means get ALL groups ever registered. + /// @return Whether any Entities were found and added to the list. + bool GetAllOfGroupInModuleSpace(std::list& entityList, const std::string& groupName, const std::string& typeName, int whichModuleSpace) const { return GetAllOfGroups(entityList, {groupName}, typeName, whichModuleSpace, true); } /// Adds to a list all previously read in (defined) Entities which are associated with several specific groups. /// @param entityList Reference to a list which will get all matching Entities added to it. Ownership of the list or the Entities placed in it are NOT transferred! - /// @param groups The groups to look for. "All" will look in all. - /// @param type The name of the least common denominator type of the Entities you want. "All" will look at all types. + /// @param groupNames The groups to look for. "All" will look in all. + /// @param typeName The name of the least common denominator type of the Entities you want. "All" will look at all types. /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). + /// @param moduleSpace Whether to get all instances in official modules, in addition to the specified module. /// @return Whether any Entities were found and added to the list. - bool GetAllOfGroups(std::list& entityList, const std::vector& groups, const std::string& type = "All", int whichModule = -1); + bool GetAllOfGroups(std::list& entityList, const std::vector& groupNames, const std::string& typeName = "All", int whichModule = -1, bool moduleSpace = false) const; /// Adds to a list all previously read in (defined) Entities which are not associated with a specific group. /// @param entityList Reference to a list which will get all matching Entities added to it. Ownership of the list or the Entities placed in it are NOT transferred! - /// @param group The group to exclude. - /// @param type The name of the least common denominator type of the Entities you want. "All" will look at all types. + /// @param groupName The group to exclude. + /// @param typeName The name of the least common denominator type of the Entities you want. "All" will look at all types. /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). /// @return Whether any Entities were found and added to the list. - bool GetAllNotOfGroup(std::list& entityList, const std::string& group, const std::string& type = "All", int whichModule = -1) { return GetAllNotOfGroups(entityList, {group}, type, whichModule); } + bool GetAllNotOfGroup(std::list& entityList, const std::string& groupName, const std::string& typeName = "All", int whichModule = -1) const { return GetAllNotOfGroups(entityList, {groupName}, typeName, whichModule); } /// Adds to a list all previously read in (defined) Entities which are not associated with several specific groups. /// @param entityList Reference to a list which will get all matching Entities added to it. Ownership of the list or the Entities placed in it are NOT transferred! - /// @param groups The groups to exclude. - /// @param type The name of the least common denominator type of the Entities you want. "All" will look at all types. + /// @param groupNames The groups to exclude. + /// @param typeName The name of the least common denominator type of the Entities you want. "All" will look at all types. /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). /// @return Whether any Entities were found and added to the list. - bool GetAllNotOfGroups(std::list& entityList, const std::vector& groups, const std::string& type = "All", int whichModule = -1); - - /// Returns a previously read in (defined) Entity which is randomly - /// selected from a specific group. - /// @param group The group to randomly select an Entity from. "All" will look in all. - /// @param type The name of the least common denominator type of the Entitys you want. (default: "All") - /// "All" will look at all types. - /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). (default: -1) + bool GetAllNotOfGroups(std::list& entityList, const std::vector& groupNames, const std::string& typeName = "All", int whichModule = -1) const; +#pragma endregion + +#pragma region Random Preset Getters + /// Returns a previously read in (defined) Entity which is randomly selected from a specific group. + /// @param groupName The group to randomly select an Entity from. "All" will look in all. + /// @param typeName The name of the least common denominator type of the Entity to get. "All" will look at all types. + /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). + /// @param moduleSpace Whether to get all instances in official modules, in addition to the group in the specified module. /// @return The Entity preset that was randomly selected. Ownership is NOT transferred! - Entity* GetRandomOfGroup(std::string group, std::string type = "All", int whichModule = -1); - - /// Returns a previously read in (defined) Entity which is randomly - /// selected from a specific group only if it belongs to some tech. - /// @param group The group to randomly select an Entity from. "All" will look in all. - /// @param type The name of the least common denominator type of the Entitys you want. (default: "All") - /// "All" will look at all types. - /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1) (default: -1) - /// or all modules uncluding non-tech ones. + Entity* GetRandomOfGroup(const std::string& groupName, const std::string& typeName = "All", int whichModule = -1, bool moduleSpace = false); + + /// Returns a previously read in (defined) Entity which is associated with a specific group, randomly selected and only exist in a specific module space. + /// @param groupName The group to randomly select an Entity from. "All" will look in all. + /// @param typeName The name of the least common denominator type of the Entity to get. "All" will look at all types. + /// @param whichModuleSpace Which module to get the instances for, in addition to all groups in official modules. -1 means get ALL groups ever registered. /// @return The Entity preset that was randomly selected. Ownership is NOT transferred! - Entity* GetRandomBuyableOfGroupFromTech(std::string group, std::string type = "All", int whichModule = -1); - - /// Adds to a list all previously read in (defined) Entitys which are - /// associated with a specific group, and only exist in a specific module - /// space. - /// @param entityList Reference to a list which will get all matching Entity:s added to it. - /// @param group Ownership of the list or the Entitys placed in it are NOT transferred! - /// @param type The group to look for. "All" will look in all. - /// @param whichModuleSpace The name of the least common denominator type of the Entitys you want. - /// "All" will look at all types. - /// Which module to get the instances for, in addition to all groups in - /// official modules loaded earlier than the one specified here. -1 means - /// get ALL groups ever reg'd. - /// @return Whether any Entity:s were found and added to the list. - bool GetAllOfGroupInModuleSpace(std::list& entityList, std::string group, std::string type, int whichModuleSpace); - - /// Returns a previously read in (defined) Entity which is associated with - /// a specific group, randomly selected and only exist in a specific module - /// space. - /// @param group Ownership of the list or the Entitys placed in it are NOT transferred! - /// @param type The group to randomly select from. "All" will look in all. - /// @param whichModuleSpace The name of the least common denominator type of the Entity:s you want. - /// "All" will look at all types. - /// Which module to get the instances for, in addition to all groups in - /// official modules loaded earlier than the one specified here. -1 means - /// get ALL groups ever reg'd. - /// @return The randomly select preset, if any was found with thse search params. - /// Ownership is NOT transferred! - Entity* GetRandomOfGroupInModuleSpace(std::string group, std::string type, int whichModuleSpace); - - /// Gets the data file path of a previously read in (defined) Entity. - /// @param type The type name of the derived Entity. Ownership is NOT transferred! - /// @param preset The preset name of the derived Entity preset. - /// @param whichModule Which module to try to get the entity from. If it's not found there, - /// the official modules will be searched also. - /// @return The file path of the data file that the specified Entity was read from. - /// If no Entity of that description was found, "" is returned. - std::string GetEntityDataLocation(std::string type, std::string preset, int whichModule); + Entity* GetRandomOfGroupInModuleSpace(const std::string& groupName, const std::string& typeName, int whichModuleSpace) { return GetRandomOfGroup(groupName, typeName, whichModuleSpace, true); } + /// Returns a previously read in (defined) Entity which is randomly selected from a specific group only if it belongs to some tech. + /// @param groupName The group to randomly select an Entity from. "All" will look in all. + /// @param typeName The name of the least common denominator type of the Entity to get. "All" will look at all types. + /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). + /// @return The Entity preset that was randomly selected. Ownership is NOT transferred! + Entity* GetRandomBuyableOfGroupFromTech(const std::string& groupName, const std::string& typeName = "All", int whichModule = -1); +#pragma endregion + +#pragma region Loadout Getters + /// Creates and returns an Actor defined in the specified Loadout. + /// @param loadoutName Loadout preset name. + /// @param whichModule The module ID in which the Loadout is defined. + /// @param spawnDeliveryCraft Whether or not spawn delivery craft defined for that Loadout. + /// @return Created Actor if matching loadout was found or nullptr. OWNERSHIP IS TRANSFERED! + Actor* GetLoadout(const std::string& loadoutName, int whichModule, bool spawnDeliveryCraft); + + /// Creates and returns an Actor defined in the specified Loadout. + /// @param loadoutName Loadout preset name. + /// @param whichModule The module name in which the Loadout is defined. + /// @param spawnDeliveryCraft Whether or not spawn delivery craft defined for that Loadout. + /// @return Created Actor if matching loadout was found or nullptr. OWNERSHIP IS TRANSFERED! + Actor* GetLoadout(const std::string& loadoutName, const std::string& moduleName, bool spawnDeliveryCraft); +#pragma endregion + +#pragma region Preset Reload Handling /// Reloads all scripted Entity Presets with the latest version of their respective script files. void ReloadAllScripts() const; @@ -296,93 +216,41 @@ namespace RTE { /// Resets whether or not ReloadEntityPreset was called this update. void ClearReloadEntityPresetCalledThisUpdate() { m_ReloadEntityPresetCalledThisUpdate = false; } +#pragma endregion - /// Adds a Material mapping local to a DataModule. This is used for when - /// multiple DataModule:s are loading conflicting Material:s, and need to - /// resolve the conflicts by mapping their materials to ID's different than - /// those specified in the data files. +#pragma region Concrete Methods + /// Adds a Material mapping local to a DataModule. + /// This is used for when multiple DataModules are loading conflicting Materials, and need to resolve the conflicts by mapping their materials to ID's different than those specified in the data files. /// @param fromID The material ID to map from. /// @param toID The material ID to map to. - /// @param whichModule The ID of the DataModule we are making the mapping for. This should be - /// a non-official module as mapping shouldn't be needed in the official - /// modules. - /// @return Whether this created a new mapping which didn't override a previous - /// material mapping. - bool AddMaterialMapping(int fromID, int toID, int whichModule); - - /// Registers the existence of an Entity group, and in which module. - /// @param newGroup The group to register. - /// @param whichModule The ID of the module in which at least one entity of this group can be - /// found. - /// global register. - void RegisterGroup(std::string newGroup, int whichModule); + /// @param whichModule The ID of the DataModule we are making the mapping for. This should be a non-official module as mapping shouldn't be needed in the official modules. + /// @return Whether this created a new mapping which didn't override a previous material mapping. + bool AddMaterialMapping(uint8_t fromID, uint8_t toID, int whichModule) const; + + /// Adds an Entity instance's pointer and name associations to the internal list of already read in Entities. Ownership is NOT transferred! + /// If there already is an instance defined, nothing happens. If there is not, a clone is made of the passed-in Entity and added to the library. + /// @param entityToAdd A pointer to the Entity derived instance to add. It should be created from a Reader. Ownership is NOT transferred! + /// @param whichModule Which module to add the entity to. + /// @param overwriteSame Whether to overwrite if an instance of the EXACT same TYPE and name was found. If one of the same name but not the exact type, false is returned regardless and nothing will have been added. + /// @param readFromFile The file this instance was read from, or where it should be written. If "Same" is passed as the file path read from, an overwritten instance will keep the old one's file location entry. + /// @return Whether or not a copy of the passed-in instance was successfully inserted into the module. False will be returned if there already was an instance of that class and instance name inserted previously, unless overwritten. + bool AddEntityPreset(Entity* entityToAdd, int whichModule = 0, bool overwriteSame = false, const std::string& readFromFile = "Same") const; + + /// Reads a preset of an Entity and tries to add it to the list of read-in instances. Regardless of whether there is a name collision, the read-in preset will be returned, ownership TRANSFERRED! + /// @param reader The Reader which is about to read in a preset. + /// @return A pointer to the Entity preset read in. 0 if there was an error, or the instance name was 'None'. Ownership IS transferred! + Entity* ReadReflectedPreset(Reader& reader); +#pragma endregion - /// Fills out a list with all groups registered in a specific module. - /// @param groupList The list that all found groups will be ADDED to. OWNERSHIP IS NOT TRANSFERRED! - /// @param whichModule Which module to get the groups for. -1 means get ALL groups ever reg'd. (default: -1) - /// @param withType Pass a type name here and only groups with entitys of that type will be (default: "All") - /// be included. "All" means don't consider what types are in the groups. - /// @return Whether any groups were found and thus added to the list. - bool GetGroups(std::list& groupList, int whichModule = -1, std::string withType = "All") const; - - /// Fills out a list with all groups registered in all official modules, - /// PLUS a specific non-official module as well. - /// @param groupList The list that all found groups will be ADDED to. OWNERSHIP IS NOT TRANSFERRED! - /// @param whichModule Which module to get the groups for, in addition to all groups in - /// official modules loaded earlier than the one specified here. -1 means - /// get ALL groups ever reg'd. - /// @param withType Pass a type name here and only groups with entitys of that type will be (default: "All") - /// be included. "All" means don't consider what types are in the groups. - /// @return Whether any groups were found and thus added to the list. - bool GetModuleSpaceGroups(std::list& groupList, int whichModule, std::string withType = "All") const; - - /// Creates and returns actor defined in the specified loadout. - /// @param loadoutName Loadout preset name, module name, whether or not spawn delivery craft defined for that loadout - /// @return Created actor if matching loadout was found or 0. OWNERSHIP IS TRANSFERED. - Actor* GetLoadout(std::string loadoutName, std::string module, bool spawnDropShip); - - /// Creates and returns actor defined in the specified loadout. - /// @param loadoutName Loadout preset name, module id, whether or not spawn delivery craft defined for that loadout - /// @return Created actor if matching loadout was found or 0. OWNERSHIP IS TRANSFERED. - Actor* GetLoadout(std::string loadoutName, int moduleNumber, bool spawnDropShip); - - /// Protected member variable and method declarations - protected: - // Owned and loaded DataModule:s - std::vector m_pDataModules; - - // Names of all DataModule:s mapped to indices into the m_pDataModules vector. - // The names are all lowercase name so we can more easily find them in case-agnostic fashion - std::map m_DataModuleIDs; - - // How many modules are 'official' and shipped with the game, and guaranteed to not have name conflicts among them - // All official modules are in the beginning of the m_TypeMap, so this count shows how many into that vector they represent - int m_OfficialModuleCount; - - std::string m_SingleModuleToLoad; //!< Name of the single module to load after the official modules. - - // List of all Entity groups ever registered, all uniques - // This is just a handy total of all the groups registered in all the individual DataModule:s - std::list m_TotalGroupRegister; - - /// Private member variable and method declarations private: - static const std::array c_OfficialModules; // Array storing the names of all the official modules. - static const std::array, 3> c_UserdataModules; // Array storing the names of all the userdata modules. - - std::array m_LastReloadedEntityPresetInfo; //!< Array storing the last reloaded Entity preset info (ClassName, PresetName and DataModule). Used for quick reloading via key combination. bool m_ReloadEntityPresetCalledThisUpdate; //!< A flag for whether or not ReloadEntityPreset was called this update. + std::array m_LastReloadedEntityPresetInfo; //!< Array storing the last reloaded Entity preset info (ClassName, PresetName and DataModule). Used for quick reloading via key combination. - /// Iterates through the working directory to find any files matching the zipped module package extension (.rte.zip) and proceeds to extract them. - void FindAndExtractZippedModules() const; - - /// Clears all the member variables of this PresetMan, effectively - /// resetting the members of this abstraction level only. + /// Clears all the member variables of this PresetMan, effectively resetting the members of this abstraction level only. void Clear(); // Disallow the use of some implicit methods. PresetMan(const PresetMan& reference) = delete; PresetMan& operator=(const PresetMan& rhs) = delete; }; - } // namespace RTE diff --git a/Source/Managers/SettingsMan.cpp b/Source/Managers/SettingsMan.cpp index 3e5429145..208501ceb 100644 --- a/Source/Managers/SettingsMan.cpp +++ b/Source/Managers/SettingsMan.cpp @@ -1,4 +1,5 @@ #include "SettingsMan.h" +#include "ModuleMan.h" #include "ConsoleMan.h" #include "CameraMan.h" #include "MovableMan.h" @@ -66,7 +67,6 @@ void SettingsMan::Clear() { m_PrintDebugInfo = false; m_MeasureModuleLoadTime = false; - m_DisabledMods.clear(); m_EnabledGlobalScripts.clear(); } @@ -209,7 +209,7 @@ int SettingsMan::ReadProperty(const std::string_view& propName, Reader& reader) MatchProperty("ServerSleepWhenIdle", { reader >> g_NetworkServer.m_SleepWhenIdle; }); MatchProperty("ServerSimSleepWhenIdle", { reader >> g_NetworkServer.m_SimSleepWhenIdle; }); MatchProperty("VisibleAssemblyGroup", { m_VisibleAssemblyGroupsList.push_back(reader.ReadPropValue()); }); - MatchProperty("DisableMod", { m_DisabledMods.try_emplace(reader.ReadPropValue(), true); }); + MatchProperty("DisableMod", { g_ModuleMan.m_DisabledDataModuleNames.emplace(reader.ReadPropValue()); }); MatchProperty("EnableGlobalScript", { m_EnabledGlobalScripts.try_emplace(reader.ReadPropValue(), true); }); MatchProperty("MouseSensitivity", { reader >> g_UInputMan.m_MouseSensitivity; }); MatchForwards("Player1Scheme") MatchForwards("Player2Scheme") MatchForwards("Player3Scheme") MatchProperty("Player4Scheme", { @@ -395,15 +395,13 @@ int SettingsMan::Save(Writer& writer) const { } } - if (!m_DisabledMods.empty()) { + if (!g_ModuleMan.m_DisabledDataModuleNames.empty()) { writer.NewLine(false, 2); writer.NewDivider(false); writer.NewLineString("// Disabled Mods", false); writer.NewLine(false); - for (const auto& [modPath, modDisabled]: m_DisabledMods) { - if (modDisabled) { - writer.NewPropertyWithValue("DisableMod", modPath); - } + for (const std::string& disabledModuleName: g_ModuleMan.m_DisabledDataModuleNames) { + writer.NewPropertyWithValue("DisableMod", disabledModuleName); } } diff --git a/Source/Managers/SettingsMan.h b/Source/Managers/SettingsMan.h index 18cce1084..03bb17d0b 100644 --- a/Source/Managers/SettingsMan.h +++ b/Source/Managers/SettingsMan.h @@ -260,15 +260,6 @@ namespace RTE { #pragma endregion #pragma region Mod and Script Management - /// Gets the map of mods which are disabled. - /// @return Map of mods which are disabled. - std::unordered_map& GetDisabledModsMap() { return m_DisabledMods; } - - /// Gets whether the specified mod is disabled in the settings. - /// @param modModule Mod to check. - /// @return Whether the mod is disabled via settings. - bool IsModDisabled(const std::string& modModule) const { return (m_DisabledMods.find(modModule) != m_DisabledMods.end()) ? m_DisabledMods.at(modModule) : false; } - /// Gets the map of global scripts which are enabled. /// @return Map of global scripts which are enabled. std::unordered_map& GetEnabledGlobalScriptMap() { return m_EnabledGlobalScripts; } @@ -406,7 +397,6 @@ namespace RTE { bool m_MeasureModuleLoadTime; //!< Whether to measure the duration of data module loading (extraction included). For benchmarking purposes. std::list m_VisibleAssemblyGroupsList; //!< List of assemblies groups always shown in editors. - std::unordered_map m_DisabledMods; //!< Map of the module names we disabled. std::unordered_map m_EnabledGlobalScripts; //!< Map of the global script names we enabled. private: diff --git a/Source/Managers/WindowMan.cpp b/Source/Managers/WindowMan.cpp index 59b39d397..0c4a3790a 100644 --- a/Source/Managers/WindowMan.cpp +++ b/Source/Managers/WindowMan.cpp @@ -4,7 +4,7 @@ #include "ActivityMan.h" #include "UInputMan.h" #include "ConsoleMan.h" -#include "PresetMan.h" +#include "ModuleMan.h" #include "PostProcessMan.h" #include "GLCheck.h" @@ -103,7 +103,7 @@ void WindowMan::Initialize() { CreatePrimaryWindow(); InitializeOpenGL(); CreateBackBufferTexture(); - m_ScreenBlitShader = std::make_unique(g_PresetMan.GetFullModulePath("Base.rte/Shaders/ScreenBlit.vert"), g_PresetMan.GetFullModulePath("Base.rte/Shaders/ScreenBlit.frag")); + m_ScreenBlitShader = std::make_unique(g_ModuleMan.GetFullModulePath("Base.rte/Shaders/ScreenBlit.vert"), g_ModuleMan.GetFullModulePath("Base.rte/Shaders/ScreenBlit.frag")); // SDL is kinda dumb about the taskbar icon so we need to poll after creating the window for it to show up, otherwise there's no icon till it starts polling in the main menu loop. SDL_PollEvent(nullptr); diff --git a/Source/Managers/WindowMan.h b/Source/Managers/WindowMan.h index 4b16441d4..783ef7375 100644 --- a/Source/Managers/WindowMan.h +++ b/Source/Managers/WindowMan.h @@ -273,7 +273,7 @@ namespace RTE { void AttemptToRevertToPreviousResolution(bool revertToDefaults = false); #pragma endregion -#pragma region Multi - Display Handling +#pragma region Multi-Display Handling /// Clears all the multi-display data, resetting the game to a single-window-single-display state. void ClearMultiDisplayData(); diff --git a/Source/Managers/meson.build b/Source/Managers/meson.build index 91a3f0db7..3156f145d 100644 --- a/Source/Managers/meson.build +++ b/Source/Managers/meson.build @@ -8,6 +8,7 @@ sources += files( #'LuaMan.cpp', 'MenuMan.cpp', 'MetaMan.cpp', +'ModuleMan.cpp', 'MovableMan.cpp', 'MusicMan.cpp', 'NetworkClient.cpp', diff --git a/Source/Menus/AssemblyEditorGUI.cpp b/Source/Menus/AssemblyEditorGUI.cpp index a28f0b1e3..eb8657df9 100644 --- a/Source/Menus/AssemblyEditorGUI.cpp +++ b/Source/Menus/AssemblyEditorGUI.cpp @@ -2,6 +2,7 @@ #include "CameraMan.h" #include "FrameMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "ActivityMan.h" #include "GameActivity.h" @@ -190,7 +191,7 @@ void AssemblyEditorGUI::SetModuleSpace(int moduleSpaceID) { } void AssemblyEditorGUI::SetNativeTechModule(int whichModule) { - if (whichModule >= 0 && whichModule < g_PresetMan.GetTotalModuleCount()) { + if (whichModule >= 0 && whichModule < g_ModuleMan.GetTotalModuleCount()) { m_NativeTechModule = whichModule; m_pPicker->SetNativeTechModule(m_NativeTechModule); } diff --git a/Source/Menus/BuyMenuGUI.cpp b/Source/Menus/BuyMenuGUI.cpp index eb9c58a21..4a5c9cc58 100644 --- a/Source/Menus/BuyMenuGUI.cpp +++ b/Source/Menus/BuyMenuGUI.cpp @@ -3,6 +3,7 @@ #include "CameraMan.h" #include "WindowMan.h" #include "FrameMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "ActivityMan.h" #include "UInputMan.h" @@ -21,7 +22,6 @@ #include "GUIButton.h" #include "GUILabel.h" -#include "DataModule.h" #include "Controller.h" #include "SceneObject.h" #include "MovableObject.h" @@ -78,7 +78,7 @@ void BuyMenuGUI::Clear() { m_MetaPlayer = Players::NoPlayer; m_NativeTechModule = 0; m_ForeignCostMult = 4.0; - int moduleCount = g_PresetMan.GetTotalModuleCount(); + int moduleCount = g_ModuleMan.GetTotalModuleCount(); m_aExpandedModules = new bool[moduleCount]; for (int i = 0; i < moduleCount; ++i) m_aExpandedModules[i] = i == 0 ? true : false; @@ -554,13 +554,13 @@ void BuyMenuGUI::SetMetaPlayer(int metaPlayer) { } void BuyMenuGUI::SetNativeTechModule(int whichModule) { - if (whichModule >= 0 && whichModule < g_PresetMan.GetTotalModuleCount()) { + if (whichModule >= 0 && whichModule < g_ModuleMan.GetTotalModuleCount()) { m_NativeTechModule = whichModule; SetModuleExpanded(m_NativeTechModule); DeployLoadout(0); if (!g_SettingsMan.FactionBuyMenuThemesDisabled() && m_NativeTechModule > 0) { - if (const DataModule* techModule = g_PresetMan.GetDataModule(whichModule); techModule->IsFaction()) { + if (const DataModule* techModule = g_ModuleMan.GetDataModule(whichModule); techModule->IsFaction()) { const DataModule::BuyMenuTheme& techBuyMenuTheme = techModule->GetFactionBuyMenuTheme(); if (!techBuyMenuTheme.SkinFilePath.empty()) { @@ -583,7 +583,7 @@ void BuyMenuGUI::SetNativeTechModule(int whichModule) { } void BuyMenuGUI::SetModuleExpanded(int whichModule, bool expanded) { - int moduleCount = g_PresetMan.GetTotalModuleCount(); + int moduleCount = g_ModuleMan.GetTotalModuleCount(); if (whichModule > 0 && whichModule < moduleCount) { m_aExpandedModules[whichModule] = expanded; // Refresh the item view with the newly expanded module items @@ -1220,7 +1220,7 @@ void BuyMenuGUI::Update() { } } } else if (pItem && pItem->m_ExtraIndex >= 0) { - const DataModule* pModule = g_PresetMan.GetDataModule(pItem->m_ExtraIndex); + const DataModule* pModule = g_ModuleMan.GetDataModule(pItem->m_ExtraIndex); if (pModule && !pModule->GetDescription().empty()) { description = pModule->GetDescription(); } @@ -1933,7 +1933,7 @@ void BuyMenuGUI::CategoryChange(bool focusOnCategoryTabs) { // Don't add anyhting to the real buy item list if the current module didn't yield any valid items if (!tempList.empty()) { // Add the DataModule separator in the shop list, with appropriate name and perhaps icon? Don't add for first base module - if (moduleID != 0 && (pModule = g_PresetMan.GetDataModule(moduleID))) { + if (moduleID != 0 && (pModule = g_ModuleMan.GetDataModule(moduleID))) { pItemBitmap = pModule->GetIcon() ? new AllegroBitmap(pModule->GetIcon()) : 0; // Passing in ownership of the bitmap, making uppercase the name std::string name = pModule->GetFriendlyName(); @@ -2082,11 +2082,11 @@ bool BuyMenuGUI::DeployLoadout(int index) { } void BuyMenuGUI::AddObjectsToItemList(std::vector>& moduleList, const std::string& type, const std::vector& groups, bool excludeGroups) { - while (moduleList.size() < g_PresetMan.GetTotalModuleCount()) { + while (moduleList.size() < g_ModuleMan.GetTotalModuleCount()) { moduleList.emplace_back(); } - for (int moduleID = 0; moduleID < g_PresetMan.GetTotalModuleCount(); ++moduleID) { - if ((g_SettingsMan.ShowForeignItems() || m_NativeTechModule <= 0) || (moduleID == 0 || moduleID == m_NativeTechModule || g_PresetMan.GetDataModule(moduleID)->IsMerchant())) { + for (int moduleID = 0; moduleID < g_ModuleMan.GetTotalModuleCount(); ++moduleID) { + if ((g_SettingsMan.ShowForeignItems() || m_NativeTechModule <= 0) || (moduleID == 0 || moduleID == m_NativeTechModule || g_ModuleMan.GetDataModule(moduleID)->IsMerchant())) { if (groups.empty() || std::find(groups.begin(), groups.end(), "All") != groups.end()) { g_PresetMan.GetAllOfType(moduleList[moduleID], type, moduleID); } else { diff --git a/Source/Menus/MetagameGUI.cpp b/Source/Menus/MetagameGUI.cpp index 587520cd2..ad84345dc 100644 --- a/Source/Menus/MetagameGUI.cpp +++ b/Source/Menus/MetagameGUI.cpp @@ -3,6 +3,7 @@ #include "WindowMan.h" #include "FrameMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "ActivityMan.h" #include "AudioMan.h" @@ -37,7 +38,6 @@ #include "BaseEditor.h" #include "Scene.h" #include "SLTerrain.h" -#include "DataModule.h" #include "Loadout.h" #include "MusicMan.h" #include "System.h" @@ -726,8 +726,8 @@ void MetagameGUI::SetEnabled(bool enable) { m_apPlayerTechSelect[player]->GetListPanel()->AddItem("-Random-", "", nullptr, nullptr, -1); m_apPlayerTechSelect[player]->SetSelectedIndex(0); } - for (int moduleID = 0; moduleID < g_PresetMan.GetTotalModuleCount(); ++moduleID) { - if (const DataModule* dataModule = g_PresetMan.GetDataModule(moduleID)) { + for (int moduleID = 0; moduleID < g_ModuleMan.GetTotalModuleCount(); ++moduleID) { + if (const DataModule* dataModule = g_ModuleMan.GetDataModule(moduleID)) { if (dataModule->IsFaction()) { for (int player = Players::PlayerOne; player < Players::MaxPlayerCount; ++player) { m_apPlayerTechSelect[player]->GetListPanel()->AddItem(dataModule->GetFriendlyName(), "", nullptr, nullptr, moduleID); @@ -1091,7 +1091,7 @@ bool MetagameGUI::LoadGame() { } bool MetagameGUI::SaveGame(std::string saveName, std::string savePath, bool resaveSceneData) { - const std::string fullSavePath = g_PresetMan.GetFullModulePath(savePath); + const std::string fullSavePath = g_ModuleMan.GetFullModulePath(savePath); // If specified, first load all bitmap data of all Scenes in the current Metagame that have once saved em, so we can re-save them to the new files if (resaveSceneData) g_MetaMan.LoadSceneData(); @@ -1121,7 +1121,7 @@ bool MetagameGUI::SaveGame(std::string saveName, std::string savePath, bool resa newSave.SetPresetName(saveName); // Now add or update the actual Preset - g_PresetMan.AddEntityPreset(&newSave, g_PresetMan.GetModuleID(METASAVEMODULENAME), true, std::string(METASAVEPATH) + "Index.ini"); + g_PresetMan.AddEntityPreset(&newSave, g_ModuleMan.GetModuleID(METASAVEMODULENAME), true, std::string(METASAVEPATH) + "Index.ini"); // Now write out the index file of all MetaSaves so the new save is found on next runtime Writer indexWriter((std::string(METASAVEPATH) + "Index.ini").c_str()); @@ -2550,7 +2550,7 @@ void MetagameGUI::CompletedActivity() { // Scrub the module ID so the migration goes well.. this is a bit hacky, but ok in this special case g_MetaMan.m_RoundOffensives[g_MetaMan.m_CurrentOffensive]->SetModuleID(-1); // Remind the Offensive that it is a unique snowflake and should save itself as such - g_MetaMan.m_RoundOffensives[g_MetaMan.m_CurrentOffensive]->MigrateToModule(g_PresetMan.GetModuleID(METASAVEMODULENAME)); + g_MetaMan.m_RoundOffensives[g_MetaMan.m_CurrentOffensive]->MigrateToModule(g_ModuleMan.GetModuleID(METASAVEMODULENAME)); // We are now reviewing the battle after it has concluded; UpdateOffensives will show all that stuff m_PreTurn = true; @@ -2611,7 +2611,7 @@ void MetagameGUI::CompletedActivity() { m_pPlayingScene->SetModuleID(-1); m_pPlayingScene->GetTerrain()->SetModuleID(-1); // Remind the Scene that it is a unique snowflake and should save itself as such - m_pPlayingScene->MigrateToModule(g_PresetMan.GetModuleID(METASAVEMODULENAME)); + m_pPlayingScene->MigrateToModule(g_ModuleMan.GetModuleID(METASAVEMODULENAME)); // We're not playing this anymore m_pPlayingScene = 0; // Auto save the entire MetaMan state too diff --git a/Source/Menus/ModManagerGUI.cpp b/Source/Menus/ModManagerGUI.cpp index 2c0f1437b..2b9f2eba3 100644 --- a/Source/Menus/ModManagerGUI.cpp +++ b/Source/Menus/ModManagerGUI.cpp @@ -1,9 +1,9 @@ #include "ModManagerGUI.h" #include "SettingsMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "WindowMan.h" -#include "DataModule.h" #include "GlobalScript.h" #include "GUI.h" @@ -57,26 +57,22 @@ ModManagerGUI::ModManagerGUI(AllegroScreen* guiScreen, GUIInputWrapper* guiInput } void ModManagerGUI::PopulateKnownModsList() { - for (int i = 0; i < g_PresetMan.GetTotalModuleCount(); ++i) { - if (i >= g_PresetMan.GetOfficialModuleCount() && i < g_PresetMan.GetTotalModuleCount()) { - if (const DataModule* dataModule = g_PresetMan.GetDataModule(i); dataModule && !dataModule->IsUserdata()) { - ModRecord modRecord = {dataModule->GetFileName(), dataModule->GetFriendlyName(), dataModule->GetDescription(), g_SettingsMan.IsModDisabled(dataModule->GetFileName())}; - m_KnownMods.emplace_back(modRecord); - } + for (const auto& [moduleID, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + if (!dataModule->IsOfficial() && !dataModule->IsUserdata()) { + m_KnownMods.emplace_back(dataModule->GetFileName(), dataModule->GetFriendlyName(), dataModule->GetDescription(), g_ModuleMan.IsModuleEnabled(dataModule->GetFileName())); } } // Add missing data from disabled mods settings - for (const auto& [modPath, modDisabled]: g_SettingsMan.GetDisabledModsMap()) { + for (const std::string& disabledModuleName: g_ModuleMan.GetDisabledDataModuleNames()) { bool found = false; for (const ModRecord& knowModListEntry: m_KnownMods) { - if (modPath == knowModListEntry.ModulePath) { + if (disabledModuleName == knowModListEntry.ModulePath) { found = true; break; } } if (!found) { - ModRecord disabledModRecord = {modPath, "N/A, Module not loaded", "N/A, Module not loaded", modDisabled}; - m_KnownMods.emplace_back(disabledModRecord); + m_KnownMods.emplace_back(disabledModuleName, "N/A, Module not loaded", "N/A, Module not loaded", false); } } std::sort(m_KnownMods.begin(), m_KnownMods.end()); @@ -110,22 +106,27 @@ void ModManagerGUI::PopulateKnownScriptsList() { void ModManagerGUI::ToggleMod() { int index = m_ModsListBox->GetSelectedIndex(); if (index > -1) { - std::unordered_map& disabledModsList = g_SettingsMan.GetDisabledModsMap(); + std::unordered_set& disabledModsList = g_ModuleMan.GetDisabledDataModuleNames(); GUIListPanel::Item* selectedItem = m_ModsListBox->GetSelected(); ModRecord& modRecord = m_KnownMods.at(selectedItem->m_ExtraIndex); - modRecord.Disabled = !modRecord.Disabled; - if (modRecord.Disabled) { - m_ToggleModButton->SetText("Enable Mod"); - if (disabledModsList.find(modRecord.ModulePath) != disabledModsList.end()) { - disabledModsList.at(modRecord.ModulePath) = true; - } else { - disabledModsList.try_emplace(modRecord.ModulePath, true); - } - } else { + modRecord.Enabled = !modRecord.Enabled; + if (modRecord.Enabled) { m_ToggleModButton->SetText("Disable Mod"); - disabledModsList.at(modRecord.ModulePath) = false; + disabledModsList.erase(disabledModsList.find(modRecord.ModulePath)); + g_ModuleMan.LoadDataModule(modRecord.ModulePath, DataModule::DataModuleType::Unofficial, nullptr); + } else { + m_ToggleModButton->SetText("Enable Mod"); + disabledModsList.emplace(modRecord.ModulePath); + g_ModuleMan.UnloadDataModule(modRecord.ModulePath); } + + const DataModule* dataModule = g_ModuleMan.GetDataModule(g_ModuleMan.GetModuleID(modRecord.ModulePath)); + if (dataModule) { + modRecord.ModuleName = dataModule->GetFriendlyName(); + modRecord.Description = dataModule->GetDescription(); + } + selectedItem->m_Name = modRecord.GetDisplayString(); m_ModsListBox->SetSelectedIndex(index); m_ModsListBox->Invalidate(); @@ -184,7 +185,7 @@ bool ModManagerGUI::HandleInputEvents() { if (guiEvent.GetControl() == m_ModsListBox && (guiEvent.GetMsg() == GUIListBox::Select && m_ModsListBox->GetSelectedIndex() > -1)) { const ModRecord& modRecord = m_KnownMods.at(m_ModsListBox->GetSelected()->m_ExtraIndex); m_ModOrScriptDescriptionLabel->SetText(modRecord.Description); - m_ToggleModButton->SetText(modRecord.Disabled ? "Enable Mod" : "Disable Mod"); + m_ToggleModButton->SetText(modRecord.Enabled ? "Disable Mod" : "Enable Mod"); } else if (guiEvent.GetControl() == m_ScriptsListBox && (guiEvent.GetMsg() == GUIListBox::Select && m_ScriptsListBox->GetSelectedIndex() > -1)) { const ScriptRecord& scriptRecord = m_KnownScripts.at(m_ScriptsListBox->GetSelected()->m_ExtraIndex); m_ModOrScriptDescriptionLabel->SetText(scriptRecord.Description); diff --git a/Source/Menus/ModManagerGUI.h b/Source/Menus/ModManagerGUI.h index 3c5fbeb01..b5d723761 100644 --- a/Source/Menus/ModManagerGUI.h +++ b/Source/Menus/ModManagerGUI.h @@ -40,11 +40,11 @@ namespace RTE { std::string ModulePath; //!< Mod DataModule path. std::string ModuleName; //!< Mod ModuleName. std::string Description; //!< Mod description. - bool Disabled; //!< Whether the mod is disabled through the settings file or not. + bool Enabled; //!< Whether the mod is disabled through the settings file or not. /// Makes GUI displayable string with mod info. /// @return String with mod info. - std::string GetDisplayString() const { return (Disabled ? "- " : "+ ") + ModulePath + " - " + ModuleName; } + std::string GetDisplayString() const { return (Enabled ? "+ " : "- ") + ModulePath + " - " + ModuleName; } /// Comparison operator for sorting the KnownMods list alphabetically by path with std::sort. /// @param rhs ModRecord to compare with. diff --git a/Source/Menus/ObjectPickerGUI.cpp b/Source/Menus/ObjectPickerGUI.cpp index 199d7efa9..386170c03 100644 --- a/Source/Menus/ObjectPickerGUI.cpp +++ b/Source/Menus/ObjectPickerGUI.cpp @@ -4,6 +4,7 @@ #include "WindowMan.h" #include "FrameMan.h" #include "PresetMan.h" +#include "ModuleMan.h" #include "ActivityMan.h" #include "UInputMan.h" #include "SettingsMan.h" @@ -17,7 +18,6 @@ #include "GUIListBox.h" #include "GUILabel.h" -#include "DataModule.h" #include "SceneObject.h" #include "EditorActivity.h" #include "BunkerAssembly.h" @@ -51,7 +51,7 @@ void ObjectPickerGUI::Clear() { m_RepeatStartTimer.Reset(); m_RepeatTimer.Reset(); - m_ExpandedModules.resize(g_PresetMan.GetTotalModuleCount()); + m_ExpandedModules.resize(g_ModuleMan.GetTotalModuleCount()); std::fill(m_ExpandedModules.begin(), m_ExpandedModules.end(), false); m_ExpandedModules[0] = true; // Base.rte is always expanded } @@ -146,13 +146,13 @@ void ObjectPickerGUI::SetEnabled(bool enable) { } void ObjectPickerGUI::SetNativeTechModule(int whichModule) { - if (whichModule >= 0 && whichModule < g_PresetMan.GetTotalModuleCount()) { + if (whichModule >= 0 && whichModule < g_ModuleMan.GetTotalModuleCount()) { m_NativeTechModuleID = whichModule; if (m_NativeTechModuleID > 0) { SetObjectsListModuleGroupExpanded(m_NativeTechModuleID); if (!g_SettingsMan.FactionBuyMenuThemesDisabled()) { - if (const DataModule* techModule = g_PresetMan.GetDataModule(whichModule); techModule->IsFaction()) { + if (const DataModule* techModule = g_ModuleMan.GetDataModule(whichModule); techModule->IsFaction()) { const DataModule::BuyMenuTheme& techBuyMenuTheme = techModule->GetFactionBuyMenuTheme(); if (!techBuyMenuTheme.SkinFilePath.empty()) { @@ -314,7 +314,7 @@ void ObjectPickerGUI::SelectNextOrPrevObject(bool getPrev) { } void ObjectPickerGUI::AddObjectsListModuleGroup(int moduleID) { - const DataModule* dataModule = g_PresetMan.GetDataModule(moduleID); + const DataModule* dataModule = g_ModuleMan.GetDataModule(moduleID); std::string moduleName = dataModule->GetFriendlyName(); std::transform(moduleName.begin(), moduleName.end(), moduleName.begin(), ::toupper); GUIBitmap* dataModuleIcon = dataModule->GetIcon() ? new AllegroBitmap(dataModule->GetIcon()) : nullptr; @@ -344,7 +344,7 @@ void ObjectPickerGUI::ShowDescriptionPopupBox() { if (objectListItem && objectListItem->m_pEntity && !objectListItem->m_pEntity->GetDescription().empty()) { description = objectListItem->m_pEntity->GetDescription(); } else if (objectListItem && objectListItem->m_ExtraIndex >= 0) { - const DataModule* dataModule = g_PresetMan.GetDataModule(objectListItem->m_ExtraIndex); + const DataModule* dataModule = g_ModuleMan.GetDataModule(objectListItem->m_ExtraIndex); if (dataModule && !dataModule->GetDescription().empty()) { description = dataModule->GetDescription(); } @@ -365,7 +365,7 @@ void ObjectPickerGUI::ShowDescriptionPopupBox() { void ObjectPickerGUI::UpdateObjectsList(bool selectTop) { m_ObjectsList->ClearList(); - std::vector> moduleList(g_PresetMan.GetTotalModuleCount(), std::list()); + std::vector> moduleList(g_ModuleMan.GetTotalModuleCount(), std::list()); if (const GUIListPanel::Item* groupListItem = m_GroupsList->GetSelected()) { if (m_ModuleSpaceID < 0) { @@ -375,16 +375,13 @@ void ObjectPickerGUI::UpdateObjectsList(bool selectTop) { } } else { for (int moduleID = 0; moduleID < moduleList.size(); ++moduleID) { - if (moduleID == 0 || moduleID == m_NativeTechModuleID || g_PresetMan.GetDataModule(moduleID)->IsMerchant()) { + if (moduleID == 0 || moduleID == m_NativeTechModuleID || g_ModuleMan.GetDataModule(moduleID)->IsMerchant()) { g_PresetMan.GetAllOfGroup(moduleList.at(moduleID), groupListItem->m_Name, m_ShowType, moduleID); } } } } else { - for (int moduleID = 0; moduleID < g_PresetMan.GetOfficialModuleCount() && moduleID < m_ModuleSpaceID; ++moduleID) { - g_PresetMan.GetAllOfGroup(moduleList.at(moduleID), groupListItem->m_Name, m_ShowType, moduleID); - } - g_PresetMan.GetAllOfGroup(moduleList.at(m_ModuleSpaceID), groupListItem->m_Name, m_ShowType, m_ModuleSpaceID); + g_PresetMan.GetAllOfGroupInModuleSpace(moduleList.at(m_ModuleSpaceID), groupListItem->m_Name, m_ShowType, m_ModuleSpaceID); } } diff --git a/Source/Menus/SaveLoadMenuGUI.cpp b/Source/Menus/SaveLoadMenuGUI.cpp index 04d83fa82..f3c44b92a 100644 --- a/Source/Menus/SaveLoadMenuGUI.cpp +++ b/Source/Menus/SaveLoadMenuGUI.cpp @@ -1,7 +1,7 @@ #include "SaveLoadMenuGUI.h" #include "ActivityMan.h" -#include "PresetMan.h" +#include "ModuleMan.h" #include "WindowMan.h" #include "PauseMenuGUI.h" @@ -80,7 +80,7 @@ void SaveLoadMenuGUI::PopulateSaveGamesList() { m_GUIControlManager->GetManager()->SetFocus(nullptr); - std::string saveFilePath = g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/"; + std::string saveFilePath = g_ModuleMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/"; for (const auto& entry: std::filesystem::directory_iterator(saveFilePath)) { if (entry.is_directory()) { SaveRecord record; @@ -191,7 +191,7 @@ void SaveLoadMenuGUI::CreateSave() { } void SaveLoadMenuGUI::DeleteSave() { - std::string saveFilePath = g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/" + m_SaveGameName->GetText(); + std::string saveFilePath = g_ModuleMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/" + m_SaveGameName->GetText(); std::filesystem::remove_all(saveFilePath); g_GUISound.ConfirmSound()->Play(); diff --git a/Source/Menus/ScenarioActivityConfigGUI.cpp b/Source/Menus/ScenarioActivityConfigGUI.cpp index aa811cf7f..4c17c7763 100644 --- a/Source/Menus/ScenarioActivityConfigGUI.cpp +++ b/Source/Menus/ScenarioActivityConfigGUI.cpp @@ -1,12 +1,12 @@ #include "ScenarioActivityConfigGUI.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "UInputMan.h" #include "FrameMan.h" #include "SceneMan.h" #include "LuaMan.h" -#include "DataModule.h" #include "GameActivity.h" #include "Scene.h" @@ -65,29 +65,32 @@ ScenarioActivityConfigGUI::ScenarioActivityConfigGUI(GUIControlManager* parentCo m_CPULockLabel = dynamic_cast(m_GUIControlManager->GetControl("LabelCPUTeamLock")); m_StartErrorLabel = dynamic_cast(m_GUIControlManager->GetControl("LabelStartError")); m_StartGameButton = dynamic_cast(m_GUIControlManager->GetControl("ButtonStartGame")); - - m_TechListFetched = false; } void ScenarioActivityConfigGUI::PopulateTechComboBoxes() { + static constexpr int allTechIndex = 0; + static constexpr int randomTechIndex = 1; + + std::array lastSelectedIndices = {}; + lastSelectedIndices.fill(allTechIndex); + for (int team = Activity::Teams::TeamOne; team < Activity::Teams::MaxTeamCount; ++team) { - m_TeamTechComboBoxes[team]->GetListPanel()->AddItem("-All-", "", nullptr, nullptr, -2); - m_TeamTechComboBoxes[team]->GetListPanel()->AddItem("-Random-", "", nullptr, nullptr, -1); - m_TeamTechComboBoxes[team]->SetSelectedIndex(0); + lastSelectedIndices[team] = m_TeamTechComboBoxes[team]->GetSelectedIndex(); + m_TeamTechComboBoxes[team]->ClearList(); + m_TeamTechComboBoxes[team]->GetListPanel()->AddItem("-All-", "", nullptr, nullptr, allTechIndex); + m_TeamTechComboBoxes[team]->GetListPanel()->AddItem("-Random-", "", nullptr, nullptr, randomTechIndex); } - for (int moduleID = 0; moduleID < g_PresetMan.GetTotalModuleCount(); ++moduleID) { - if (const DataModule* dataModule = g_PresetMan.GetDataModule(moduleID)) { - if (dataModule->IsFaction()) { - for (int team = Activity::Teams::TeamOne; team < Activity::Teams::MaxTeamCount; ++team) { - m_TeamTechComboBoxes[team]->GetListPanel()->AddItem(dataModule->GetFriendlyName(), "", nullptr, nullptr, moduleID); - } + for (const auto& [moduleID, dataModule]: g_ModuleMan.GetLoadedDataModules()) { + if (dataModule->IsFaction()) { + for (int team = Activity::Teams::TeamOne; team < Activity::Teams::MaxTeamCount; ++team) { + m_TeamTechComboBoxes[team]->GetListPanel()->AddItem(dataModule->GetFriendlyName(), "", nullptr, nullptr, moduleID); } } } for (int team = Activity::Teams::TeamOne; team < Activity::Teams::MaxTeamCount; ++team) { + m_TeamTechComboBoxes[team]->SetSelectedIndex(lastSelectedIndices[team] >= 0 && lastSelectedIndices[team] < m_TeamTechComboBoxes[team]->GetCount() ? lastSelectedIndices[team] : allTechIndex); m_TeamTechComboBoxes[team]->GetListPanel()->ScrollToTop(); } - m_TechListFetched = true; } bool ScenarioActivityConfigGUI::IsEnabled() const { @@ -113,9 +116,7 @@ void ScenarioActivityConfigGUI::SetEnabled(bool enable, const Activity* selected m_TeamTechComboBoxes[team]->SetVisible(enable); } if (enable && m_SelectedActivity && m_SelectedScene) { - if (!m_TechListFetched) { - PopulateTechComboBoxes(); - } + PopulateTechComboBoxes(); int startingGoldOverride = selectingPreviousActivityWithManuallyAdjustedGold ? m_StartingGoldSlider->GetValue() : -1; ResetActivityConfigBox(); @@ -246,9 +247,9 @@ void ScenarioActivityConfigGUI::StartGame() { if (techItem->m_ExtraIndex == -2) { gameActivity->SetTeamTech(team, "-All-"); } else if (techItem->m_ExtraIndex == -1) { - gameActivity->SetTeamTech(team, g_PresetMan.GetDataModuleName(m_TeamTechComboBoxes.at(team)->GetItem(RandomNum(2, m_TeamTechComboBoxes.at(team)->GetListPanel()->GetItemList()->size() - 1))->m_ExtraIndex)); + gameActivity->SetTeamTech(team, g_ModuleMan.GetModuleName(m_TeamTechComboBoxes.at(team)->GetItem(RandomNum(2, m_TeamTechComboBoxes.at(team)->GetListPanel()->GetItemList()->size() - 1))->m_ExtraIndex)); } else { - gameActivity->SetTeamTech(team, g_PresetMan.GetDataModuleName(techItem->m_ExtraIndex)); + gameActivity->SetTeamTech(team, g_ModuleMan.GetModuleName(techItem->m_ExtraIndex)); } } gameActivity->SetTeamAISkill(team, (m_TeamAISkillSliders.at(team)->IsEnabled()) ? m_TeamAISkillSliders.at(team)->GetValue() : Activity::AISkillSetting::DefaultSkill); diff --git a/Source/Menus/ScenarioActivityConfigGUI.h b/Source/Menus/ScenarioActivityConfigGUI.h index d3883dd3f..94ccb86cd 100644 --- a/Source/Menus/ScenarioActivityConfigGUI.h +++ b/Source/Menus/ScenarioActivityConfigGUI.h @@ -74,8 +74,6 @@ namespace RTE { Timer m_StartGameButtonBlinkTimer; //!< Timer for blinking the start game button. - bool m_TechListFetched; //!< Whether the tech list was fetched and each team's ComboBox was populated with it, even if no valid tech modules were added. - /// GUI elements that compose the Activity setup box. GUICollectionBox* m_ActivityConfigBox; GUILabel* m_StartErrorLabel; diff --git a/Source/Menus/ScenarioGUI.cpp b/Source/Menus/ScenarioGUI.cpp index 59258d3bb..4115ee342 100644 --- a/Source/Menus/ScenarioGUI.cpp +++ b/Source/Menus/ScenarioGUI.cpp @@ -2,6 +2,7 @@ #include "WindowMan.h" #include "FrameMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "ActivityMan.h" #include "UInputMan.h" @@ -533,9 +534,9 @@ void ScenarioGUI::DrawSitePoints(BITMAP* drawBitmap) const { int blendAmount = 0; for (const Scene* scenePointer: *m_ActivityScenes) { int drawColor = 0; - if (scenePointer->GetModuleID() == g_PresetMan.GetModuleID("Base.rte")) { + if (scenePointer->GetModuleID() == g_ModuleMan.GetModuleID("Base.rte")) { drawColor = c_GUIColorYellow; - } else if (scenePointer->GetModuleID() == g_PresetMan.GetModuleID("Missions.rte")) { + } else if (scenePointer->GetModuleID() == g_ModuleMan.GetModuleID("Missions.rte")) { drawColor = c_GUIColorGreen; } else { drawColor = c_GUIColorCyan; diff --git a/Source/Menus/SceneEditorGUI.cpp b/Source/Menus/SceneEditorGUI.cpp index 763b5509b..854ea92ab 100644 --- a/Source/Menus/SceneEditorGUI.cpp +++ b/Source/Menus/SceneEditorGUI.cpp @@ -2,6 +2,7 @@ #include "CameraMan.h" #include "FrameMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "ActivityMan.h" #include "GameActivity.h" @@ -214,7 +215,7 @@ void SceneEditorGUI::SetModuleSpace(int moduleSpaceID) { } void SceneEditorGUI::SetNativeTechModule(int whichModule) { - if (whichModule >= 0 && whichModule < g_PresetMan.GetTotalModuleCount()) { + if (whichModule >= 0 && whichModule < g_ModuleMan.GetTotalModuleCount()) { m_NativeTechModule = whichModule; m_pPicker->SetNativeTechModule(m_NativeTechModule); } diff --git a/Source/System/Constants.h b/Source/System/Constants.h index 265619817..bbea2bbf8 100644 --- a/Source/System/Constants.h +++ b/Source/System/Constants.h @@ -356,7 +356,7 @@ namespace RTE { {Directions::Right, 0.0F}}; #pragma endregion -#pragma region Un - Definitions +#pragma region Un-Definitions // Allegro defines these via define in astdint.h and Boost with stdlib go crazy so we need to undefine them manually. #undef int8_t #undef uint8_t diff --git a/Source/System/ContentFile.cpp b/Source/System/ContentFile.cpp index cd57c043b..1b70cd2c4 100644 --- a/Source/System/ContentFile.cpp +++ b/Source/System/ContentFile.cpp @@ -1,6 +1,7 @@ #include "ContentFile.h" #include "AudioMan.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "ConsoleMan.h" #include "RTETools.h" @@ -27,7 +28,6 @@ void ContentFile::Clear() { m_DataPathIsImageFile = false; m_FormattedReaderPosition.clear(); m_DataPathAndReaderPosition.clear(); - m_DataModuleID = 0; m_ImageFileInfo.fill(-1); } @@ -42,7 +42,6 @@ int ContentFile::Create(const ContentFile& reference) { m_DataPath = reference.m_DataPath; m_DataPathExtension = reference.m_DataPathExtension; m_DataPathWithoutExtension = reference.m_DataPathWithoutExtension; - m_DataModuleID = reference.m_DataModuleID; return 0; } @@ -73,12 +72,8 @@ int ContentFile::Save(Writer& writer) const { return 0; } -int ContentFile::GetDataModuleID() const { - return (m_DataModuleID < 0) ? g_PresetMan.GetModuleIDFromPath(m_DataPath) : m_DataModuleID; -} - void ContentFile::SetDataPath(const std::string& newDataPath) { - m_DataPath = g_PresetMan.GetFullModulePath(newDataPath); + m_DataPath = g_ModuleMan.GetFullModulePath(newDataPath); m_DataPathExtension = std::filesystem::path(m_DataPath).extension().string(); RTEAssert(!m_DataPathExtension.empty(), "Failed to find file extension when trying to find file with path and name:\n" + m_DataPath + "\n" + GetFormattedReaderPosition()); @@ -87,7 +82,6 @@ void ContentFile::SetDataPath(const std::string& newDataPath) { m_DataPathWithoutExtension = m_DataPath.substr(0, m_DataPath.length() - m_DataPathExtension.length()); s_PathHashes[GetHash()] = m_DataPath; - m_DataModuleID = g_PresetMan.GetModuleIDFromPath(m_DataPath); } size_t ContentFile::GetHash() const { diff --git a/Source/System/ContentFile.h b/Source/System/ContentFile.h index 4a89210fb..28003c183 100644 --- a/Source/System/ContentFile.h +++ b/Source/System/ContentFile.h @@ -62,10 +62,6 @@ namespace RTE { #pragma endregion #pragma region Getters and Setters - /// Gets the ID of the Data Module this file is inside. - /// @return The ID of the DataModule containing this' file. - int GetDataModuleID() const; - /// Gets the file path of the content file represented by this ContentFile object. /// @return A string with the file name path. const std::string& GetDataPath() const { return m_DataPath; } @@ -180,8 +176,6 @@ namespace RTE { std::string m_FormattedReaderPosition; //!< A string containing the currently read file path and the line being read. Formatted to be used for logging. std::string m_DataPathAndReaderPosition; //!< The path to this ContentFile's data file combined with the ini file and line it is being read from. This is used for logging. - int m_DataModuleID; //!< Data Module ID of where this was loaded from. - #pragma region Image Info Getters /// Gets the specified image info from this ContentFile's data file on disk. /// @param infoTypeToGet The image info type to get. See ImageFileInfoType enumeration. diff --git a/Source/System/DataModule.cpp b/Source/System/DataModule.cpp index a2025ce4c..287ed7584 100644 --- a/Source/System/DataModule.cpp +++ b/Source/System/DataModule.cpp @@ -1,4 +1,5 @@ #include "DataModule.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "SceneMan.h" #include "LuaMan.h" @@ -25,7 +26,7 @@ DataModule::~DataModule() { } void DataModule::Clear() { - m_IsUserdata = false; + m_ModuleType = DataModuleType::Unofficial; m_FileName.clear(); m_FriendlyName.clear(); m_Author.clear(); @@ -49,7 +50,6 @@ void DataModule::Clear() { int DataModule::Create(const std::string& moduleName, const ProgressCallback& progressCallback) { m_FileName = std::filesystem::path(moduleName).generic_string(); - m_ModuleID = g_PresetMan.GetModuleID(moduleName); m_CrabToHumanSpawnRatio = 0; // Report that we're starting to read a new DataModule @@ -58,8 +58,8 @@ int DataModule::Create(const std::string& moduleName, const ProgressCallback& pr } Reader reader; - std::string indexPath = g_PresetMan.GetFullModulePath(m_FileName + "/Index.ini"); - std::string mergedIndexPath = g_PresetMan.GetFullModulePath(m_FileName + "/MergedIndex.ini"); + std::string indexPath = g_ModuleMan.GetFullModulePath(m_FileName + "/Index.ini"); + std::string mergedIndexPath = g_ModuleMan.GetFullModulePath(m_FileName + "/MergedIndex.ini"); // NOTE: This looks for the MergedIndex.ini generated by the index merger tool. The tool is mostly superseded by disabling loading visuals, but still provides some benefit. if (std::filesystem::exists(mergedIndexPath)) { @@ -67,7 +67,7 @@ int DataModule::Create(const std::string& moduleName, const ProgressCallback& pr } // If the module is a mod, read only its `index.ini` to validate its SupportedGameVersion. - if (m_ModuleID >= g_PresetMan.GetOfficialModuleCount() && !m_IsUserdata && ReadModuleProperties(moduleName, progressCallback) >= 0) { + if (m_ModuleType == DataModuleType::Unofficial && ReadModuleProperties(moduleName, progressCallback) >= 0) { CheckSupportedGameVersion(); } @@ -88,22 +88,6 @@ int DataModule::Create(const std::string& moduleName, const ProgressCallback& pr return -1; } -bool DataModule::CreateOnDiskAsUserdata(const std::string& moduleName, const std::string_view& friendlyName, bool ignoreMissingItems, bool scanFolderContents) { - std::string moduleNameWithPackageExtension = System::GetUserdataDirectory() + moduleName + (moduleName.ends_with(System::GetModulePackageExtension()) ? "" : System::GetModulePackageExtension()); - if (Writer writer(moduleNameWithPackageExtension + "/Index.ini", false, true); writer.WriterOK()) { - DataModule newModule; - newModule.m_IsUserdata = true; - newModule.m_FriendlyName = friendlyName; - newModule.m_IgnoreMissingItems = ignoreMissingItems; - newModule.m_ScanFolderContents = scanFolderContents; - newModule.Save(writer); - writer.EndWrite(); - } else { - return false; - } - return true; -} - void DataModule::Destroy() { for (const PresetEntry& preset: m_PresetList) { delete preset.m_EntityPreset; @@ -114,7 +98,6 @@ void DataModule::Destroy() { int DataModule::ReadModuleProperties(const std::string& moduleName, const ProgressCallback& progressCallback) { m_FileName = moduleName; - m_ModuleID = g_PresetMan.GetModuleID(moduleName); m_CrabToHumanSpawnRatio = 0; // Report that we're starting to read a new DataModule @@ -187,7 +170,7 @@ int DataModule::ReadProperty(const std::string_view& propName, Reader& reader) { // Check for required dependencies if we're not load properties std::string requiredModule; reader >> requiredModule; - if (!reader.GetSkipIncludes() && g_PresetMan.GetModuleID(requiredModule) == -1) { + if (!reader.GetSkipIncludes() && g_ModuleMan.GetModuleID(requiredModule) == -1) { reader.ReportError("\"" + m_FileName + "\" requires \"" + requiredModule + "\" in order to load!\n"); } }); @@ -223,7 +206,7 @@ int DataModule::Save(Writer& writer) const { writer.NewPropertyWithValue("ModuleName", m_FriendlyName); - if (!m_IsUserdata) { + if (!IsUserdata()) { writer.NewPropertyWithValue("Author", m_Author); writer.NewPropertyWithValue("Description", m_Description); writer.NewPropertyWithValue("IsFaction", m_IsFaction); @@ -438,7 +421,7 @@ void DataModule::ReloadAllScripts() const { int DataModule::FindAndRead(const ProgressCallback& progressCallback) { int result = 0; - const std::string directoryToScan = g_PresetMan.GetFullModulePath(m_FileName); + const std::string directoryToScan = g_ModuleMan.GetFullModulePath(m_FileName); for (const std::filesystem::directory_entry& directoryEntry: std::filesystem::directory_iterator(System::GetWorkingDirectory() + directoryToScan)) { if (directoryEntry.path().extension() == ".ini" && directoryEntry.path().filename() != "Index.ini") { Reader iniReader; diff --git a/Source/System/DataModule.h b/Source/System/DataModule.h index cc2aed372..a9347adb5 100644 --- a/Source/System/DataModule.h +++ b/Source/System/DataModule.h @@ -23,12 +23,20 @@ namespace RTE { /// A representation of a DataModule containing zero or many Material, Effect, Ammo, Device, Actor, or Scene definitions. class DataModule : public Serializable { + friend class ModuleMan; friend struct SystemLuaBindings; public: SerializableClassNameGetter; SerializableOverrideMethods; + /// Enumeration for the different types of DataModules. + enum class DataModuleType { + Unofficial, // Mods and any other modules not shipped with the game. + Official, + Userdata // Userdata written by the game (e.g saved games or editor scenes) that should be ignored anywhere where that is relevant. + }; + /// Struct that holds data about the custom BuyMenu/ObjectPicker theme of this DataModule. /// Themes are used when a DataModule is considered a faction and is selected to be played as in an Activity. struct BuyMenuTheme { @@ -54,14 +62,6 @@ namespace RTE { /// @param progressCallback A function pointer to a function that will be called and sent a string with information about the progress of this DataModule's creation. /// @return An error return value signaling success or any particular failure. Anything below 0 is an error signal. int Create(const std::string& moduleName, const ProgressCallback& progressCallback = nullptr); - - /// Creates a new DataModule directory with "Index.ini" on disk to be used for userdata. Does NOT instantiate the newly created DataModule. - /// @param moduleName File/folder name of the data module, e.g. "MyMod.rte". - /// @param friendlyName Friendly name of the data module, e.g. "My Weapons Mod". - /// @param scanFolderContents Whether module loader should scan for any .ini's inside module folder instead of loading files defined in IncludeFile only. - /// @param ignoreMissingItems Whether module loader should ignore missing items in this module. - /// @return Whether the DataModule was successfully created on disk. - static bool CreateOnDiskAsUserdata(const std::string& moduleName, const std::string_view& friendlyName, bool scanFolderContents = false, bool ignoreMissingItems = false); #pragma endregion #pragma region Destruction @@ -88,12 +88,13 @@ namespace RTE { #pragma endregion #pragma region Module Information Getters + /// Gets whether this DataModule is an official module. + /// @return Whether this DataModule is an official module. + bool IsOfficial() const { return m_ModuleType == DataModuleType::Official; } + /// Gets whether this DataModule is a userdata module. /// @return Whether this DataModule is used for userdata written by the game. - bool IsUserdata() const { return m_IsUserdata; } - - /// Sets this DataModule as a userdata module. - void SetAsUserdata() { m_IsUserdata = true; } + bool IsUserdata() const { return m_ModuleType == DataModuleType::Userdata; } /// Gets the file name of this DataModule, e.g. "MyMod.rte". /// @return A string with the data module file name. @@ -241,7 +242,7 @@ namespace RTE { std::string m_FileReadFrom; //!< Where the instance was read from. }; - bool m_IsUserdata; //!< Whether this DataModule contains userdata written by the game (e.g saved games or editor scenes), meaning it is not an official nor a 3rd party module and is ignored anywhere where that is relevant. + DataModuleType m_ModuleType; //!< The type of this DataModule. See DataModuleType enumeration. bool m_ScanFolderContents; //!< Indicates whether module loader should scan for any .ini's inside module folder instead of loading files defined in IncludeFile only. bool m_IgnoreMissingItems; //!< Indicates whether module loader should ignore missing items in this module. diff --git a/Source/System/Entity.cpp b/Source/System/Entity.cpp index c8f34f15f..00ac9ec1c 100644 --- a/Source/System/Entity.cpp +++ b/Source/System/Entity.cpp @@ -1,8 +1,8 @@ #include "Entity.h" #include "RTETools.h" +#include "ModuleMan.h" #include "PresetMan.h" #include "ConsoleMan.h" -#include "DataModule.h" namespace RTE { @@ -147,7 +147,7 @@ namespace RTE { if (m_DefinedInModule < 0) { return GetPresetName(); } - const DataModule* dataModule = g_PresetMan.GetDataModule(m_DefinedInModule); + const DataModule* dataModule = g_ModuleMan.GetDataModule(m_DefinedInModule); if (!dataModule) { return GetPresetName(); @@ -157,7 +157,7 @@ namespace RTE { std::string Entity::GetModuleName() const { if (m_DefinedInModule >= 0) { - if (const DataModule* dataModule = g_PresetMan.GetDataModule(m_DefinedInModule)) { + if (const DataModule* dataModule = g_ModuleMan.GetDataModule(m_DefinedInModule)) { return dataModule->GetFileName(); } } diff --git a/Source/System/Reader.cpp b/Source/System/Reader.cpp index db3232e38..d5302592b 100644 --- a/Source/System/Reader.cpp +++ b/Source/System/Reader.cpp @@ -1,6 +1,6 @@ #include "Reader.h" #include "ConsoleMan.h" -#include "PresetMan.h" +#include "ModuleMan.h" #include "SettingsMan.h" #include "System.h" @@ -49,12 +49,12 @@ int Reader::Create(const std::string& fileName, bool overwrites, const ProgressC m_DataModuleName = "Base.rte"; m_DataModuleID = 0; } else { - m_FilePath = g_PresetMan.GetFullModulePath(fileName); + m_FilePath = g_ModuleMan.GetFullModulePath(fileName); // Extract the file name and module name from the path m_FileName = m_FilePath.substr(m_FilePath.find_last_of("/\\") + 1); - m_DataModuleName = g_PresetMan.GetModuleNameFromPath(m_FilePath); - m_DataModuleID = g_PresetMan.GetModuleID(m_DataModuleName); + m_DataModuleName = g_ModuleMan.GetModuleNameFromPath(m_FilePath); + m_DataModuleID = g_ModuleMan.GetModuleID(m_DataModuleName); } return Create(std::make_unique(m_FilePath), overwrites, progressCallback, failOK); @@ -81,7 +81,7 @@ int Reader::Create(std::unique_ptr&& stream, bool overwrites, cons } int Reader::GetReadModuleID() const { - return (m_DataModuleID < 0) ? g_PresetMan.GetModuleID(m_DataModuleName) : m_DataModuleID; + return (m_DataModuleID < 0) ? g_ModuleMan.GetModuleID(m_DataModuleName) : m_DataModuleID; } std::string Reader::WholeFileAsString() const { @@ -322,7 +322,7 @@ bool Reader::StartIncludeFile() { } // Get the file path from the current stream before pushing it into the StreamStack, otherwise we can't open a new stream after releasing it because we can't read. - std::string includeFilePath = g_PresetMan.GetFullModulePath(ReadPropValue()); + std::string includeFilePath = g_ModuleMan.GetFullModulePath(ReadPropValue()); // Push the current stream onto the StreamStack for future retrieval when the new include file has run out of data. m_StreamStack.push(StreamInfo(m_Stream.release(), m_FilePath, m_CurrentLine, m_PreviousIndent)); diff --git a/Source/System/System.h b/Source/System/System.h index 4199ce5f0..379ba4761 100644 --- a/Source/System/System.h +++ b/Source/System/System.h @@ -84,7 +84,7 @@ namespace RTE { static bool PathExistsCaseSensitive(const std::string& pathToCheck); #pragma endregion -#pragma region Command - Line Interface +#pragma region Command-Line Interface /// Tells whether printing loading progress report and console to command-line is enabled or not. /// @return Whether printing to command-line is enabled or not. static bool IsLoggingToCLI() { return s_LogToCLI; }