Browse Source

Add `UnrealAPI` with low-level auxiliary methods

pull/8/head
Anton Tarasenko 4 years ago
parent
commit
ce3e060416
  1. 3
      sources/Global.uc
  2. 31
      sources/Manifest.uc
  3. 25
      sources/Unreal/Tests/MockGameRulesA.uc
  4. 25
      sources/Unreal/Tests/MockGameRulesB.uc
  5. 25
      sources/Unreal/Tests/MockInventoryA.uc
  6. 25
      sources/Unreal/Tests/MockInventoryAChild.uc
  7. 25
      sources/Unreal/Tests/MockInventoryB.uc
  8. 230
      sources/Unreal/Tests/TEST_UnrealAPI.uc
  9. 246
      sources/Unreal/UnrealAPI.uc

3
sources/Global.uc

@ -29,7 +29,7 @@ var public RefAPI ref;
var public BoxAPI box; var public BoxAPI box;
var public LoggerAPI logger; var public LoggerAPI logger;
var public CollectionsAPI collections; var public CollectionsAPI collections;
//var public JSONAPI json; var public UnrealAPI unreal;
var public AliasesAPI alias; var public AliasesAPI alias;
var public TextAPI text; var public TextAPI text;
var public MemoryAPI memory; var public MemoryAPI memory;
@ -59,6 +59,7 @@ protected function Initialize()
box = BoxAPI(memory.Allocate(class'BoxAPI')); box = BoxAPI(memory.Allocate(class'BoxAPI'));
text = TextAPI(memory.Allocate(class'TextAPI')); text = TextAPI(memory.Allocate(class'TextAPI'));
collections = CollectionsAPI(memory.Allocate(class'CollectionsAPI')); collections = CollectionsAPI(memory.Allocate(class'CollectionsAPI'));
unreal = UnrealAPI(memory.Allocate(class'UnrealAPI'));
logger = LoggerAPI(memory.Allocate(class'LoggerAPI')); logger = LoggerAPI(memory.Allocate(class'LoggerAPI'));
alias = AliasesAPI(memory.Allocate(class'AliasesAPI')); alias = AliasesAPI(memory.Allocate(class'AliasesAPI'));
console = ConsoleAPI(memory.Allocate(class'ConsoleAPI')); console = ConsoleAPI(memory.Allocate(class'ConsoleAPI'));

31
sources/Manifest.uc

@ -34,19 +34,20 @@ defaultproperties
testCases(0) = class'TEST_Base' testCases(0) = class'TEST_Base'
testCases(1) = class'TEST_Boxes' testCases(1) = class'TEST_Boxes'
testCases(2) = class'TEST_Refs' testCases(2) = class'TEST_Refs'
testCases(3) = class'TEST_Aliases' testCases(3) = class'TEST_UnrealAPI'
testCases(4) = class'TEST_ColorAPI' testCases(4) = class'TEST_Aliases'
testCases(5) = class'TEST_Text' testCases(5) = class'TEST_ColorAPI'
testCases(6) = class'TEST_TextAPI' testCases(6) = class'TEST_Text'
testCases(7) = class'TEST_Parser' testCases(7) = class'TEST_TextAPI'
testCases(8) = class'TEST_JSON' testCases(8) = class'TEST_Parser'
testCases(9) = class'TEST_TextCache' testCases(9) = class'TEST_JSON'
testCases(10) = class'TEST_User' testCases(10) = class'TEST_TextCache'
testCases(11) = class'TEST_Memory' testCases(11) = class'TEST_User'
testCases(12) = class'TEST_DynamicArray' testCases(12) = class'TEST_Memory'
testCases(13) = class'TEST_AssociativeArray' testCases(13) = class'TEST_DynamicArray'
testCases(14) = class'TEST_Iterator' testCases(14) = class'TEST_AssociativeArray'
testCases(15) = class'TEST_Command' testCases(15) = class'TEST_Iterator'
testCases(16) = class'TEST_CommandDataBuilder' testCases(16) = class'TEST_Command'
testCases(17) = class'TEST_LogMessage' testCases(17) = class'TEST_CommandDataBuilder'
testCases(18) = class'TEST_LogMessage'
} }

25
sources/Unreal/Tests/MockGameRulesA.uc

@ -0,0 +1,25 @@
/**
* Mock `GameRules` class for testing `UnrealAPI` and it' methods for
* adding / removing `GameRules`.
* Copyright 2021 Anton Tarasenko
*------------------------------------------------------------------------------
* 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 <https://www.gnu.org/licenses/>.
*/
class MockGameRulesA extends GameRules;
defaultproperties
{
}

