package de.gurkenlabs.litiengine.environment;

import java.util.List;

import de.gurkenlabs.litiengine.Game;
import de.gurkenlabs.litiengine.entities.IEntity;
import de.gurkenlabs.litiengine.entities.Spawnpoint;
import de.gurkenlabs.litiengine.util.CollectionUtilities;

public abstract class EntitySpawner<T extends IEntity> implements IEntitySpawner<T> {
  private int amount;
  private int interval;
  private long lastSpawnWave;
  private int spawnDelay;
  private SpawnMode spawnMode;
  private List<Spawnpoint> spawnpoints;

  /**
   * Instantiates a new entity spawner.
   *
   * @param environment
   *          the environment
   * @param loop
   *          the loop
   * @param spawnpoints
   *          the spawnpoints
   * @param interval
   *          the interval
   * @param amount
   *          the amount
   */
  public EntitySpawner(final List<Spawnpoint> spawnpoints, final int interval, final int amount) {
    this.interval = interval;
    this.spawnDelay = 1000;
    this.amount = amount;
    this.spawnpoints = spawnpoints;
    this.spawnMode = SpawnMode.ALLSPAWNPOINTS;
  }

  @Override
  public int getSpawnAmount() {
    return this.amount;
  }

  @Override
  public int getSpawnInterval() {
    return this.interval;
  }

  @Override
  public int getSpawnDelay() {
    return this.spawnDelay;
  }

  @Override
  public SpawnMode getSpawnMode() {
    return this.spawnMode;
  }

  @Override
  public List<Spawnpoint> getSpawnPoints() {
    return this.spawnpoints;
  }

  @Override
  public void setSpawnAmount(final int amount) {
    this.amount = amount;
  }

  @Override
  public void setSpawnInterval(final int interval) {
    this.interval = interval;
  }

  @Override
  public void setSpawnDelay(final int delay) {
    this.spawnDelay = delay;
  }

  @Override
  public void setSpawnMode(final SpawnMode mode) {
    this.spawnMode = mode;
  }

  @Override
  public void update() {
    if (this.lastSpawnWave != 0 && Game.time().since(this.lastSpawnWave) < this.getSpawnInterval()) {
      return;
    }

    this.spawnNewEntities();
    this.lastSpawnWave = Game.time().now();
  }

  /**
   * Spawn new entities, depending on the <code>SpawnMode</code>, spawnAmount, spawnDelay, and spawnInterval of an <code>EntitySpawner</code>.
   * 
   * @see SpawnMode
   */
  protected void spawnNewEntities() {
    if (this.getSpawnPoints().isEmpty()) {
      return;
    }

    switch (this.getSpawnMode()) {
    case ALLSPAWNPOINTS:
      for (int i = 0; i < this.getSpawnPoints().size(); i++) {
        final int index = i;
        Game.loop().perform(this.getSpawnDelay() + this.getSpawnDelay() * i, () -> {
          this.spawn(this.getSpawnPoints().get(index), this.getSpawnAmount());
        });
      }
      break;
    case ONERANDOMSPAWNPOINT:
      this.spawn(CollectionUtilities.random(this.getSpawnPoints()), this.getSpawnAmount());
      break;
    case RANDOMSPAWNPOINTS:
      for (int i = 0; i < this.getSpawnAmount(); i++) {
        Game.loop().perform(this.getSpawnDelay() + this.getSpawnDelay() * i, () -> {
          this.spawn(CollectionUtilities.random(this.getSpawnPoints()), 1);
        });
      }

      break;
    default:
      break;
    }
  }

  private void spawn(final Spawnpoint spawnpoint, final int amount) {
    for (int i = 0; i < amount; i++) {
      final T newEntity = this.createNew();
      newEntity.setLocation(spawnpoint.getLocation());
      newEntity.setMapId(Game.world().environment().getNextMapId());
      Game.world().environment().add(newEntity);
    }
  }
}
@@ -3386,24 +3386,137 @@
  amount) %7B%0D%0A
+    if (spawnpoint.getEnvironment() == null %7C%7C !spawnpoint.getEnvironment().isLoaded()) %7B%0D%0A      return;%0D%0A    %7D%0D%0A
     for (int
@@ -3539,24 +3539,24 @@
 nt; i++) %7B%0D%0A
-
       final 
@@ -3669,30 +3669,31 @@
 etMapId(
-Game.world().e
+spawnpoint.getE
 nvironme
@@ -3725,22 +3725,23 @@
     
-Game.world().e
+spawnpoint.getE
 nvir

Use the environment of the Spawnpoint