|
|
|
@ -1,5 +1,7 @@
|
|
|
|
|
/** |
|
|
|
|
* Container for the information about available resources from other packages. |
|
|
|
|
* Author: dkanus |
|
|
|
|
* Home repo: https://www.insultplayers.ru/git/AcediaFramework/AcediaCore |
|
|
|
|
* License: GPL |
|
|
|
|
* Copyright 2022-2023 Anton Tarasenko |
|
|
|
|
*------------------------------------------------------------------------------ |
|
|
|
|
* This file is part of Acedia. |
|
|
|
@ -19,35 +21,17 @@
|
|
|
|
|
*/ |
|
|
|
|
class AcediaEnvironment extends AcediaObject; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* # `AcediaEnvironment` |
|
|
|
|
* |
|
|
|
|
* Instance of this class will be used by Acedia to manage resources available |
|
|
|
|
* from different packages like `Feature`s and such other etc.. |
|
|
|
|
* This is mostly necessary to implement Acedia loader (and, possibly, |
|
|
|
|
* its alternatives) that would load available packages and enable `Feature`s |
|
|
|
|
* admin wants to be enabled. |
|
|
|
|
* |
|
|
|
|
* ## Packages |
|
|
|
|
* |
|
|
|
|
* Any package to be used in Acedia should first be *registered* with |
|
|
|
|
* `RegisterPackage()` method. Then a manifest class from it will be read and |
|
|
|
|
* Acedia will become aware of all the resources that package contains. |
|
|
|
|
* Once any of those resources is used, package gets marked as *loaded* and its |
|
|
|
|
* *entry object* (if specified) will be created. |
|
|
|
|
* |
|
|
|
|
* ## `Feature`s |
|
|
|
|
* |
|
|
|
|
* Whether `Feature` is enabled is governed by the `AcediaEnvironment` added |
|
|
|
|
* into the `Global` class. It is possible to create several `Feature` |
|
|
|
|
* instances of the same class instance of each class, but only one can be |
|
|
|
|
* considered enabled at the same time. |
|
|
|
|
*/ |
|
|
|
|
//! API for management of running `Feature`s and loaded packages. |
|
|
|
|
//! |
|
|
|
|
//! Instance of this class will be used by Acedia to manage resources available |
|
|
|
|
//! from different packages like `Feature`s and such other etc.. |
|
|
|
|
//! This is mostly necessary to implement Acedia loader (and, possibly, |
|
|
|
|
//! its alternatives) that would load available packages and enable `Feature`s |
|
|
|
|
//! admin wants to be enabled. |
|
|
|
|
|
|
|
|
|
var private bool acediaShutDown; |
|
|
|
|
|
|
|
|
|
var private array< class<_manifest> > availablePackages; |
|
|
|
|
var private array< class<_manifest> > loadedPackages; |
|
|
|
|
|
|
|
|
|
var private array< class<Feature> > availableFeatures; |
|
|
|
|
var private array<Feature> enabledFeatures; |
|
|
|
@ -65,97 +49,77 @@ var private SimpleSignal onShutdownSystemSignal;
|
|
|
|
|
var private Environment_FeatureEnabled_Signal onFeatureEnabledSignal; |
|
|
|
|
var private Environment_FeatureDisabled_Signal onFeatureDisabledSignal; |
|
|
|
|
|
|
|
|
|
protected function Constructor() |
|
|
|
|
{ |
|
|
|
|
protected function Constructor() { |
|
|
|
|
// Always register our core package |
|
|
|
|
RegisterPackage_S("AcediaCore"); |
|
|
|
|
onShutdownSignal = SimpleSignal( |
|
|
|
|
_.memory.Allocate(class'SimpleSignal')); |
|
|
|
|
onShutdownSystemSignal = SimpleSignal( |
|
|
|
|
_.memory.Allocate(class'SimpleSignal')); |
|
|
|
|
onShutdownSignal = SimpleSignal(_.memory.Allocate(class'SimpleSignal')); |
|
|
|
|
onShutdownSystemSignal = SimpleSignal(_.memory.Allocate(class'SimpleSignal')); |
|
|
|
|
onFeatureEnabledSignal = Environment_FeatureEnabled_Signal( |
|
|
|
|
_.memory.Allocate(class'Environment_FeatureEnabled_Signal')); |
|
|
|
|
onFeatureDisabledSignal = Environment_FeatureDisabled_Signal( |
|
|
|
|
_.memory.Allocate(class'Environment_FeatureDisabled_Signal')); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected function Finalizer() |
|
|
|
|
{ |
|
|
|
|
protected function Finalizer() { |
|
|
|
|
_.memory.Free(onShutdownSignal); |
|
|
|
|
_.memory.Free(onShutdownSystemSignal); |
|
|
|
|
_.memory.Free(onFeatureEnabledSignal); |
|
|
|
|
_.memory.Free(onFeatureDisabledSignal); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Signal that will be emitted before Acedia shuts down. |
|
|
|
|
* At this point all APIs should still exist and function. |
|
|
|
|
* |
|
|
|
|
* [Signature] |
|
|
|
|
* void <slot>() |
|
|
|
|
*/ |
|
|
|
|
/* SIGNAL */ |
|
|
|
|
public final function SimpleSlot OnShutDown(AcediaObject receiver) |
|
|
|
|
{ |
|
|
|
|
/// Signal that will be emitted right before Acedia shuts down. |
|
|
|
|
/// |
|
|
|
|
/// At the point of emission all APIs should still exist and function. |
|
|
|
|
/// |
|
|
|
|
/// # Signature |
|
|
|
|
/// |
|
|
|
|
/// void <slot>() |
|
|
|
|
public final /*signal*/ function SimpleSlot OnShutDown(AcediaObject receiver) { |
|
|
|
|
return SimpleSlot(onShutdownSignal.NewSlot(receiver)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Signal that will be emitted during Acedia shut down. System API use it to |
|
|
|
|
* clean up after themselves, so one shouldn't rely on them. |
|
|
|
|
* |
|
|
|
|
* There is no reason to use this signal unless you're reimplementing one of |
|
|
|
|
* the APIs. Otherwise you probably want to use `OnShutDown()` signal instead. |
|
|
|
|
* |
|
|
|
|
* [Signature] |
|
|
|
|
* void <slot>() |
|
|
|
|
*/ |
|
|
|
|
/* SIGNAL */ |
|
|
|
|
public final function SimpleSlot OnShutDownSystem(AcediaObject receiver) |
|
|
|
|
{ |
|
|
|
|
/// Signal that will be emitted during Acedia shut down. |
|
|
|
|
/// |
|
|
|
|
/// System API will use it to clean up after themselves, so one shouldn't rely on using them. |
|
|
|
|
/// |
|
|
|
|
/// There is no reason to use this signal unless you're reimplementing one of the APIs. |
|
|
|
|
/// Otherwise you probably want to use `OnShutDown()` signal instead. |
|
|
|
|
/// |
|
|
|
|
/// # Signature |
|
|
|
|
/// |
|
|
|
|
/// void <slot>() |
|
|
|
|
public final /*signal*/ function SimpleSlot OnShutDownSystem(AcediaObject receiver) { |
|
|
|
|
return SimpleSlot(onShutdownSystemSignal.NewSlot(receiver)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Signal that will be emitted when new `Feature` is enabled. |
|
|
|
|
* Emitted after `Feature`'s `OnEnabled()` method was called. |
|
|
|
|
* |
|
|
|
|
* [Signature] |
|
|
|
|
* void <slot>(Feature enabledFeature) |
|
|
|
|
* |
|
|
|
|
* @param enabledFeature `Feature` instance that was just enabled. |
|
|
|
|
*/ |
|
|
|
|
/* SIGNAL */ |
|
|
|
|
public final function Environment_FeatureEnabled_Slot OnFeatureEnabled( |
|
|
|
|
AcediaObject receiver) |
|
|
|
|
{ |
|
|
|
|
return Environment_FeatureEnabled_Slot( |
|
|
|
|
onFeatureEnabledSignal.NewSlot(receiver)); |
|
|
|
|
/// Signal that will be emitted right after a new `Feature` is enabled and its `OnEnabled()` method |
|
|
|
|
// was called. |
|
|
|
|
/// |
|
|
|
|
/// # Signature |
|
|
|
|
/// |
|
|
|
|
/// void <slot>(Feature enabledFeature) |
|
|
|
|
/// @param enabledFeature `Feature` instance that was just enabled. |
|
|
|
|
public final /*signal*/ function Environment_FeatureEnabled_Slot OnFeatureEnabled( |
|
|
|
|
AcediaObject receiver |
|
|
|
|
) { |
|
|
|
|
return Environment_FeatureEnabled_Slot(onFeatureEnabledSignal.NewSlot(receiver)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Signal that will be emitted when new `Feature` is disabled. |
|
|
|
|
* Emitted after `Feature`'s `OnDisabled()` method was called. |
|
|
|
|
* |
|
|
|
|
* [Signature] |
|
|
|
|
* void <slot>(class<Feature> disabledFeatureClass) |
|
|
|
|
* |
|
|
|
|
* @param disabledFeatureClass Class of the `Feature` instance that was |
|
|
|
|
* just disabled. |
|
|
|
|
*/ |
|
|
|
|
/* SIGNAL */ |
|
|
|
|
public final function Environment_FeatureDisabled_Slot OnFeatureDisabled( |
|
|
|
|
AcediaObject receiver) |
|
|
|
|
{ |
|
|
|
|
return Environment_FeatureDisabled_Slot( |
|
|
|
|
onFeatureEnabledSignal.NewSlot(receiver)); |
|
|
|
|
/// Signal that will be emitted right after when a `Feature` is disabled and its `OnDisabled()` |
|
|
|
|
/// method was called. |
|
|
|
|
/// |
|
|
|
|
/// # Signature |
|
|
|
|
/// |
|
|
|
|
/// void <slot>(class<Feature> disabledFeatureClass) |
|
|
|
|
/// @param disabledFeatureClass Class of the `Feature` instance that was just disabled. |
|
|
|
|
public final /*signal*/ function Environment_FeatureDisabled_Slot OnFeatureDisabled( |
|
|
|
|
AcediaObject receiver |
|
|
|
|
) { |
|
|
|
|
return Environment_FeatureDisabled_Slot(onFeatureEnabledSignal.NewSlot(receiver)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Shuts AcediaCore down, performing all the necessary cleaning up. |
|
|
|
|
*/ |
|
|
|
|
public final function Shutdown() |
|
|
|
|
{ |
|
|
|
|
/// Shuts AcediaCore down, performing all the necessary clean up. |
|
|
|
|
public final function Shutdown() { |
|
|
|
|
local LevelCore core; |
|
|
|
|
|
|
|
|
|
if (acediaShutDown) { |
|
|
|
@ -176,18 +140,16 @@ public final function Shutdown()
|
|
|
|
|
acediaShutDown = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Registers an Acedia package with name given by `packageName`. |
|
|
|
|
* |
|
|
|
|
* @param packageName Name of the package to register. Must not be `none`. |
|
|
|
|
* This package must exist and not have yet been registered in this |
|
|
|
|
* environment. |
|
|
|
|
* @return `true` if package was successfully registered, `false` if it |
|
|
|
|
* either does not exist, was already registered or `packageName` is |
|
|
|
|
* `none`. |
|
|
|
|
*/ |
|
|
|
|
public final function bool RegisterPackage(BaseText packageName) |
|
|
|
|
{ |
|
|
|
|
/// Registers an Acedia package wit ha given name. |
|
|
|
|
/// |
|
|
|
|
/// Returns `true` if package was successfully registered, `false` if it either does not exist, |
|
|
|
|
/// was already registered or [`packageName`] is `none`. |
|
|
|
|
/// |
|
|
|
|
/// # Errors |
|
|
|
|
/// |
|
|
|
|
/// Will log an error if the package has failed to get registered (it is either missing or not |
|
|
|
|
/// an Acedia package). |
|
|
|
|
public final function bool RegisterPackage(BaseText packageName) { |
|
|
|
|
local class<_manifest> manifestClass; |
|
|
|
|
|
|
|
|
|
if (packageName == none) { |
|
|
|
@ -196,13 +158,11 @@ public final function bool RegisterPackage(BaseText packageName)
|
|
|
|
|
_.logger.Auto(infoRegisteringPackage).Arg(packageName.Copy()); |
|
|
|
|
manifestClass = class<_manifest>(DynamicLoadObject( |
|
|
|
|
packageName.ToString() $ manifestSuffix, class'Class', true)); |
|
|
|
|
if (manifestClass == none) |
|
|
|
|
{ |
|
|
|
|
if (manifestClass == none) { |
|
|
|
|
_.logger.Auto(errNotRegistered).Arg(packageName.Copy()); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (IsManifestRegistered(manifestClass)) |
|
|
|
|
{ |
|
|
|
|
if (IsManifestRegistered(manifestClass)) { |
|
|
|
|
_.logger.Auto(infoAlreadyRegistered).Arg(packageName.Copy()); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
@ -211,17 +171,16 @@ public final function bool RegisterPackage(BaseText packageName)
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Registers an Acedia package with name given by `packageName`. |
|
|
|
|
* |
|
|
|
|
* @param packageName Name of the package to register. |
|
|
|
|
* This package must exist and not have yet been registered in this |
|
|
|
|
* environment. |
|
|
|
|
* @return `true` if package was successfully registered, `false` if it |
|
|
|
|
* either does not exist or was already registered. |
|
|
|
|
*/ |
|
|
|
|
public final function RegisterPackage_S(string packageName) |
|
|
|
|
{ |
|
|
|
|
/// Registers an Acedia package wit ha given name. |
|
|
|
|
/// |
|
|
|
|
/// Returns `true` if package was successfully registered, `false` if it either does not exist or |
|
|
|
|
/// was already registered. |
|
|
|
|
/// |
|
|
|
|
/// # Errors |
|
|
|
|
/// |
|
|
|
|
/// Will log an error if the package has failed to get registered (it is either missing or not |
|
|
|
|
/// an Acedia package). |
|
|
|
|
public final function RegisterPackage_S(string packageName) { |
|
|
|
|
local Text wrapper; |
|
|
|
|
|
|
|
|
|
wrapper = _.text.FromString(packageName); |
|
|
|
@ -229,12 +188,10 @@ public final function RegisterPackage_S(string packageName)
|
|
|
|
|
_.memory.Free(wrapper); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private final function bool IsManifestRegistered(class<_manifest> manifestClass) |
|
|
|
|
{ |
|
|
|
|
private final function bool IsManifestRegistered(class<_manifest> manifestClass) { |
|
|
|
|
local int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < availablePackages.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < availablePackages.length; i += 1) { |
|
|
|
|
if (manifestClass == availablePackages[i]) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -242,72 +199,35 @@ private final function bool IsManifestRegistered(class<_manifest> manifestClass)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private final function ReadManifest(class<_manifest> manifestClass) |
|
|
|
|
{ |
|
|
|
|
private final function ReadManifest(class<_manifest> manifestClass) { |
|
|
|
|
local int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < manifestClass.default.features.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < manifestClass.default.features.length; i += 1) { |
|
|
|
|
if (manifestClass.default.features[i] == none) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
manifestClass.default.features[i].static.LoadConfigs(); |
|
|
|
|
availableFeatures[availableFeatures.length] = |
|
|
|
|
manifestClass.default.features[i]; |
|
|
|
|
availableFeatures[availableFeatures.length] = manifestClass.default.features[i]; |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < manifestClass.default.testCases.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
class'TestingService'.static |
|
|
|
|
.RegisterTestCase(manifestClass.default.testCases[i]); |
|
|
|
|
for (i = 0; i < manifestClass.default.testCases.length; i += 1) { |
|
|
|
|
class'TestingService'.static.RegisterTestCase(manifestClass.default.testCases[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns all packages registered in the caller `AcediaEnvironment`. |
|
|
|
|
* |
|
|
|
|
* NOTE: package being registered doesn't mean it's actually loaded. |
|
|
|
|
* Package must either be explicitly loaded or automatically when one of its |
|
|
|
|
* resources is being used. |
|
|
|
|
* |
|
|
|
|
* @return All packages registered in caller `AcediaEnvironment`. |
|
|
|
|
*/ |
|
|
|
|
public final function array< class<_manifest> > GetAvailablePackages() |
|
|
|
|
{ |
|
|
|
|
/// Returns all packages registered in the caller [`AcediaEnvironment`]. |
|
|
|
|
public final function array< class<_manifest> > GetAvailablePackages() { |
|
|
|
|
return availablePackages; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns all packages loaded in the caller `AcediaEnvironment`. |
|
|
|
|
* |
|
|
|
|
* NOTE: package being registered doesn't mean it's actually loaded. |
|
|
|
|
* Package must either be explicitly loaded or automatically when one of its |
|
|
|
|
* resources is being used. |
|
|
|
|
* |
|
|
|
|
* @return All packages loaded in caller `AcediaEnvironment`. |
|
|
|
|
*/ |
|
|
|
|
public final function array< class<_manifest> > GetLoadedPackages() |
|
|
|
|
{ |
|
|
|
|
return loadedPackages; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns all `Feature`s available in the caller `AcediaEnvironment`. |
|
|
|
|
* |
|
|
|
|
* @return All `Feature`s available in the caller `AcediaEnvironment`. |
|
|
|
|
*/ |
|
|
|
|
public final function array< class<Feature> > GetAvailableFeatures() |
|
|
|
|
{ |
|
|
|
|
/// Returns all [`Feature`]s available in the caller `AcediaEnvironment`. |
|
|
|
|
public final function array< class<Feature> > GetAvailableFeatures() { |
|
|
|
|
return availableFeatures; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns all `Feature` instances enabled in the caller `AcediaEnvironment`. |
|
|
|
|
* |
|
|
|
|
* @return All `Feature`s enabled in the caller `AcediaEnvironment`. |
|
|
|
|
*/ |
|
|
|
|
public final function array<Feature> GetEnabledFeatures() |
|
|
|
|
{ |
|
|
|
|
/// Returns all currently enabled [`Feature`]s. |
|
|
|
|
public final function array<Feature> GetEnabledFeatures() { |
|
|
|
|
local int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) { |
|
|
|
|
enabledFeatures[i].NewRef(); |
|
|
|
|
} |
|
|
|
@ -319,42 +239,32 @@ public final function array<Feature> GetEnabledFeatures()
|
|
|
|
|
private final function CleanEnabledFeatures() |
|
|
|
|
{ |
|
|
|
|
local int i; |
|
|
|
|
while (i < enabledFeatures.length) |
|
|
|
|
{ |
|
|
|
|
if ( enabledFeatures[i].GetLifeVersion() |
|
|
|
|
!= enabledFeaturesLifeVersions[i]) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
while (i < enabledFeatures.length) { |
|
|
|
|
if (enabledFeatures[i].GetLifeVersion() != enabledFeaturesLifeVersions[i]) { |
|
|
|
|
enabledFeatures.Remove(i, 1); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
i += 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Checks if `Feature` of given class `featureClass` is enabled. |
|
|
|
|
* |
|
|
|
|
* NOTE: even if If feature of class `featureClass` is enabled, it's not |
|
|
|
|
* necessarily that the instance you have reference to is enabled. |
|
|
|
|
* Although unlikely, it is possible that someone spawned another instance |
|
|
|
|
* of the same class that isn't considered enabled. If you want to check |
|
|
|
|
* whether some particular instance of given class `featureClass` is enabled, |
|
|
|
|
* use `IsFeatureEnabled()` method instead. |
|
|
|
|
* |
|
|
|
|
* @param featureClass Feature class to check for being enabled. |
|
|
|
|
* @return `true` if feature of class `featureClass` is currently enabled and |
|
|
|
|
* `false` otherwise. |
|
|
|
|
*/ |
|
|
|
|
public final function bool IsFeatureClassEnabled(class<Feature> featureClass) |
|
|
|
|
{ |
|
|
|
|
/// Checks if `Feature` of given class is enabled. |
|
|
|
|
/// |
|
|
|
|
/// Even if If feature of class `featureClass` is enabled, it's not necessarily that the instance |
|
|
|
|
/// you have reference to is enabled. |
|
|
|
|
/// |
|
|
|
|
/// Although unlikely, it is possible that someone spawned another instance of the same class that |
|
|
|
|
/// isn't considered enabled. If you want to check whether some particular instance of given class |
|
|
|
|
/// [`featureClass`] is enabled, use [`IsFeatureEnabled()`] method instead. |
|
|
|
|
public final function bool IsFeatureClassEnabled(class<Feature> featureClass) { |
|
|
|
|
local int i; |
|
|
|
|
|
|
|
|
|
if (featureClass == none) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
CleanEnabledFeatures(); |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) { |
|
|
|
|
if (featureClass == enabledFeatures[i].class) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -362,26 +272,18 @@ public final function bool IsFeatureClassEnabled(class<Feature> featureClass)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Checks if given `Feature` instance is enabled. |
|
|
|
|
* |
|
|
|
|
* If you want to check if any instance instance of given class |
|
|
|
|
* `classToCheck` is enabled (and not `feature` specifically), use |
|
|
|
|
* `IsFeatureClassEnabled()` method instead. |
|
|
|
|
* |
|
|
|
|
* @param feature Feature instance to check for being enabled. |
|
|
|
|
* @return `true` if feature `feature` is currently enabled and |
|
|
|
|
* `false` otherwise. |
|
|
|
|
*/ |
|
|
|
|
public final function bool IsFeatureEnabled(Feature feature) |
|
|
|
|
{ |
|
|
|
|
/// Checks if given `Feature` instance is enabled. |
|
|
|
|
/// |
|
|
|
|
/// If you want to check if any instance instance of given class `classToCheck` is enabled |
|
|
|
|
/// (and not [`feature`] specifically), use [`IsFeatureClassEnabled()`] method instead. |
|
|
|
|
public final function bool IsFeatureEnabled(Feature feature) { |
|
|
|
|
local int i; |
|
|
|
|
|
|
|
|
|
if (feature == none) return false; |
|
|
|
|
if (!feature.IsAllocated()) return false; |
|
|
|
|
|
|
|
|
|
CleanEnabledFeatures(); |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) { |
|
|
|
|
if (feature == enabledFeatures[i]) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -389,24 +291,17 @@ public final function bool IsFeatureEnabled(Feature feature)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns enabled `Feature` instance of the given class `featureClass`. |
|
|
|
|
* |
|
|
|
|
* @param featureClass Feature class to find enabled instance for. |
|
|
|
|
* @return Enabled `Feature` instance of the given class `featureClass`. |
|
|
|
|
* If no feature of `featureClass` is enabled, returns `none`. |
|
|
|
|
*/ |
|
|
|
|
public final function Feature GetEnabledFeature(class<Feature> featureClass) |
|
|
|
|
{ |
|
|
|
|
/// Returns enabled `Feature` instance of the given class. |
|
|
|
|
/// |
|
|
|
|
/// Returns `none` only if `featureClass` is not enabled (or also `none`). |
|
|
|
|
public final function Feature GetEnabledFeature(class<Feature> featureClass) { |
|
|
|
|
local int i; |
|
|
|
|
if (featureClass == none) { |
|
|
|
|
return none; |
|
|
|
|
} |
|
|
|
|
CleanEnabledFeatures(); |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
if (featureClass == enabledFeatures[i].class) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) { |
|
|
|
|
if (featureClass == enabledFeatures[i].class) { |
|
|
|
|
enabledFeatures[i].NewRef(); |
|
|
|
|
return enabledFeatures[i]; |
|
|
|
|
} |
|
|
|
@ -414,41 +309,26 @@ public final function Feature GetEnabledFeature(class<Feature> featureClass)
|
|
|
|
|
return none; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Enables given `Feature` instance `newEnabledFeature` with a given config. |
|
|
|
|
* Does not change a config for already enabled feature, failing instead. |
|
|
|
|
* |
|
|
|
|
* @see `Feature::EnableMe()`. |
|
|
|
|
* |
|
|
|
|
* @param newEnabledFeature Instance to enable. |
|
|
|
|
* @param configName Name of the config to enable `newEnabledFeature` |
|
|
|
|
* feature with. `none` means "default" config (will be created, if |
|
|
|
|
* necessary). |
|
|
|
|
* @return `true` if given `newEnabledFeature` was enabled and `false` |
|
|
|
|
* otherwise (including if feature of the same class has already been |
|
|
|
|
* enabled). |
|
|
|
|
*/ |
|
|
|
|
public final function bool EnableFeature( |
|
|
|
|
Feature newEnabledFeature, |
|
|
|
|
BaseText configName) |
|
|
|
|
{ |
|
|
|
|
/// Enables given `Feature` instance `newEnabledFeature` with a given config. |
|
|
|
|
/// Does not change a config for already enabled feature, failing instead. |
|
|
|
|
/// |
|
|
|
|
/// Returns `true` if given `newEnabledFeature` was enabled and `false` otherwise |
|
|
|
|
/// (including if feature of the same class has already been enabled). |
|
|
|
|
public final function bool EnableFeature(Feature newEnabledFeature, optional BaseText configName) { |
|
|
|
|
local int i; |
|
|
|
|
|
|
|
|
|
if (newEnabledFeature == none) return false; |
|
|
|
|
if (!newEnabledFeature.IsAllocated()) return false; |
|
|
|
|
|
|
|
|
|
CleanEnabledFeatures(); |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
if (newEnabledFeature.class == enabledFeatures[i].class) |
|
|
|
|
{ |
|
|
|
|
if (newEnabledFeature == enabledFeatures[i]) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) { |
|
|
|
|
if (newEnabledFeature.class == enabledFeatures[i].class) { |
|
|
|
|
if (newEnabledFeature == enabledFeatures[i]) { |
|
|
|
|
_.logger |
|
|
|
|
.Auto(warnFeatureAlreadyEnabled) |
|
|
|
|
.Arg(_.text.FromClass(newEnabledFeature.class)); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
else { |
|
|
|
|
_.logger |
|
|
|
|
.Auto(errFeatureClassAlreadyEnabled) |
|
|
|
|
.Arg(_.text.FromClass(newEnabledFeature.class)); |
|
|
|
@ -465,26 +345,19 @@ public final function bool EnableFeature(
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Disables given `Feature` instance `featureToDisable`. |
|
|
|
|
* |
|
|
|
|
* @see `Feature::EnableMe()`. |
|
|
|
|
* |
|
|
|
|
* @param featureToDisable Instance to disable. |
|
|
|
|
* @return `true` if given `newEnabledFeature` was disabled and `false` |
|
|
|
|
* otherwise (including if it already was disabled). |
|
|
|
|
*/ |
|
|
|
|
public final function bool DisableFeature(Feature featureToDisable) |
|
|
|
|
{ |
|
|
|
|
/// Disables given `Feature` instance `featureToDisable`. |
|
|
|
|
/// |
|
|
|
|
/// Returns `true` if given `newEnabledFeature` was disabled and `false` otherwise |
|
|
|
|
/// (including if it already was disabled). |
|
|
|
|
public final function bool DisableFeature(Feature featureToDisable) { |
|
|
|
|
local int i; |
|
|
|
|
|
|
|
|
|
if (featureToDisable == none) return false; |
|
|
|
|
if (!featureToDisable.IsAllocated()) return false; |
|
|
|
|
|
|
|
|
|
CleanEnabledFeatures(); |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
if (featureToDisable == enabledFeatures[i]) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) { |
|
|
|
|
if (featureToDisable == enabledFeatures[i]) { |
|
|
|
|
enabledFeatures.Remove(i, 1); |
|
|
|
|
enabledFeaturesLifeVersions.Remove(i, 1); |
|
|
|
|
featureToDisable.DisableInternal(); |
|
|
|
@ -496,13 +369,10 @@ public final function bool DisableFeature(Feature featureToDisable)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Disables all currently enabled `Feature`s. |
|
|
|
|
* |
|
|
|
|
* Mainly intended for the clean up when Acedia shuts down. |
|
|
|
|
*/ |
|
|
|
|
public final function DisableAllFeatures() |
|
|
|
|
{ |
|
|
|
|
/// Disables all currently enabled `Feature`s. |
|
|
|
|
/// |
|
|
|
|
/// Mainly intended for the clean up when Acedia shuts down. |
|
|
|
|
public final function DisableAllFeatures() { |
|
|
|
|
local int i; |
|
|
|
|
local array<Feature> featuresCopy; |
|
|
|
|
|
|
|
|
@ -510,8 +380,7 @@ public final function DisableAllFeatures()
|
|
|
|
|
featuresCopy = enabledFeatures; |
|
|
|
|
enabledFeatures.length = 0; |
|
|
|
|
enabledFeaturesLifeVersions.length = 0; |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < enabledFeatures.length; i += 1) { |
|
|
|
|
featuresCopy[i].DisableInternal(); |
|
|
|
|
onFeatureDisabledSignal.Emit(featuresCopy[i].class); |
|
|
|
|
} |
|
|
|
|