Author Topic: looping thru bricks  (Read 1272 times)

It gives a console error, and only some bricks are deleted...

If I run it again, it deletes a couple more, then again and it deletes some more etc

Code: [Select]
//Clear Guest Bricks Script
//by Cucumberdude
//Allows superadmins to clear all bricks that do not belong to them

function serverCmdClearGuestBricks(%cl)
{
if(%cl.isSuperAdmin)
{
messageAll('MsgClearBricks',"\c3" @ %cl.name @ "\c0 has cleared all guest bricks.");

//loop through all bricks
%groupCount = MainBrickGroup.getCount();
for(%i = 0; %i < %groupCount; %i++)
{
%group = MainBrickGroup.getObject(%i);
//if the brickgroup does not belong to %cl
if(%group.bl_id != %cl.bl_id)
{
%count = %group.getCount();
for(%j = 0; %j < %count; %j++)
{
//KILL THEM ALL HAHHAHAHAHAHHA
%brick = %group.getObject(%j);
%brick.delete();
}
}
}
}
}
Code: [Select]
...
Set::getObject index out of range on BrickGroup_10729. Index = 41, Size = 27
BackTrace: ->serverCmdClearGuestBricks

Add-Ons/Script_ClearGuestBricks/server.cs (0): Unable to find object: '-1' attempting to call function 'delete'
BackTrace: ->serverCmdClearGuestBricks

Set::getObject index out of range on BrickGroup_10729. Index = 42, Size = 27
BackTrace: ->serverCmdClearGuestBricks

Add-Ons/Script_ClearGuestBricks/server.cs (0): Unable to find object: '-1' attempting to call function 'delete'
BackTrace: ->serverCmdClearGuestBricks

Set::getObject index out of range on BrickGroup_10729. Index = 43, Size = 27
BackTrace: ->serverCmdClearGuestBricks

Add-Ons/Script_ClearGuestBricks/server.cs (0): Unable to find object: '-1' attempting to call function 'delete'
BackTrace: ->serverCmdClearGuestBricks

Set::getObject index out of range on BrickGroup_10729. Index = 44, Size = 27
BackTrace: ->serverCmdClearGuestBricks

Add-Ons/Script_ClearGuestBricks/server.cs (0): Unable to find object: '-1' attempting to call function 'delete'
BackTrace: ->serverCmdClearGuestBricks

Set::getObject index out of range on BrickGroup_10729. Index = 45, Size = 27
BackTrace: ->serverCmdClearGuestBricks

Add-Ons/Script_ClearGuestBricks/server.cs (0): Unable to find object: '-1' attempting to call function 'delete'
BackTrace: ->serverCmdClearGuestBricks

Set::getObject index out of range on BrickGroup_10729. Index = 46, Size = 27
BackTrace: ->serverCmdClearGuestBricks

Add-Ons/Script_ClearGuestBricks/server.cs (0): Unable to find object: '-1' attempting to call function 'delete'
BackTrace: ->serverCmdClearGuestBricks

Set::getObject index out of range on BrickGroup_10729. Index = 47, Size = 27
BackTrace: ->serverCmdClearGuestBricks

Add-Ons/Script_ClearGuestBricks/server.cs (0): Unable to find object: '-1' attempting to call function 'delete'
BackTrace: ->serverCmdClearGuestBricks

Set::getObject index out of range on BrickGroup_10729. Index = 48, Size = 27
...

wtf

When you delete an object in a group, while looping through the group's objects, it messes up the loop. Try %brick.schedule(0,"delete");
Also, apparently not all objects stored in a brickgroup are bricks. You should be doing this check before deleting it:
Code: [Select]
if((%brick.getType() & $TypeMasks::FxBrickAlwaysObjectType) && !%brick.isDead && %brick.isPlanted)

Code: [Select]
//Clear Guest Bricks Script
//by Cucumberdude
//Allows superadmins to clear all bricks that do not belong to them

