Deleting list items within an Iterator

Discussions about Coding and Scripting
User avatar
Barbie
Godlike
Posts: 2912
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Deleting list items within an Iterator

Post by Barbie »

I would like to have a peer review if this construction to delete list items within an iterator is safe. In my mind it is, but as we say: four eyes see more than two ;o)

Code: Select all

function DropAll(class<actor> DropClass) { // Drops all Actors of given DropClass and its sub classes.
local Actor A;

	do
	{
		foreach AllActors(Dropclass, A)
		{
			log(self @ "DropAll: Dropping " @ A);
			A.Destroy();
			break;
		}
	} until (A == None);
}
(See http://wiki.beyondunreal.com/ForEach_loop#Pitfalls for my decision using extra do ... until loop.)
"If Origin not in center it be not in center." --Buggie
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Deleting list items within an Iterator

Post by sektor2111 »

I gotta clock this function to see if is not lazy because of conditions added to iterator. Foreach is not very slow, but I cannot say it's faster one. Comparing it with PawnList in a Level with 1000 Pawns, <foreach> is really faster. Adding <do - until> I don't think can accelerate it since iterator has a default speed and it's probably really slower.
User avatar
Shadow
Masterful
Posts: 744
Joined: Tue Jan 29, 2008 12:00 am
Personal rank: Mad Carpenter
Location: Germany

Re: Deleting list items within an Iterator

Post by Shadow »

doing stuff like this would be better in c++ code, iterators are slow and a mess
concerning the pawn list: epic's intention was to have a fast list of items (creatures in this case) with a manageable count of elements (100+), linked lists are slower with many elements (1000+) - that's why the actor list is a dynamic array, and the pawn list is a partial quantity of that list, that's why it's faster

accessing the actor list in c++ allows to enter it directly through a for loop not being necessary to use slow iterators (just my 2 cents)
Image
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Deleting list items within an Iterator

Post by Higor »

First things first.
Do_Until isn't doing anything there.
AllActors iterators alone is fine, otherwise your game will crash as soon as you hit a bStatic or bNoDelete actor
User avatar
Barbie
Godlike
Posts: 2912
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Deleting list items within an Iterator

Post by Barbie »

Thanks for the replies. Using PawnList is not an option, because I use that function for more than Pawns (DropAll(class 'CTFFlag') e.g.)
Speed is also not important due to its purpose - that function is called only once per undesired class and per map and before game starts.
bStatic or bNoDelete
Oh, I didn't consider these and have to test that. What about changing these values before dropping?

Code: Select all

log(self @ "DropAll: Dropping " @ A);
A.bStatic = false;
A.bNoDelete = false;
A.Destroy();
break;
Do_Until isn't doing anything there.
On every deleted object the foreach-loop is left by break and then the variable containing that just destroyed object is compared with None. So I have to investigate what happens to the value of a variable that points to an Actor that was destroyed meanwhile...

I used this Do-Until-construction because deleting or adding items to a list that is just iterated might confuse the iterator (see "Pitfalls" above also). As long as I don't know the implementation of that iterator IMO this Do-Until-constructions seems to be the only safe way to modify an iterated list.
"If Origin not in center it be not in center." --Buggie
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Deleting list items within an Iterator

Post by sektor2111 »

Did those compile ?

Code: Select all

log(self @ "DropAll: Dropping " @ A);
A.bStatic = false; //Interesting
A.bNoDelete = false; //Really Interesting - In which engine are available these ?
A.Destroy();
break;
Then I see Break which means stop iterator. Then iterator will restart until (A == None). Nah, Too much useless things for nothing and I think is like a doggy slow iterating multiple times.

How about a fake trash:

Code: Select all

foreach allactors (class 'Something', A)
{
if (!A.bStatic && !A.bNoDelete)
{
A.Destroy();
}
else //Watch this...
{
A.SetCollisionSize(0,0);
A.SetCollision(false,false,false);
A.Disable('Touch');
A.Disable('Trigger');
A.Disable('Tick');
A.Disable('Timer');
A.Tag='';
A.bHidden = True;
//Good Night Mr. A - Cya at garbage collector...
}
}
Anything else ? Like I said multiple times: Simple is better.
Now I have figured that <do...until> is not for iterators. An Iterator will work by itself alone checking stuff inside and setting up things correctly rather than a crash or a console spam.
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Deleting list items within an Iterator

Post by Higor »

Btw the game will react badly to your code if the actor has this code...

Code: Select all

var bool bGetRekt;

event Destroyed()
{
   if ( !default.bGetRekt )
       Log("WTF you tryin' to destroy me?, lemme shove this up yours...");
   default.bGetRekt = true;
   Spawn( class); //HA HA HA x1
   Spawn( class); //HA HA HA x2
   Spawn( class); //HA HA HA x3
}
Image
User avatar
Chamberly
Godlike
Posts: 1963
Joined: Sat Sep 17, 2011 4:32 pm
Personal rank: Dame. Vandora
Location: TN, USA

Re: Deleting list items within an Iterator

Post by Chamberly »

Lmao :loool:
Image
Image
Image Edit: Why does my sig not work anymore?
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Re: Deleting list items within an Iterator

Post by MrLoathsome »

Somebody try this:

Code: Select all

event Destroyed()
{
   if ( !default.bGetRekt )
       Log("WTF you tryin' to destroy me?, lemme shove this up yours...");
   default.bGetRekt = true;
   Spawn( class); //HA HA HA x1
   Self.Destroyed();
}
blarg
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Deleting list items within an Iterator

Post by sektor2111 »

I have verified already if UScript can call "Event" and looks like it doesn't really call events, but C++ can do more. I have an attempt and what was shown at Wiki was true. Else a mountain of mods would just mess up with crashes.
User avatar
Barbie
Godlike
Posts: 2912
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Deleting list items within an Iterator

Post by Barbie »

sektor2111 wrote:Did those compile ?
Yes, successfully compiled with Brain-08.15, but it seems not fully compatible to Ucc. As Because bStatic and bNoDelete are constants, Ucc rejects compiling.
sektor2111 wrote:A.Disable('Timer');
This has helped me with another matter, thanks.

Thanks to all for the other replies too, but I got the impression that hardly anyone has understood the issue with this topic. :roll:
"If Origin not in center it be not in center." --Buggie
JackGriffin
Godlike
Posts: 3776
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Deleting list items within an Iterator

Post by JackGriffin »

Barbie wrote: Thanks to all for the other replies too, but I got the impression that hardly anyone has understood the issue with this topic. :roll:
To be honest, that's on you. Your question was poorly formed and the code you posted was incredibly general. You are getting funny responses because of that.

Can you delete a bunch of actors in a level via an iterated list? Sure. Is it safe to do so? 100% depends on the actors you are deleting. I'd never do it the way you showed though. It's never a good idea to remove actors with a large broom like that. Spawning and destroying need to be done with precision and a commensurate amount of care.
So long, and thanks for all the fish
User avatar
Wormbo
Adept
Posts: 258
Joined: Sat Aug 24, 2013 6:04 pm

Re: Deleting list items within an Iterator

Post by Wormbo »

sektor2111 wrote:I have verified already if UScript can call "Event" and looks like it doesn't really call events, but C++ can do more. I have an attempt and what was shown at Wiki was true. Else a mountain of mods would just mess up with crashes.
Don't give too much attention to "event" vs "function" unless you're writing native code. The "event" modifier is actually inherited by overridden functions, whether you write it or not. All Destroyed() functions will be events, because it's an event in Actor. Destroyed() is natively called during Destroy(), but can of course also be called (without any actual actor destruction going on) from UnrealScript code.
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Deleting list items within an Iterator

Post by sektor2111 »

Wormbo wrote:but can of course also be called (without any actual actor destruction going on) from UnrealScript code.
I simply have failed to get a valid response from EVENT SetInitialState (if I well recall). I was trying something with monsters and it did not worked - later I found something written at Wiki and I got confirmation. I'm not sure how much EVENTS are for UScript, functions have the purpose to get called when they are needed. Events usually are Engine's job, fix me if I'm wrong...
Barbie wrote:Yes, successfully compiled with Brain-08.15, but it seems not fully compatible to Ucc.
Ahah, and let me know what kinda Brain have client. Try to destroy a static mesh from client...
As I know based on logs and direct observations client is not so authoritative for Level related things. If in server you might destroy ANY actor and even using only UScript and UCC, for client side I believe you need some nasty hacks, else destruction in client is only a nice dream. Yes, NET stuff is the problem.
User avatar
Wormbo
Adept
Posts: 258
Joined: Sat Aug 24, 2013 6:04 pm

Re: Deleting list items within an Iterator

Post by Wormbo »

sektor2111 wrote:I simply have failed to get a valid response from EVENT SetInitialState (if I well recall). I was trying something with monsters and it did not worked - later I found something written at Wiki and I got confirmation. I'm not sure how much EVENTS are for UScript, functions have the purpose to get called when they are needed. Events usually are Engine's job, fix me if I'm wrong...
Again: Events are in no way special from the UnrealScript view, except that they will be exported to native headers when generating them. That's really it.
Any UnrealScript function/event can be clled from both UnrealScript and native code. It's just that the generated headers for UnrealScript events make calls easier, because you simply call "eventNameOfUScriptFunction(UScript parameters)" from C++, whereas you'd have to specially craft a function parameters struct for non-event functions and explicitly call it through C++ ProcessEvent().

tl;dr:
In UnrealScript "function" and "event" can be used interchangeably without any difference.