Anton Tarasenko
4 years ago
9 changed files with 619 additions and 16 deletions
@ -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 |
||||
{ |
||||
} |
@ -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 |
||||
{ |
||||
} |
@ -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 |
||||
{ |
||||
} |
@ -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 |
||||
{ |
||||
} |
@ -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 |
||||
{ |
||||
} |
@ -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" |
||||
} |
@ -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…
Reference in new issue