function serverCmdClearGuestBricks(%cl)
{
if(%cl.isSuperAdmin)
{
messageAll('MsgClearBricks',"\c3" @ %cl.name @ "\c0 has cleared all guest bricks.");

//loop through all bricks
%groupCount = MainBrickGroup.getCount();
for(%i = 0; %i < %groupCount; %i++)
{
%group = MainBrickGroup.getObject(%i);
//if the brickgroup does not belong to %cl
if(%group.bl_id != %cl.bl_id)
%group.chainDeleteAll(); //remove all bricks in the brickgroup
}
}
}

That should work nicely, I've used it before.

EDIT: That's all that /clearBricks does to clear everything too.
« Last Edit: May 11, 2011, 01:21:20 AM by Greek2me »

Code: [Select]
//Clear Guest Bricks Script
//by Cucumberdude
//Allows superadmins to clear all bricks that do not belong to them

function serverCmdClearGuestBricks(%cl)
{
if(%cl.isSuperAdmin)
{
messageAll('MsgClearBricks',"\c3" @ %cl.name @ "\c0 has cleared all guest bricks.");

//loop through all bricks
%groupCount = MainBrickGroup.getCount();
for(%i = 0; %i < %groupCount; %i++)
{
%group = MainBrickGroup.getObject(%i);
//if the brickgroup does not belong to %cl
if(%group.bl_id != %cl.bl_id)
%group.chainDeleteAll(); //remove all bricks in the brickgroup
}
}
}

That should work nicely, I've used it before.

EDIT: That's all that /clearBricks does to clear everything too.
Thanks, I'll try that then.

If you want to use the code you had, schedule the delete method (0ms works, it just can't be right away).

If you want to use the code you had, schedule the delete method (0ms works, it just can't be right away).
gotcha

ill just use chain delete, after all if clear bricks uses it why not?

to "fix" your origional code, you will want something like this:
Code: [Select]
function serverCmdClearGuestBricks(%cl)
{
  if(%cl.isSuperAdmin)
  {
    messageAll('MsgClearBricks',"\c3" @ %cl.name @ "\c0 has cleared all guest bricks.");
      
    //loop through all bricks
    %groupCount = MainBrickGroup.getCount();
    for(%i = 0; %i < %groupCount; %i++)
    {
      %group = MainBrickGroup.getObject(%i);
      //if the brickgroup does not belong to %cl
      if (%group.bl_id != %cl.bl_id)
        {
         while (%group.getCount() > 0)
           {
            %brick = %group.getObject(0);
            %brick.delete();
           }
        }
    }
  }
}

The reason you are having problems is that when you delete the brick, it also gets removed from its brickgroup.  The same brickgroup you are accessing.  So when you get object at index #42 out of the group, and delete it.  that goes away, and index#42 is now a new brick - which gets skipped, cause the next thing you loop does is to move to index #43.

The same thing happens when you get to the end of the brick group.  you delete the last brick, that brick gets removed from the brickgroup, and then your loop asks for the next index number -- which is beyond the size of the collection, and you get an error.
« Last Edit: May 11, 2011, 08:01:24 PM by Red_Guy »


An alternative would be this.

Code: [Select]
// Deletes all bricks with %bricktype as their datablock.
// @null
function deleteAll(%brickType)
{
// Did we supply a valid datablock?
if(isObject(%brickType))
{
%killList = "";

// Loop through all brickgroups.
for(%a = 0; %a < MainBrickGroup.getCount(); %a++)
{
%bg = MainBrickGroup.getObject(%a);

// Loop through every brick in this brickgroup.
for(%b = 0; %b < %bg.getCount(); %b++)
{
%brick = %bg.getObject(%b);

// Test if the bricktype of the selected brick
if(%brick.getDatablock().getID() == %brickType.getID())
{
// Add a field to our killList.
%killList = setField(%str, getFieldCount(%killList), %brick.getID());
}
}
}

// Loop through every field in the killlist.
for(%a = 0; %a < getFieldCount(%killList); %a++)
{
// Kill the brick.
%brick = getField(%killList, %a);
%brick.killBrick();
}

echo("Destroyed" SPC getFieldCount(%killList) SPC "Brick(s).");
}
}

Yeah, the new code works.

Thanks guys.

An alternative would be this.
He wants to delete all the bricks in the brickgroup, not a specific type of brick.