package org.mafagafogigante.dungeon.entity.creatures;
import org.mafagafogigante.dungeon.entity.Luminosity;
import org.mafagafogigante.dungeon.entity.TagSet;
import org.mafagafogigante.dungeon.entity.Weight;
import org.mafagafogigante.dungeon.game.Id;
import org.mafagafogigante.dungeon.game.NameFactory;
import org.mafagafogigante.dungeon.io.JsonObjectFactory;
import org.mafagafogigante.dungeon.logging.DungeonLogger;
import org.mafagafogigante.dungeon.util.Percentage;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* A CreaturePresetFactory that uses JSON files.
*/
public class JsonCreaturePresetFactory implements CreaturePresetFactory {
private static final int DEFAULT_INVENTORY_ITEM_LIMIT = 100;
private static final double DEFAULT_INVENTORY_WEIGHT_LIMIT = 100.0;
private final String filename;
public JsonCreaturePresetFactory(String filename) {
this.filename = filename;
}
/**
* Attempts to read a string from the provided JSON object, returning null if the string is not present or if the
* value is not a string.
*
* @param jsonObject a JsonObject, not null
* @param name a String, not null
* @return a String or null
*/
@Nullable
private static String getStringFromJsonObject(@NotNull JsonObject jsonObject, @NotNull String name) {
JsonValue value = jsonObject.get(name);
if (value == null || !value.isString()) {
return null;
} else {
return value.asString();
}
}
@Nullable
private static Percentage getPercentageFromJsonObject(@NotNull JsonObject jsonObject, @NotNull String name) {
String percentageString = getStringFromJsonObject(jsonObject, name);
if (percentageString != null) {
if (Percentage.isValidPercentageString(percentageString)) {
return Percentage.fromString(percentageString);
} else {
throw new IllegalStateException("JSON contains invalid percentage string: " + percentageString + ".");
}
}
return null;
}
private static List<Id> getInventory(JsonObject object) {
if (object.get("inventory") == null) {
return Collections.emptyList();
} else {
List<Id> list = new ArrayList<>();
for (JsonValue value : object.get("inventory").asArray()) {
list.add(new Id(value.asString()));
}
return list;
}
}
private static List<Drop> getDrops(JsonObject object) {
if (object.get("drops") == null) {
return Collections.emptyList();
} else {
List<Drop> list = new ArrayList<>();
for (JsonValue value : object.get("drops").asArray()) {
JsonArray dropArray = value.asArray();
list.add(new Drop(new Id(dropArray.get(0).asString()), new Percentage(dropArray.get(1).asDouble())));
}
return list;
}
}
private static void setVisibility(CreaturePreset preset, JsonObject presetObject) {
Percentage visibilityPercentage = getPercentageFromJsonObject(presetObject, "visibility");
if (visibilityPercentage != null) {
preset.setVisibility(visibilityPercentage);
}
}
private static void setLuminosityIfPresent(CreaturePreset preset, JsonObject presetObject) {
Percentage luminosityPercentage = getPercentageFromJsonObject(presetObject, "luminosity");
if (luminosityPercentage != null) {
preset.setLuminosity(new Luminosity(luminosityPercentage));
}
}
private static void setWeaponIfPreset(CreaturePreset preset, JsonObject presetObject) {
String weapon = getStringFromJsonObject(presetObject, "weapon");
if (weapon != null) {
preset.setWeaponId(new Id(weapon));
}
}
@Override
public Collection<CreaturePreset> getCreaturePresets() {
Collection<CreaturePreset> creaturePresetMap = new ArrayList<>();
JsonObject object = JsonObjectFactory.makeJsonObject(filename);
for (JsonValue value : object.get("creatures").asArray()) {
JsonObject presetObject = value.asObject();
CreaturePreset preset = new CreaturePreset();
preset.setId(new Id(presetObject.get("id").asString()));
preset.setType(presetObject.get("type").asString());
preset.setName(NameFactory.fromJsonObject(presetObject.get("name").asObject()));
if (presetObject.get("tags") != null) {
preset.setTagSet(TagSet.fromJsonArray(presetObject.get("tags").asArray(), Creature.Tag.class));
} else {
preset.setTagSet(TagSet.makeEmptyTagSet(Creature.Tag.class));
}
preset.setInventoryItemLimit(presetObject.getInt("inventoryItemLimit", DEFAULT_INVENTORY_ITEM_LIMIT));
preset.setInventoryWeightLimit(presetObject.getDouble("inventoryWeightLimit", DEFAULT_INVENTORY_WEIGHT_LIMIT));
preset.setItems(getInventory(presetObject));
preset.setDropList(getDrops(presetObject));
setLuminosityIfPresent(preset, presetObject);
setVisibility(preset, presetObject);
preset.setWeight(Weight.newInstance(presetObject.get("weight").asDouble()));
preset.setHealth(presetObject.get("health").asInt());
preset.setAttack(presetObject.get("attack").asInt());
setWeaponIfPreset(preset, presetObject);
preset.setAttackAlgorithmId(AttackAlgorithmId.valueOf(presetObject.get("attackAlgorithmID").asString()));
creaturePresetMap.add(preset);
}
DungeonLogger.info("Loaded " + creaturePresetMap.size() + " creature presets.");
return creaturePresetMap;
}
}