25
sources/Unreal/Tests/MockGameRulesB.uc

@ -0,0 +1,25 @@
/**
* Mock `GameRules` class for testing `UnrealAPI` and it's methods for
* adding / removing `GameRules`.
* Copyright 2021 Anton Tarasenko
*------------------------------------------------------------------------------
* 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 <https://www.gnu.org/licenses/>.
*/
class MockGameRulesB extends GameRules;
defaultproperties
{
}

25
sources/Unreal/Tests/MockInventoryA.uc

@ -0,0 +1,25 @@
/**
* Mock inventory class for testing `UnrealAPI` and it's methods for
* adding / removing `GameRules`.
* Copyright 2021 Anton Tarasenko
*------------------------------------------------------------------------------
* 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 <https://www.gnu.org/licenses/>.
*/
class MockInventoryA extends Inventory;
defaultproperties
{
}

25
sources/Unreal/Tests/MockInventoryAChild.uc

@ -0,0 +1,25 @@
/**
* Mock inventory class for testing `UnrealAPI` and it's methods for
* adding / removing `GameRules`.
* Copyright 2021 Anton Tarasenko
*------------------------------------------------------------------------------
* 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 <https://www.gnu.org/licenses/>.
*/
class MockInventoryAChild extends MockInventoryA;
defaultproperties
{
}

25
sources/Unreal/Tests/MockInventoryB.uc

@ -0,0 +1,25 @@
/**
* Mock inventory class for testing `UnrealAPI` and it's methods for
* adding / removing `GameRules`.
* Copyright 2021 Anton Tarasenko
*------------------------------------------------------------------------------
* 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 <https://www.gnu.org/licenses/>.
*/
class MockInventoryB extends Inventory;
defaultproperties
{
}

230
sources/Unreal/Tests/TEST_UnrealAPI.uc

