package org.mafagafogigante.dungeon.entity.creatures;
import org.mafagafogigante.dungeon.achievements.AchievementTracker;
import org.mafagafogigante.dungeon.date.Date;
import org.mafagafogigante.dungeon.entity.items.CreatureInventory.SimulationResult;
import org.mafagafogigante.dungeon.entity.items.Item;
import org.mafagafogigante.dungeon.entity.items.ItemFactory;
import org.mafagafogigante.dungeon.game.Game;
import org.mafagafogigante.dungeon.game.Id;
import org.mafagafogigante.dungeon.game.World;
import org.mafagafogigante.dungeon.logging.DungeonLogger;
import org.mafagafogigante.dungeon.stats.Statistics;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* The factory of creatures.
*/
public final class CreatureFactory implements Serializable {
private final Map<Id, CreaturePreset> creaturePresets = new HashMap<>();
/**
* Constructs an ItemFactory from one or more CreaturePresetFactories.
*/
public CreatureFactory(@NotNull CreaturePresetFactory... creaturePresetFactories) {
for (CreaturePresetFactory creaturePresetFactory : creaturePresetFactories) {
addAllPresets(creaturePresetFactory.getCreaturePresets());
}
}
/**
* Iterates over all presets of a Collection, adding them to this factory after they are validated.
*/
private void addAllPresets(Collection<CreaturePreset> presets) {
for (CreaturePreset preset : presets) {
Id id = preset.getId();
if (creaturePresets.containsKey(id)) {
throw new IllegalArgumentException("factory already contains a preset with the Id " + preset.getId() + ".");
}
creaturePresets.put(id, preset);
}
}
/**
* Gives a Creature all the Items defined in the corresponding CreaturePreset and equips its weapon, if there is one.
*
* @param creature the Creature
*/
private void giveItems(Creature creature, World world) {
CreaturePreset preset = creaturePresets.get(creature.getId());
ItemFactory itemFactory = world.getItemFactory();
for (Id itemId : preset.getItems()) {
if (itemFactory.canMakeItem(itemId)) {
Item item = itemFactory.makeItem(itemId, world.getWorldDate());
SimulationResult result = creature.getInventory().simulateItemAddition(item);
if (result == SimulationResult.SUCCESSFUL) {
creature.getInventory().addItem(item);
} else {
DungeonLogger.warning("Could not add " + itemId + " to " + creature.getId() + ". Reason: " + result + ".");
}
}
}
equipWeapon(creature, preset);
}
public Collection<CreaturePreset> getPresets() {
return creaturePresets.values();
}
/**
* Attempts to create a creature from the CreaturePreset specified by an ID. Returns null if no preset was found.
*
* <p>Also adds the new creature to the statistics.
*/
public Creature makeCreature(Id id, World world) {
CreaturePreset preset = creaturePresets.get(id);
if (preset != null) {
Creature creature = new Creature(preset);
Game.getGameState().getStatistics().getWorldStatistics().addSpawn(creature.getName().getSingular());
giveItems(creature, world);
return creature;
} else {
return null;
}
}
private static void equipWeapon(Creature creature, CreaturePreset preset) {
if (preset.getWeaponId() != null) {
// Get the weapon from the creature's inventory.
for (Item item : creature.getInventory().getItems()) {
if (item.getId().equals(preset.getWeaponId())) {
creature.setWeapon(item);
break;
}
}
if (!creature.hasWeapon()) { // Did not found a suitable Item in the inventory.
String format = "%s not found in the inventory of %s!";
DungeonLogger.warning(String.format(format, preset.getWeaponId(), creature.getId()));
}
}
}
/**
* Creates the Hero.
*
* @param date the Date when the Items the Hero has were created
* @return the Hero object
*/
public Hero makeHero(Date date, World world, Statistics statistics) {
DateOfBirthGenerator dateOfBirthGenerator = new DateOfBirthGenerator(date, 30);
Date dateOfBirth = dateOfBirthGenerator.generateDateOfBirth();
Hero hero = new Hero(creaturePresets.get(new Id("HERO")), new AchievementTracker(statistics), dateOfBirth);
giveItems(hero, world);
return hero;
}
}