package org.mafagafogigante.dungeon.game;
import org.mafagafogigante.dungeon.entity.creatures.Creature;
import org.mafagafogigante.dungeon.logging.DungeonLogger;
import java.io.Serializable;
/**
* Spawner class that repopulates locations.
*/
class Spawner implements Serializable {
private final Id id;
private final int populationLimit;
private final int spawnDelay;
private final Location location;
// A change can be either the spawn of a creature or the end of the population limit.
private long lastChange;
public Spawner(SpawnerPreset preset, Location location) {
id = preset.id;
populationLimit = Random.nextInteger(preset.minimumPopulation, preset.maximumPopulation + 1);
spawnDelay = preset.spawnDelay;
this.location = location;
lastChange = getWorldCreationTime();
}
/**
* Refresh the spawner, spawning all creatures that should have spawned since the last spawn.
*
* <p>Only spawners in locations whose creatures are visible to the player should be refreshed.
*/
public void refresh() {
long worldTime = getWorldTime();
while (worldTime - lastChange >= spawnDelay && location.getCreatureCount(id) < populationLimit) {
World world = location.getWorld();
Creature creature = world.getCreatureFactory().makeCreature(id, world);
if (creature != null) {
location.addCreature(creature);
} else {
DungeonLogger.warning("Could not find the creature preset for " + id + ".");
}
// Simulate that the creature was spawned just when it should have been.
// Do not prevent this modification if making the creature was unsuccessful to avoid an infinite loop.
lastChange += spawnDelay;
}
}
/**
* Notify the killing of a creature in the location of the spawner. This is necessary in order to record a possible
* end of the population limit.
*/
public void notifyKill(Creature creature) {
if (id.equals(creature.getId()) && location.getCreatureCount(id) == populationLimit) {
lastChange = getWorldTime();
}
}
/**
* Returns the time, in milliseconds, of the World of the Location that this Spawner is in.
*/
private long getWorldTime() {
return location.getWorld().getWorldDate().getTime();
}
/**
* Returns the time, in milliseconds, of the creation of the World of the Location that this Spawner is in.
*/
private long getWorldCreationTime() {
return location.getWorld().getWorldCreationDate().getTime();
}
@Override
public String toString() {
return "Spawner{" +
"id=" + id +
", populationLimit=" + populationLimit +
", spawnDelay=" + spawnDelay +
", location=" + location +
", lastChange=" + lastChange +
'}';
}
}