/** * This actor's role is to perform Acedia's server startup. * Copyright 2019-2023 Anton Tarasenko * 2023 Shtoyan *------------------------------------------------------------------------------ * This file is part of Acedia. * * Acedia is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License, or * (at your option) any later version. * * Acedia is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ class StartUp extends Actor dependson(Packages); // Acedia's reference to a `Global` object. var private Global _; var private ServerGlobal _server; // Responsible for setting up Acedia's game modes in current voting system var private VotingHandlerAdapter votingAdapter; var private LoggerAPI.Definition infoFeatureEnabled; var private LoggerAPI.Definition errorCannotRunTests; function PreBeginPlay() { super.PreBeginPlay(); InitializeServer(); if (level != none && level.game != none) { level.game.AddMutator(string(class'AcediaLauncherMut')); } } public function VotingHandlerAdapter GetVotingHandlerAdapter() { if (votingAdapter != none) { votingAdapter.NewRef(); } return votingAdapter; } private function InitializeServer() { local int i; local GameMode currentGameMode; local array availableFeatures; if (class'Packages'.default.clientside) { AddToPackageMap("AcediaLauncher"); } CheckForGarbage(); // Launch and setup core Acedia _ = class'Global'.static.GetInstance(); _server = class'ServerGlobal'.static.GetInstance(); class'ServerLevelCore'.static.CreateLevelCore(self); class'MapList'.static.Initialize(); for (i = 0; i < class'Packages'.default.package.length; i += 1) { _.environment.RegisterPackage_S(class'Packages'.default.package[i]); } if (class'TestingService'.default.runTestsOnStartUp) { RunStartUpTests(); } // Determine required features and launch them availableFeatures = GetAutoConfigurationInfo(); if (class'Packages'.default.useGameModes) { class'GameMode'.static.Initialize(); votingAdapter = VotingHandlerAdapter( _.memory.Allocate(class'VotingHandlerAdapter')); currentGameMode = votingAdapter.SetupGameModeAfterTravel(); if (currentGameMode != none) { currentGameMode.UpdateFeatureArray(availableFeatures); } } EnableFeatures(availableFeatures); } // Checks whether Acedia has left garbage after the previous map. // This can lead to serious problems, so such diagnostic check is warranted. private function CheckForGarbage() { local int leftoverObjectAmount; local int leftoverActorAmount; local int leftoverDBRAmount; local AcediaObject nextObject; local AcediaActor nextActor; local DBRecord nextRecord; foreach AllObjects(class'AcediaObject', nextObject) { leftoverObjectAmount += 1; } foreach AllActors(class'AcediaActor', nextActor) { leftoverActorAmount += 1; } foreach AllObjects(class'DBRecord', nextRecord) { leftoverDBRAmount += 1; } if ( leftoverObjectAmount == 0 && leftoverActorAmount == 0 && leftoverDBRAmount == 0) { Log("Acedia garbage check: nothing was found."); } else { Log("Acedia garbage check: garbage was found." @ "This can cause problems, report it."); Log("Leftover object:" @ leftoverObjectAmount); Log("Leftover actors:" @ leftoverActorAmount); Log("Leftover database records:" @ leftoverDBRAmount); } } public function array GetAutoConfigurationInfo() { local int i; local Text autoConfig; local array< class > availableFeatures; local Packages.FeatureConfigPair nextPair; local array result; availableFeatures = _.environment.GetAvailableFeatures(); for (i = 0; i < availableFeatures.length; i += 1) { autoConfig = availableFeatures[i].static.GetAutoEnabledConfig(); if (autoConfig != none) { nextPair.featureClass = availableFeatures[i]; nextPair.configName = autoConfig; result[result.length] = nextPair; } } return result; } private function EnableFeatures(array features) { local int i; local Text defaultConfigName; local Text nextConfigName; defaultConfigName = _.text.FromString("default"); for (i = 0; i < features.length; i += 1) { if (features[i].featureClass == none) { continue; } // `configName` being `none` here means that config name was not // specified through config and we should fallback to "default" if (features[i].configName == none) { nextConfigName = defaultConfigName.Copy(); } else { nextConfigName = features[i].configName.Copy(); } features[i].featureClass.static.EnableMe(nextConfigName); _.logger.Auto(infoFeatureEnabled) .Arg(_.text.FromString(string(features[i].featureClass))) .Arg(nextConfigName); // consumes `nextConfigName` } defaultConfigName.FreeSelf(); } private final function RunStartUpTests() { local TestingService testService; testService = TestingService(class'TestingService'.static.Require()); testService.PrepareTests(); if (testService.filterTestsByName) { testService.FilterByName(testService.requiredName); } if (testService.filterTestsByGroup) { testService.FilterByGroup(testService.requiredGroup); } if (!testService.Run()) { _.logger.Auto(errorCannotRunTests); } } defaultproperties { // This is a server-only actor remoteRole = ROLE_None infoFeatureEnabled = (l=LOG_Info,m="Feature `%1` enabled with config \"%2\".") errorCannotRunTests = (l=LOG_Error,m="Could not perform Acedia's tests.") }