@ -0,0 +1,230 @@
/**
* Set of tests for `UnrealAPI` class.
* Copyright 2021 Anton Tarasenko
*------------------------------------------------------------------------------
* 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 <https://www.gnu.org/licenses/>.
*/
class TEST_UnrealAPI extends TestCase;
protected static function int CountRulesAmount(class<GameRules> gameRulesClass)
{
local int counter;
local GameRules rulesIter;
if (gameRulesClass == none) {
return 0;
}
rulesIter = __().unreal.GetGameType().gameRulesModifiers;
while (rulesIter != none)
{
if (rulesIter.class == gameRulesClass) {
counter += 1;
}
rulesIter = rulesIter.nextGameRules;
}
return counter;
}
protected static function TESTS()
{
Test_GameType();
Test_GameRules();
Test_InventoryChainFetching();
}
protected static function Test_GameType()
{
Context("Testing methods for returning `GameType` class.");
Issue("`GetGameType()` returns `none`.");
TEST_ExpectNotNone(__().unreal.GetGameType());
Issue("`GetKFGameType()` returns `none`.");
TEST_ExpectNotNone(__().unreal.GetKFGameType());
Issue("`GetGameType()` and `GetKFGameType()` return different values.");
TEST_ExpectTrue(__().unreal.GetGameType() == __().unreal.GetKFGameType());
}
protected static function Test_GameRules()
{
Context("Testing methods for working with `GameRules`.");
SubTest_AddRemoveGameRules();
SubTest_CheckGameRules();
}
protected static function SubTest_AddRemoveGameRules()
{
Issue("`AddGameRules()` does not add game rules.");
__().unreal.AddGameRules(class'MockGameRulesA');
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 1);
__().unreal.AddGameRules(class'MockGameRulesA');
Issue("Calling `AddGameRules()` twice leads to rule duplication.");
TEST_ExpectFalse(CountRulesAmount(class'MockGameRulesA') > 1);
Issue("Calling `AddGameRules()` leads to rule not being added.");
TEST_ExpectFalse(CountRulesAmount(class'MockGameRulesA') == 0);
Issue("Adding new rules with `AddGameRules()` does not work properly.");
__().unreal.AddGameRules(class'MockGameRulesB');
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 1);
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesB') == 1);
Issue("Adding/removing rules with `RemoveGameRules()` leads to" @
"unexpected results.");
__().unreal.RemoveGameRules(class'MockGameRulesB');
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 1);
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesB') == 0);
__().unreal.AddGameRules(class'MockGameRulesB');
__().unreal.RemoveGameRules(class'MockGameRulesA');
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 0);
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesB') == 1);
__().unreal.RemoveGameRules(class'MockGameRulesB');
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 0);
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesB') == 0);
}
protected static function SubTest_CheckGameRules()
{
local string issueForAdded, issueForNotAdded;
issueForAdded = "`AreGameRulesAdded()` returns `false` for rules that are" @
"currently added.";
issueForNotAdded = "`AreGameRulesAdded()` returns `true` for rules that" @
"are not currently added.";
__().unreal.RemoveGameRules(class'MockGameRulesA');
__().unreal.RemoveGameRules(class'MockGameRulesB');
Issue(issueForNotAdded);
TEST_ExpectFalse(__().unreal.AreGameRulesAdded(class'MockGameRulesA'));
TEST_ExpectFalse(__().unreal.AreGameRulesAdded(class'MockGameRulesB'));
__().unreal.AddGameRules(class'MockGameRulesB');
Issue(issueForNotAdded);
TEST_ExpectFalse(__().unreal.AreGameRulesAdded(class'MockGameRulesA'));
Issue(issueForAdded);
TEST_ExpectTrue(__().unreal.AreGameRulesAdded(class'MockGameRulesB'));
__().unreal.AddGameRules(class'MockGameRulesA');
Issue(issueForAdded);
TEST_ExpectTrue(__().unreal.AreGameRulesAdded(class'MockGameRulesA'));
TEST_ExpectTrue(__().unreal.AreGameRulesAdded(class'MockGameRulesB'));
__().unreal.RemoveGameRules(class'MockGameRulesB');
Issue(issueForAdded);
TEST_ExpectTrue(__().unreal.AreGameRulesAdded(class'MockGameRulesA'));
Issue(issueForNotAdded);
TEST_ExpectFalse(__().unreal.AreGameRulesAdded(class'MockGameRulesB'));
}
protected static function Test_InventoryChainFetching()
{
local Inventory chainStart, chainEnd;
// a - B - A - a - B - a - A,
// where A = `MockInventoryA`
// a = `MockInventoryAChild`
// B = `MockInventoryB`
chainStart = Inventory(__().memory.Allocate(class'MockInventoryAChild'));
chainEnd = chainStart;
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryB'));
chainEnd = chainEnd.inventory;
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryA'));
chainEnd = chainEnd.inventory;
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryAChild'));
chainEnd = chainEnd.inventory;
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryB'));
chainEnd = chainEnd.inventory;
chainEnd.inventory =
Inventory(__().memory.Allocate(class'MockInventoryAChild'));
chainEnd = chainEnd.inventory;
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryA'));
chainEnd = chainEnd.inventory;
Context("Testing auxiliary methods for working with inventory chains.");
SubTest_InventoryChainFetchingSingle(chainStart);
SubTest_InventoryChainFetchingMany(chainStart);
}
protected static function SubTest_InventoryChainFetchingSingle(Inventory chain)
{
Issue("Does not find correct first entry inside the inventory chain.");
TEST_ExpectTrue(
__().unreal.GetInventoryFrom(class'MockInventoryA', chain)
== chain.inventory.inventory);
TEST_ExpectTrue(
__().unreal.GetInventoryFrom(class'MockInventoryB', chain)
== chain.inventory);
TEST_ExpectTrue(
__().unreal.GetInventoryFrom(class'MockInventoryAChild', chain)
== chain);
Issue("Incorrectly finds missing inventory entries.");
TEST_ExpectNone(__().unreal.GetInventoryFrom(none, chain));
TEST_ExpectNone(__().unreal.GetInventoryFrom(class'Winchester', chain));
Issue("Does not find correct first entry inside the inventory chain when" @
"allowing for child classes.");
TEST_ExpectTrue(
__().unreal.GetInventoryFrom(class'MockInventoryA', chain, true)
== chain);
TEST_ExpectTrue(
__().unreal.GetInventoryFrom(class'MockInventoryB', chain, true)
== chain.inventory);
TEST_ExpectTrue(
__().unreal.GetInventoryFrom(class'MockInventoryAChild', chain, true)
== chain);
Issue("Incorrectly finds missing inventory entries when allowing for" @
"child classes.");
TEST_ExpectNone(__().unreal.GetInventoryFrom(none, chain, true));
TEST_ExpectNone(__().unreal.GetInventoryFrom( class'Winchester', chain,
true));
}
protected static function SubTest_InventoryChainFetchingMany(Inventory chain)
{
local array<Inventory> result;
Issue("Does not find correct entries inside the inventory chain.");
result = __().unreal.GetAllInventoryFrom(class'MockInventoryB', chain);
TEST_ExpectTrue(result.length == 2);
TEST_ExpectTrue(result[0] == chain.inventory);
TEST_ExpectTrue(result[1] == chain.inventory.inventory.inventory.inventory);
Issue("Does not find correct entries inside the inventory chain when" @
"allowing for child classes.");
result =
__().unreal.GetAllInventoryFrom(class'MockInventoryB', chain, true);
TEST_ExpectTrue(result.length == 2);
TEST_ExpectTrue(result[0] == chain.inventory);
TEST_ExpectTrue(result[1] == chain.inventory.inventory.inventory.inventory);
result =
__().unreal.GetAllInventoryFrom(class'MockInventoryA', chain, true);
TEST_ExpectTrue(result.length == 5);
TEST_ExpectTrue(result[0] == chain);
TEST_ExpectTrue(result[1] == chain.inventory.inventory);
TEST_ExpectTrue(result[2] == chain.inventory.inventory.inventory);
TEST_ExpectTrue(
result[3]
== chain.inventory.inventory.inventory.inventory.inventory);
TEST_ExpectTrue(
result[4]
== chain.inventory.inventory.inventory.inventory.inventory.inventory);
Issue("Does not return empty array for non-existing inventory class.");
result = __().unreal.GetAllInventoryFrom(class'Winchester', chain);
TEST_ExpectTrue(result.length == 0);
result = __().unreal.GetAllInventoryFrom(class'Winchester', chain, true);
TEST_ExpectTrue(result.length == 0);
}
defaultproperties
{
caseName = "UnrealAPI"
caseGroup = "Unreal"
}

