IENumerable error (bug?) after recent RimWorld update

Started by SourceVG, June 03, 2014, 10:46:18 PM

Previous topic - Next topic

SourceVG

This code worked in prior to the update, but now it gives an error. Although it still does delete the item, like it is supposed to.

Code:

if(!Find.ListerBuildings.AllBuildingsColonistOfClass<Building_CommsConsole>().Any<Building_CommsConsole>())
        {
            ThingDef findBeacon = ThingDef.Named("DistressBeacon");
            IEnumerable<Thing> listbeacons = Find.ListerThings.ThingsOfDef(findBeacon);
            foreach (Building newcurrent in listbeacons)
            {
                newcurrent.Destroy(); //destroy all beacons --- THIS LINE GIVES THE ERROR ------------------------
            }
            Messages.Message("You must have a Comms Console built before you can build a Distress Beacon.", MessageSound.Negative); //send a message alerting him
            return;
        }


Error:


After debugging the code, it seems to happen after the "newcurrent.Destroy();" is executed. And based on the error code, "Collection was modified" I think I know what is going on.  ...  It created the list of all of the buildings, but then when one of the item is taken away from the lists and "modifies" it, the code gives an error.

This didn't happen in prior updates so maybe the code was changed for the Destroy() function? This is kind of a possible bug report report and also a help thread.

Thanks :)





Cala13er

#2
Ermm, try telling it what destroy mode you wish for it to trigger?

newcurrent.Destroy(DestroyMode.Vanish);

DestroyMode has 4 different modes.
--->Vanish
--->Kill
--->Cancel
--->Deconstruct

You'd probably be looking at using Vanish.

Haplo

Try it with a for-loop and go backwards through the elements.
The problem is most likely that it goes forward through the items of the IEnumerable and destroys them.
The problem is this:
You have a list of items: 1 2 3 4 5 => count == 5
You destroy item 1 and the lis looks like this: 2 3 4 5 => count == 4
Now you have only four items but you still are in the foreach loop that thought there are 5 items..
Better do:

for (int i = listbeacons.Count(); i > 0; i--)
{
    listbeacons.ElementAt(i-1).Destroy();
}


I'm not 100% sure that's your solution, but you can try it...

Edit: I think it worked in Alpha 3 because every time you destroyed something there it threw you out of the loop. And you could work with the next item in the next Tick. That doesn't work in alpha 4 anymore. (And rightfully so :) )