Solved (not) impossible infinite loop?

Discussion in 'Spigot Plugin Development' started by Nuubles, Mar 20, 2019.

  1. I've been having problems with a code I've made and anyone who I've given this code to has not been able to solve this. For reference the BlockCollection.contains etc. use LinkedList, will probably later change is to something else.
    The code gets stuck in an infinite loop inside the while loop, and even though the current block from the queue is added to the collection, it still keeps saying it does not contain it and keeps adding it to the queue to be rescanned.

    Code (Java):
    public static BlockCollection scanBlockTypes(Block block, boolean corners, boolean goDown, ArrayList<Block> connectedBlocks)
    {
        BlockCollection coll = new BlockCollection();
     
        Queue<Block> q = new LinkedList<Block>();
        q.add(block);
     
        while(!q.isEmpty())
        {
            Block b = q.remove();
          coll.add(b);
            //Check all blocks around the current block
            for(int x = -1; x <= 1; ++x)
            for(int y = goDown?-1:0; y <= 1; ++y)
            for(int z = -1; z <= 1; ++z)
            {
                if(x == 0 && y == 0 && z == 0)
                    continue;
             
                Block cBlock = b.getLocation().add(x, y, z).getBlock();
             
                //If no corners are allowed, skip them
                if(!corners && x != 0 && y != 0 && z != 0)
                    continue;
             
                //Blocks are same type, continue
                if(block.getType() == cBlock.getType())
                {
                    if(!coll.contains(cBlock)) //Don't add if already in collection
                        q.add(cBlock);
                }
                //Blocks are different type, add to connectedBlocks
                else if(connectedBlocks != null)
                    connectedBlocks.add(cBlock);
            }
        }
     
        //Return the collection of blocks
        return coll;
    }
     
    #1 Nuubles, Mar 20, 2019
    Last edited: Mar 20, 2019
  2. have you tried debugging to make sure it is actually running and printing out the values of q?
     
    • Informative Informative x 1
  3. Hold one I just realized I've made a really stupid mistake with this code hold on. (yea I've tried printing but just realized at some point I've removed the line adding the block to the collection

    Edit: added the addition back, still not working and in infinite loop
    Edit2: updated the code in this post
     
  4. Yes, I've set the limit on my test server to 10000 loops and it keeps on running until it hits the limit and breaks out of loop (without it it would be infninite). I've tried printing the values and it keeps switching between blocks in 2-4 different coordinates when it gets stuck in the loop
     
  5. while was somehow pretty bugged for me too (probably me using it wrong), but the server kept lagging like hell. I just used BukkitRunnable to check the statement via if every x ticks, and if it stopped I just cancelled it. This way you just create a BukkitRunnable, let it run every x ticks till you want it to stop, then cancel it.
     
    #5 boaler, Mar 20, 2019
    Last edited: Mar 21, 2019
    • Informative Informative x 1
  6. While loops are usually not used in delayed actions (like timers or BukkitRunnables) except keeping actual applications alive in OS, but in my case, the code needs to be run once as it scans all of the blocks of the same type into a collection to be manipulated elsewhere.
     
    • Friendly Friendly x 1
  7. The check later on is about cBlock and not about b. That is another block.

    Basically what you do is having one block in queue. Then you remove it BUT you add ALL blocks around it to the queue. Then you add the outer blocks of these blocks to the queue. And it goes on and on for an eternity until it reached height 256 or -1, then it will crash.

    You will surely find other AIR blocks next to some air block. Or stone blocks next to otger stone blocks.
     
    • Useful Useful x 1
  8. Thank you! got it working :D
    I changed if(!coll.contains(cBlock)) to if(!(coll.contains(cBlock) || q.contains(cBlock)) thus now also checking if the block is in queue -> not in collection yet but going to be scanned
     
    #8 Nuubles, Mar 20, 2019
    Last edited: Mar 20, 2019
  9. I meant I checked them with an if statement, not a while loop in the BukkitRunnable :) Edited it in case someone stumbles upon it