package com.aionemu.gameserver.spawnengine;
import java.util.*;
import java.util.stream.Collectors;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.gameobjects.VisibleObject;
import com.aionemu.gameserver.model.templates.event.EventTemplate;
import com.aionemu.gameserver.model.templates.spawns.SpawnGroup;
import com.aionemu.gameserver.model.templates.spawns.SpawnTemplate;
import com.aionemu.gameserver.world.WorldMapInstance;
/**
* @author xTz, Neon
*/
public class TemporarySpawnEngine {
private static final Map<SpawnGroup, Set<Integer>> spawnGroups = new HashMap<>();
private static final Set<VisibleObject> spawnedObjects = new HashSet<>();
public static synchronized void onHourChange() {
despawn();
spawn();
}
private static void despawn() {
List<VisibleObject> remainingObjects = new ArrayList<>(spawnedObjects.size());
spawnedObjects.forEach(object -> {
if (object.getSpawn().getTemporarySpawn().canDespawn()) {
if (object instanceof Npc npc && !npc.isDead() && object.getSpawn().hasPool())
object.getSpawn().setUse(npc.getInstanceId(), false);
object.getController().deleteIfAliveOrCancelRespawn();
} else {
remainingObjects.add(object);
}
});
spawnedObjects.retainAll(remainingObjects);
}
private static void spawn() {
Map<SpawnGroup, List<VisibleObject>> spawnedBySpawnGroup = spawnedObjects.stream().collect(Collectors.groupingBy(o -> o.getSpawn().getGroup()));
spawnGroups.forEach((spawn, instanceIds) -> {
if (instanceIds.isEmpty())
return;
List<VisibleObject> spawned = spawnedBySpawnGroup.getOrDefault(spawn, Collections.emptyList());
if (spawn.hasPool()) {
if (!spawn.getTemporarySpawn().canSpawn())
return;
Set<Integer> spawnableInstanceIds = new HashSet<>(instanceIds);
spawned.forEach(o -> spawnableInstanceIds.remove(o.getInstanceId()));
for (Integer instanceId : spawnableInstanceIds) {
spawn.resetTemplates(instanceId);
for (int pool = 0; pool < spawn.getPool(); pool++) {
SpawnTemplate template = spawn.getRndTemplate(instanceId);
SpawnEngine.spawnObject(template, instanceId);
}
}
} else {
for (SpawnTemplate template : spawn.getSpawnTemplates()) {
if (!template.getTemporarySpawn().canSpawn())
continue;
Set<Integer> spawnableInstanceIds = new HashSet<>(instanceIds);
spawned.stream().filter(o -> o.getSpawn().equals(template)).forEach(o -> spawnableInstanceIds.remove(o.getInstanceId()));
spawnableInstanceIds.forEach(instanceId -> SpawnEngine.spawnObject(template, instanceId));
}
}
});
}
public static synchronized void registerSpawned(VisibleObject object) {
spawnedObjects.add(object);
}
public static synchronized void unregisterSpawned(int objectId) {
spawnedObjects.removeIf(o -> o.getObjectId() == objectId);
}
public static synchronized void addSpawnGroup(SpawnGroup spawnGroup, int instanceId) {
spawnGroups.computeIfAbsent(spawnGroup, k -> new HashSet<>()).add(instanceId);
}
public static synchronized void unregister(EventTemplate eventTemplate) {
spawnedObjects.removeIf(o -> o.getSpawn().getEventTemplate() == eventTemplate);
spawnGroups.keySet().removeIf(s -> s.getEventTemplate() == eventTemplate);
}
public static synchronized void onInstanceDestroy(WorldMapInstance instance) {
spawnedObjects.removeIf(o -> instance.equals(o.getWorldMapInstance()));
spawnGroups.forEach((spawnGroup, instanceIds) -> {
if (spawnGroup.getWorldId() == instance.getMapId())
instanceIds.remove(instance.getInstanceId());
});
}
}