Browse Source

Fix style of `Iter` and all related classes

core_refactor
Anton Tarasenko 2 years ago
parent
commit
a6738c55ad
  1. 3
      sources/Aliases/Aliases.uc
  2. 86
      sources/BaseRealm/Iter.uc
  3. 13
      sources/Data/Collections/ArrayListIterator.uc
  4. 13
      sources/Data/Collections/HashTableIterator.uc
  5. 6
      sources/Data/Collections/Tests/TEST_Iterator.uc
  6. 48
      sources/Gameplay/BaseClasses/Frontend/World/EntityIterator.uc
  7. 126
      sources/Gameplay/KF1Frontend/World/KF1_TracingIterator.uc

3
sources/Aliases/Aliases.uc

@ -98,7 +98,8 @@ protected function ReadOtherSources(HashTable otherSourcesData)
local HashTableIterator iter;
customSource.length = 0;
iter = HashTableIterator(otherSourcesData.Iterate().LeaveOnlyNotNone());
iter = HashTableIterator(otherSourcesData.Iterate());
iter.LeaveOnlyNotNone();
for (iter = iter; !iter.HasFinished(); iter.Next())
{
key = iter.GetKey();

86
sources/BaseRealm/Iter.uc

@ -1,7 +1,8 @@
/**
* Base class for iterator, an auxiliary object for iterating through
* a set of objects obtained from some context-dependent source.
* Copyright 2022 Anton Tarasenko
* Author: dkanus
* Home repo: https://www.insultplayers.ru/git/AcediaFramework/AcediaCore
* License: GPL
* Copyright 2022-2023 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@ -21,56 +22,47 @@
class Iter extends AcediaObject
abstract;
/**
* Iterators can filter objects they're iterating on by a presence or lack of
* a certain property, recording this choice requires 3 values, so `bool`
* isn't enough and we need to use this `enum` instead.
*/
enum IterFilter
{
// We don't use relevant property for filtering
ITF_Nothing,
// Iterated objects must have that property
ITF_Have,
// Iterated objects must not have that property
ITF_NotHave
//! Base class for iterator, an auxiliary object for iterating through
//! a set of objects obtained from some context-dependent source.
/// Status of the [`Iter`]'s filter regarding some specific property.
///
/// [`Iter`]s can filter objects they're iterating on by the presence or lack of a certain property,
/// recording this choice requires 3 values (for requiring having/not having a certain property and
/// for ignoring it).
/// This enumeration is for inner purposes and is there to unify iterator implementations.
enum IterFilter {
/// We don't use relevant property for filtering
IF_Nothing,
/// Iterated objects must have that property
IF_Have,
/// Iterated objects must not have that property
IF_NotHave
};
/**
* Makes iterator pick next item.
* Use `HasFinished()` to check whether you have iterated all of them.
*
* @return Reference to caller `Iterator` to allow for method chaining.
*/
public function Iter Next();
/// Advances iterator to the next item.
///
/// Makes iterator refer to the next item from the source and returns `true`, as long as the source
/// of items isn't yet exhausted.
/// In case there's no more items, method has to return `false` and do nothing else.
/// [`Iter::HasFinished()`] can also be used to check whether there are more items available.
public function bool Next();
/**
* Returns current value pointed to by an iterator.
*
* Does not advance iteration: use `Next()` to pick next value.
*
* @return Current value being iterated over. If `Iterator()` has finished
* iterating over all values or was not initialized - returns `none`.
* Note that depending on context `none` values can also be returned,
* use `LeaveOnlyNotNone()` method to prevent that.
*/
/// Returns value currently pointed to by an iterator.
///
/// Does not advance iteration: use [`Iter::Next()`] to pick next value.
///
/// In case iterator has already reached the end (and [`Iter::Next()``] returned `false`), this
/// method will return `none`.
/// Note that depending on context `none` values can also be returned, use
/// [`Iter::LeaveOnlyNotNone()`] method to prevent that.
public function AcediaObject Get();
/**
* Checks if caller `Iterator` has finished iterating.
*
* @return `true` if caller `Iterator` has finished iterating or
* was not initialized. `false` otherwise.
*/
/// Checks if caller [`Iter`] has finished iterating.
public function bool HasFinished();
/**
* Makes caller iterator skip any `none` items during iteration.
*
* @return Reference to caller `Iterator` to allow for method chaining.
*/
public function Iter LeaveOnlyNotNone();
/// Makes caller iterator skip any `none` items during iteration.
public function LeaveOnlyNotNone();
defaultproperties
{
defaultproperties {
}

13
sources/Data/Collections/ArrayListIterator.uc

@ -1,6 +1,6 @@
/**
* Iterator for iterating over `ArrayList`'s items.
* Copyright 2022 Anton Tarasenko
* Copyright 2022-2023 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@ -41,30 +41,29 @@ public function bool Initialize(Collection relevantArray)
return true;
}
public function Iter LeaveOnlyNotNone()
public function LeaveOnlyNotNone()
{
skipNoneReferences = true;
return self;
}
public function Iter Next()
public function bool Next()
{
local int collectionLength;
if (!skipNoneReferences)
{
currentIndex += 1;
return self;
return HasFinished();
}
collectionLength = relevantCollection.GetLength();
while (currentIndex < collectionLength)
{
currentIndex += 1;
if (!relevantCollection.IsNone(currentIndex)) {
return self;
return HasFinished();
}
}
return self;
return HasFinished();
}
public function AcediaObject Get()

13
sources/Data/Collections/HashTableIterator.uc

@ -1,6 +1,6 @@
/**
* Iterator for iterating over `HashTable`'s items.
* Copyright 2022 Anton Tarasenko
* Copyright 2022-2023 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@ -51,30 +51,29 @@ public function bool Initialize(Collection relevantArray)
return true;
}
public function Iter LeaveOnlyNotNone()
public function LeaveOnlyNotNone()
{
skipNoneReferences = true;
return self;
}
public function Iter Next()
public function bool Next()
{
local int collectionLength;
if (!skipNoneReferences)
{
hasNotFinished = relevantCollection.IncrementIndex(currentIndex);
return self;
return HasFinished();
}
collectionLength = relevantCollection.GetLength();
while (hasNotFinished)
{
hasNotFinished = relevantCollection.IncrementIndex(currentIndex);
if (relevantCollection.IsSomethingByIndex(currentIndex)) {
return self;
return HasFinished();
}
}
return self;
return HasFinished();
}
public function AcediaObject Get()

6
sources/Data/Collections/Tests/TEST_Iterator.uc

@ -108,7 +108,8 @@ protected static function Test_ArrayList()
Issue("Iterator for empty `ArrayList` does not return `none` as"
@ "a current item.");
TEST_ExpectNone(iter.Get());
TEST_ExpectNone(iter.Next().Get());
iter.Next();
TEST_ExpectNone(iter.Get());
for (i = 0; i < default.items.length; i += 1) {
array.AddItem(default.items[i]);
@ -142,7 +143,8 @@ protected static function Test_HashTable()
Issue("Iterator for empty `HashTable` does not return `none` as"
@ "a current item.");
TEST_ExpectNone(iter.Get());
TEST_ExpectNone(iter.Next().Get());
iter.Next();
TEST_ExpectNone(iter.Get());
for (i = 0; i < default.items.length; i += 1) {
array.SetItem(__().box.int(i), default.items[i]);

48
sources/Gameplay/BaseClasses/Frontend/World/EntityIterator.uc

@ -54,81 +54,61 @@ public function EPawn GetPawn();
/**
* Makes caller iterator skip any entities that do not support `EPawn`
* interface during iteration.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyPawns();
public function LeaveOnlyPawns();
/**
* Makes caller iterator skip any entities that support `EPawn` interface
* during iteration.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyNonPawns();
public function LeaveOnlyNonPawns();
/**
* Makes caller iterator skip any entities that are placeable (support
* `EPlaceable` interface) in the game.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyPlaceables();
public function LeaveOnlyPlaceables();
/**
* Makes caller iterator skip any entities that are not placeable (don't
* support `EPlaceable` interface) into the game world.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyNonPlaceables();
public function LeaveOnlyNonPlaceables();
/**
* Makes caller iterator skip any entities that are not visible in the game
* world.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyVisible();
public function LeaveOnlyVisible();
/**
* Makes caller iterator skip any entities that are visible in the game
* world.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyInvisible();
public function LeaveOnlyInvisible();
/**
* Makes caller iterator skip any entities that are able to collide with other
* entities in the game world.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyColliding();
public function LeaveOnlyColliding();
/**
* Makes caller iterator skip any entities that are unable to collide with
* other entities in the game world.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyNonColliding();
public function LeaveOnlyNonColliding();
/**
* Makes caller iterator skip any non-static entities that do not change over
* time, leaving only dynamic ones.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyStatic();
public function LeaveOnlyStatic();
/**
* Makes caller iterator skip any static entities that do not change over time.
*
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyDynamic();
public function LeaveOnlyDynamic();
/**
* Leaves only placeable entities that are located no further than `radius`
@ -140,9 +120,8 @@ public function EntityIterator LeaveOnlyDynamic();
* close to.
* @param radius Maximum distance that entities are allowed to be away
* from `location`.
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyNearby(
public function LeaveOnlyNearby(
EPlaceable placeable,
float radius);
@ -155,9 +134,8 @@ public function EntityIterator LeaveOnlyNearby(
* @param location Location to which entities must be close to.
* @param radius Maximum distance that entities are allowed to be away
* from `location`.
* @return Reference to caller `EntityIterator` to allow for method chaining.
*/
public function EntityIterator LeaveOnlyNearbyToLocation(
public function LeaveOnlyNearbyToLocation(
Vector location,
float radius);
@ -166,7 +144,7 @@ public function EntityIterator LeaveOnlyNearbyToLocation(
*
* `placeable` must have collisions enabled for any entity to touch it.
*/
public function EntityIterator LeaveOnlyTouching(EPlaceable placeable);
public function LeaveOnlyTouching(EPlaceable placeable);
defaultproperties
{

126
sources/Gameplay/KF1Frontend/World/KF1_TracingIterator.uc

@ -2,7 +2,7 @@
* `EntityIterator` / `TracingIterator` implementation for `KF1_Frontend`.
* Both iterators do essentially the same and can be implemented with
* a single class.
* Copyright 2022 Anton Tarasenko
* Copyright 2022-2023 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@ -112,11 +112,11 @@ protected function Finalizer()
iterated = false;
// Clear conditions
// ~ Simple conditions
pawnsFilter = ITF_Nothing;
placeablesFilter = ITF_Nothing;
collidingFilter = ITF_Nothing;
visibleFilter = ITF_Nothing;
staticFilter = ITF_Nothing;
pawnsFilter = IF_Nothing;
placeablesFilter = IF_Nothing;
collidingFilter = IF_Nothing;
visibleFilter = IF_Nothing;
staticFilter = IF_Nothing;
// ~ Distance conditions
distanceCheck = false;
_.memory.Free(shortestLimitation.placeable);
@ -162,7 +162,7 @@ public final function InitializeTracing(Vector start, Vector end)
}
startPosition = start;
endPosition = end;
collidingFilter = ITF_Have;
collidingFilter = IF_Have;
initialized = true;
tracingIterator = true;
}
@ -237,30 +237,30 @@ private final function bool ProcessActor(
if (allowedList.length > 0 && IsAllowed(nextActor, allowedList)) {
return false;
}
if (staticFilter == ITF_Have && !nextActor.bStatic) {
if (staticFilter == IF_Have && !nextActor.bStatic) {
return false;
}
if (staticFilter == ITF_NotHave && nextActor.bStatic) {
if (staticFilter == IF_NotHave && nextActor.bStatic) {
return false;
}
isCollidable = (nextActor.bCollideActors || (LevelInfo(nextActor) != none));
if (collidingFilter == ITF_Have && !isCollidable) {
if (collidingFilter == IF_Have && !isCollidable) {
return false;
}
if (collidingFilter == ITF_NotHave && isCollidable) {
if (collidingFilter == IF_NotHave && isCollidable) {
return false;
}
if (placeablesFilter == ITF_Have && nextActor.bWorldGeometry) {
if (placeablesFilter == IF_Have && nextActor.bWorldGeometry) {
return false;
}
if (placeablesFilter == ITF_NotHave && !nextActor.bWorldGeometry) {
if (placeablesFilter == IF_NotHave && !nextActor.bWorldGeometry) {
return false;
}
isVisible = IsActorVisible(nextActor);
if (visibleFilter == ITF_Have && !isVisible) {
if (visibleFilter == IF_Have && !isVisible) {
return false;
}
if (visibleFilter == ITF_NotHave && isVisible) {
if (visibleFilter == IF_NotHave && isVisible) {
return false;
}
if (distanceCheck && !IsCloseEnough(nextActor)) {
@ -395,7 +395,7 @@ private final function TryIterating()
return;
}
core = ServerLevelCore(class'ServerLevelCore'.static.GetInstance());
if (pawnsFilter == ITF_Have) {
if (pawnsFilter == IF_Have) {
targetClass = class'Pawn';
}
else {
@ -456,7 +456,7 @@ private final function DoIterate_PickBest(
// preferable, but only doable if we're also filtering by distance.
if (distanceCheck)
{
if (collidingFilter == ITF_Have) {
if (collidingFilter == IF_Have) {
DoIterate_Colliding(core, targetClass);
}
else {
@ -466,7 +466,7 @@ private final function DoIterate_PickBest(
return;
}
// If above fails - try to at least limit iteration to dynamic actors
if (staticFilter == ITF_NotHave)
if (staticFilter == IF_NotHave)
{
DoIterate_Dynamic(core, targetClass);
return;
@ -581,14 +581,13 @@ private final function DoIterate_All(
}
}
public function Iter Next()
public function bool Next()
{
if (!initialized) {
return self;
return false;
}
TryIterating();
currentIndex += 1;
return self;
return HasFinished();
}
public function AcediaObject Get()
@ -655,11 +654,10 @@ public function bool HasFinished()
return (currentIndex >= foundActors.length);
}
public function Iter LeaveOnlyNotNone()
public function LeaveOnlyNotNone()
{
// We cannot iterate over `none` actors with native iterators, so this
// condition is automatically satisfied
return self;
}
private final function UpdateFilter(
@ -669,8 +667,8 @@ private final function UpdateFilter(
if (!initialized) return;
if (iterated) return;
if (actualValue == ITF_Nothing) {
actualValue = ITF_Have;
if (actualValue == IF_Nothing) {
actualValue = IF_Have;
}
else if (actualValue != newValue)
{
@ -679,65 +677,54 @@ private final function UpdateFilter(
}
}
public function EntityIterator LeaveOnlyPawns()
public function LeaveOnlyPawns()
{
UpdateFilter(pawnsFilter, ITF_Have);
return self;
UpdateFilter(pawnsFilter, IF_Have);
}
public function EntityIterator LeaveOnlyNonPawns()
public function LeaveOnlyNonPawns()
{
UpdateFilter(pawnsFilter, ITF_NotHave);
return self;
UpdateFilter(pawnsFilter, IF_NotHave);
}
public function EntityIterator LeaveOnlyPlaceables()
public function LeaveOnlyPlaceables()
{
UpdateFilter(placeablesFilter, ITF_Have);
return self;
UpdateFilter(placeablesFilter, IF_Have);
}
public function EntityIterator LeaveOnlyNonPlaceables()
public function LeaveOnlyNonPlaceables()
{
UpdateFilter(placeablesFilter, ITF_NotHave);
return self;
UpdateFilter(placeablesFilter, IF_NotHave);
}
public function EntityIterator LeaveOnlyVisible()
public function LeaveOnlyVisible()
{
UpdateFilter(visibleFilter, ITF_Have);
return self;
UpdateFilter(visibleFilter, IF_Have);
}
public function EntityIterator LeaveOnlyInvisible()
public function LeaveOnlyInvisible()
{
UpdateFilter(visibleFilter, ITF_NotHave);
return self;
UpdateFilter(visibleFilter, IF_NotHave);
}
public function EntityIterator LeaveOnlyColliding()
public function LeaveOnlyColliding()
{
UpdateFilter(collidingFilter, ITF_Have);
return self;
UpdateFilter(collidingFilter, IF_Have);
}
public function EntityIterator LeaveOnlyNonColliding()
public function LeaveOnlyNonColliding()
{
UpdateFilter(collidingFilter, ITF_NotHave);
return self;
UpdateFilter(collidingFilter, IF_NotHave);
}
public function EntityIterator LeaveOnlyStatic()
public function LeaveOnlyStatic()
{
UpdateFilter(staticFilter, ITF_Have);
return self;
UpdateFilter(staticFilter, IF_Have);
}
public function EntityIterator LeaveOnlyDynamic()
public function LeaveOnlyDynamic()
{
UpdateFilter(staticFilter, ITF_NotHave);
return self;
UpdateFilter(staticFilter, IF_NotHave);
}
private function AddDistanceLimitation(NearbyLimitation newLimitation)
@ -761,15 +748,15 @@ private function AddDistanceLimitation(NearbyLimitation newLimitation)
}
}
public function EntityIterator LeaveOnlyNearby(
public function LeaveOnlyNearby(
EPlaceable placeable,
float radius)
{
local NearbyLimitation newLimitation;
if (!initialized) return self;
if (iterated) return self;
if (placeable == none) return self;
if (!initialized) return;
if (iterated) return;
if (placeable == none) return;
placeable.NewRef();
newLimitation.placeable = placeable;
@ -777,35 +764,32 @@ public function EntityIterator LeaveOnlyNearby(
newLimitation.distance = radius;
newLimitation.distanceSquared = radius * radius;
AddDistanceLimitation(newLimitation);
return self;
}
public function EntityIterator LeaveOnlyNearbyToLocation(
public function LeaveOnlyNearbyToLocation(
Vector location,
float radius)
{
local NearbyLimitation newLimitation;
if (!initialized) return self;
if (iterated) return self;
if (!initialized) return;
if (iterated) return;
newLimitation.location = location;
newLimitation.distance = radius;
newLimitation.distanceSquared = radius * radius;
AddDistanceLimitation(newLimitation);
return self;
}
public function EntityIterator LeaveOnlyTouching(EPlaceable placeable)
public function LeaveOnlyTouching(EPlaceable placeable)
{
if (!initialized) return self;
if (iterated) return self;
if (placeable == none) return self;
if (!initialized) return;
if (iterated) return;
if (placeable == none) return;
touchingCheck = true;
placeable.NewRef();
touchers[touchers.length] = placeable;
return self;
}
defaultproperties

Loading…
Cancel
Save