1

Hello.

I'm running a server and have added a minigame.

whenever the game is about to start.. it calls onStart() first. Now I get ConcurrentModificationException on this line:

for(Player p : waiting) {

And here is the method:

    public void onStart() {
    trawler.players.clear();
    for(Player p : waiting) {
        if(!boat.playerInArea(p)) {
            waiting.remove(p);
        }
    }

    for(Player p : waiting) {
        trawler.players.add(p);
    }

    trawler.start();
    waiting.clear();
}

if you need the classes, here they are:

TrawlerWaitingRoom.java:

package server.model.minigames.trawler;

import server.model.players.Location;
import server.model.players.Player;

public class TrawlerWaitingRoom extends WaitingRoom {
private Trawler trawler;
//private Location boat = new Location(2668,2674,3165,3185);
private Location boat = new Location(2808, 2811,3415,3425);


public TrawlerWaitingRoom(Trawler trawler) {
    super(1, 2);
    this.trawler = trawler;
}

@Override
public boolean startGame() {
    if(trawler.inProgress()) {
        return false;
    }
    return true;
}

@Override
public void onStart() {
    trawler.players.clear();
    for(Player p : waiting) {
        if(!boat.playerInArea(p)) {
            waiting.remove(p);
        }
    }

    for(Player p : waiting) {
        trawler.players.add(p);
    }

    trawler.start();
    waiting.clear();
}

@Override
public void onLeave(Player p) {
    p.asClient().getPA().movePlayer(2804, 3421, 0);
    //p.asClient().getPA().movePlayer(2676, 3170, 0);
}

@Override
public void onJoin(Player p) {
    p.asClient().getPA().movePlayer(2808, 3421, 1);
    //p.asClient().getPA().movePlayer(2672, 3170, 1);
    if(!isActive()) {
        p.asClient().sendMessage(trawler.getGameTime() == 0 ? "The trawler will be returning in less than a minute!" : "The trawler will return in "+trawler.getGameTime() + (trawler.getGameTime() == 1 ? " minute" : " minutes")+"!");
    } else {
        p.asClient().sendMessage(getTimeRemaining() == 0 ? "The trawler will be leaving in less than a minute!" : "The trawler will leave in "+ getTimeRemaining() + (getTimeRemaining() == 1 ? " minute" : " minutes")+"!");
    }
}

@Override
public Location getLocation() {
    return boat;
}

@Override
public void onTimeChange() {
    for(Player p : waiting) {
        if(!isActive()) {
            p.asClient().sendMessage(trawler.getGameTime() == 0 ? "The trawler will be returning in less than a minute!" : "The trawler will return in "+trawler.getGameTime() + (trawler.getGameTime() == 1 ? " minute" : " minutes")+"!");
        } else {
            p.asClient().sendMessage(getTimeRemaining() == 0 ? "The trawler will be leaving in less than a minute!" : "The trawler will leave in "+ getTimeRemaining() + (getTimeRemaining() == 1 ? " minute" : " minutes")+"!");
        }
    }
}

@Override
public boolean canStart() {
    if(trawler.inProgress()) {
        return false;
    }
    if(waiting.size() < minimumPlayers) {
        return false;
    }
    return true;
}

}

GroupMinigame.java:

package server.model.minigames.trawler;

import server.model.minigames.trawler.WaitingRoom;

public abstract class GroupMinigame {

public abstract WaitingRoom getWaitingRoom();

public abstract String getWaitingRoomMessage();
}

WaitingRoom.java: http://pastebin.com/KkC8ReWV

Trawler.java: http://pastebin.com/XW5XrsjR

Thanks in advance!

rahulserver
  • 10,411
  • 24
  • 90
  • 164
user2598506
  • 39
  • 1
  • 6

5 Answers5

6

Here's the problem:

for(Player p : waiting) {
    if(!boat.playerInArea(p)) {
        waiting.remove(p); // BOOM
    }
}

You can't directly modify a collection you're iterating over.

Instead, you must use an Iterator:

for(Iterator<Player> i = waiting.iterator(); i.hasNext();) {
    Player p = i.next(); 
    if(!boat.playerInArea(p)) {
        i.remove(); // Allowed with an iterator
    }
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Now, this resolved my problem but it's not adding me to the trawler.players list. for(Player p : waiting) { trawler.players.add(p); } – user2598506 Jul 19 '13 at 08:42
0

You're creating an iterator on an object, by using a for-each loop. You're then trying to edit it, which is not permitted in Java.

for(Player p : waiting) {
    // Iterator created.
    if(!boat.playerInArea(p)) {
        // Change to iterated object.
        waiting.remove(p);
    }
}

Your alternative is to create a new list, and overwrite the old list. For example:

private List<Waiting> newWaiting = new ArrayList<Waiting>();

for(Player p : waiting) {
   // Iterator created on the WAITING object.
   if(boat.playerInArea(p)) {
       newWaiting.add(p);
       // Logic is flipped, so those that pass are carried forward.
   }
}
waiting = newWaiting;
// Set waiting's reference to point to newWaiting's reference. 
christopher
  • 26,815
  • 5
  • 55
  • 89
0

Use Iterator#remove() to remove elements from List while iterating through the List.

Iterator<Player> itr = waiting.iterator();
while(itr.hasNext()) {
    Player p = itr.next(); 
    if(!boat.playerInArea(p)) {
      itr.remove(); 
    }
}
AllTooSir
  • 48,828
  • 16
  • 130
  • 164
0

It's rather simple: You're removing objects from the list waiting, while you use it as a loop. That's not allowed. Try the following instead:

List<Player> temporaryList = new LinkedList<Player>(waiting);
for(Player p : temporaryList ) {
    if(!boat.playerInArea(p)) {
        waiting.remove(p);
    }
}
MyPasswordIsLasercats
  • 1,610
  • 15
  • 24
0

There are two logical steps you need to follow before correcting and understanding this error.

  1. How does the Java 'for each' loop work? (Hint: Iterator)

  2. How can the use of an iterator lead to a Concurrent Modification exception ?

Community
  • 1
  • 1
lf215
  • 1,185
  • 7
  • 41
  • 83