246
sources/Unreal/UnrealAPI.uc

@ -0,0 +1,246 @@
/**
* Low-level API that provides set of utility methods for working with
* unreal script classes.
* Copyright 2021 Anton Tarasenko
*------------------------------------------------------------------------------
* 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 <https://www.gnu.org/licenses/>.
*/
class UnrealAPI extends AcediaObject;
/**
* Returns current game's `LevelInfo`. Useful because `level` variable
* is not defined inside objects.
*
* @return `LevelInfo` instance for the current game. Guaranteed to
* not be `none`.
*/
public final function LevelInfo GetLevel()
{
return class'CoreService'.static.GetInstance().level;
}
/**
* Returns current game's `GameInfo`. Useful because `level.game` is not
* accessible inside objects.
*
* @return `GameInfo` instance for the current game. Guaranteed to
* not be `none`.
*/
public final function GameInfo GetGameType()
{
return class'CoreService'.static.GetInstance().level.game;
}
/**
* Returns current game's `GameInfo` as `KFGameType`. Useful because
* `level.game` is not accessible inside objects and because it auto converts
* game type to `KFGameType`, which virtually all mods for killing floor use
* (by itself or as a base class).
*
* @return `KFGameType` instance for the current game. Can be `none` only if
* game was modded to run a `GameInfo` not derived from `KFGameType`.
*/
public final function KFGameType GetKFGameType()
{
return KFGameType(GetGameType());
}
/**
* Returns current local player's `Controller`. Useful because `level`
* is not accessible inside objects.
*
* @return `PlayerController` instance for the local player. `none` iff run on
* dedicated servers.
*/
public final function PlayerController GetLocalPlayer()
{
return class'CoreService'.static.GetInstance().level
.GetLocalPlayerController();
}
/**
* Checks if given class of `GameRules` is currently active in `GameInfo`.
*
* @param rulesClassToCheck Class of rules to check for.
* @return `true` if `GameRules` are active and `false` otherwise.
*/
public final function bool AreGameRulesAdded(
class<GameRules> rulesClassToCheck)
{
local GameRules rulesIter;
if (rulesClassToCheck == none) {
return false;
}
rulesIter = GetGameType().gameRulesModifiers;
while (rulesIter != none)
{
if (rulesIter.class == rulesClassToCheck) {
return true;
}
rulesIter = rulesIter.nextGameRules;
}
return false;
}
/**
* Adds new `GameRules` class to the current `GameInfo`.
* Does nothing if give `GameRules` class was already added before.
*
* @param newRulesClass Class of rules to add.
* @return `true` if `GameRules` were added and `false` otherwise
* (because they were already active.)
*/
public final function bool AddGameRules(class<GameRules> newRulesClass)
{
if (AreGameRulesAdded(newRulesClass)) {
return false;
}
GetGameType().AddGameModifier(GameRules(_.memory.Allocate(newRulesClass)));
return true;
}
/**
* Removes given `GameRules` class from the current `GameInfo`,
* if they are active. Does nothing otherwise.
*
* @param rulesClassToRemove Class of rules to try and remove.
* @return `true` if `GameRules` were removed and `false` otherwise
* (if they were not active in the first place).
*/
public final function bool RemoveGameRules(class<GameRules> rulesClassToRemove)
{
local GameInfo game;
local GameRules rulesIter;
local GameRules rulesToDestroy;
if (rulesClassToRemove == none) return false;
game = GetGameType();
if (game.gameRulesModifiers == none) return false;
// Check root rules
rulesToDestroy = game.gameRulesModifiers;
if (rulesToDestroy.class == rulesClassToRemove)
{
game.gameRulesModifiers = rulesToDestroy.nextGameRules;
rulesToDestroy.Destroy();
return true;
}
// Check rest of the rules
rulesIter = game.gameRulesModifiers;
while (rulesIter != none)
{
rulesToDestroy = rulesIter.nextGameRules;
if ( rulesToDestroy != none
&& rulesToDestroy.class == rulesClassToRemove)
{
rulesIter.nextGameRules = rulesToDestroy.nextGameRules;
rulesToDestroy.Destroy();
return true;
}
rulesIter = rulesIter.nextGameRules;
}
return false;
}
/**
* Convenience method for finding a first inventory entry of the given
* class `inventoryClass` in the given inventory chain `inventoryChain`.
*
* Inventory is stored as a linked list, where next inventory item is available
* through the `inventory` reference. This method follows this list, starting
* from `inventoryChain` until it finds `Inventory` of the appropriate class
* or reaches the end of the list.
*
* @param inventoryClass Class of the inventory we are interested in.
* @param inventoryChain Inventory chain in which we should search for
* the given class.
* @param acceptChildClass `true` if method should also return any
* `Inventory` of class derived from `inventoryClass` and `false` if
* we want given class specifically (default).
* @return First inventory from `inventoryChain` that matches given
* `inventoryClass` class (whether exactly or as a child class,
* in case `acceptChildClass == true`).
*/
public final function Inventory GetInventoryFrom(
class<Inventory> inventoryClass,
Inventory inventoryChain,
optional bool acceptChildClass)
{
if (inventoryClass == none) {
return none;
}
while (inventoryChain != none)
{
if (inventoryChain.class == inventoryClass) {
return inventoryChain;
}
if ( acceptChildClass
&& ClassIsChildOf(inventoryChain.class, inventoryClass))
{
return inventoryChain;
}
inventoryChain = inventoryChain.inventory;
}
return none;
}
/**
* Convenience method for finding a all inventory entries of the given
* class `inventoryClass` in the given inventory chain `inventoryChain`.
*
* Inventory is stored as a linked list, where next inventory item is available
* through the `inventory` reference. This method follows this list, starting
* from `inventoryChain` until the end of the list.
*
* @param inventoryClass Class of the inventory we are interested in.
* @param inventoryChain Inventory chain in which we should search for
* the given class.
* @param acceptChildClass `true` if method should also return any
* `Inventory` of class derived from `inventoryClass` and `false` if
* we want given class specifically (default).
* @return Array of inventory items from `inventoryChain` that match given
* `inventoryClass` class (whether exactly or as a child class,
* in case `acceptChildClass == true`).
*/
public final function array<Inventory> GetAllInventoryFrom(
class<Inventory> inventoryClass,
Inventory inventoryChain,
optional bool acceptChildClass)
{
local bool shouldAdd;
local array<Inventory> result;
if (inventoryClass == none) {
return result;
}
while (inventoryChain != none)
{
shouldAdd = false;
if (inventoryChain.class == inventoryClass) {
shouldAdd = true;
}
else if (acceptChildClass) {
shouldAdd = ClassIsChildOf(inventoryChain.class, inventoryClass);
}
if (shouldAdd) {
result[result.length] = inventoryChain;
}
inventoryChain = inventoryChain.inventory;
}
return result;
}
defaultproperties
{
}
Loading…
Cancel
Save