package org.mafagafogigante.dungeon.game; import org.mafagafogigante.dungeon.date.Date; import org.mafagafogigante.dungeon.date.DungeonTimeUnit; import org.mafagafogigante.dungeon.entity.creatures.CorpseItemPresetFactory; import org.mafagafogigante.dungeon.entity.creatures.CreatureFactory; import org.mafagafogigante.dungeon.entity.creatures.CreaturePresetFactory; import org.mafagafogigante.dungeon.entity.creatures.JsonCreaturePresetFactory; import org.mafagafogigante.dungeon.entity.creatures.Observer; import org.mafagafogigante.dungeon.entity.items.ItemFactory; import org.mafagafogigante.dungeon.entity.items.ItemPresetFactory; import org.mafagafogigante.dungeon.entity.items.JsonItemPresetFactory; import org.mafagafogigante.dungeon.logging.DungeonLogger; import org.mafagafogigante.dungeon.stats.WorldStatistics; import org.mafagafogigante.dungeon.world.Sky; import org.mafagafogigante.dungeon.world.SkyFactory; import org.mafagafogigante.dungeon.world.Weather; import org.jetbrains.annotations.NotNull; import java.io.Serializable; import java.util.HashMap; import java.util.Map; /** * A complete world, with a generator, entity factories, a map, a date, and statistics. */ public class World implements Serializable { private final WorldGenerator generator = new WorldGenerator(this); // Each world should have its own factories because their limitations and characteristics are not meant to be shared. private final CreatureFactory creatureFactory; private final ItemFactory itemFactory; private final Map<Point, Location> locations = new HashMap<>(); private final WorldStatistics worldStatistics; private final Date worldCreationDate = new Date(1, 1, 1); private final Sky sky = SkyFactory.makeDarrowmereSky(); private Date worldDate = new Date(2055, 6, 2, 6, 10, 0); private final Weather weather = new Weather(worldDate); /** * Creates a new World. * * @param statistics a WorldStatistics object on which this World will record its status */ public World(WorldStatistics statistics) { worldStatistics = statistics; CreaturePresetFactory creaturePresetFactory = new JsonCreaturePresetFactory("creatures.json"); creatureFactory = new CreatureFactory(creaturePresetFactory); ItemPresetFactory jsonItemPresetFactory = new JsonItemPresetFactory("items.json"); ItemPresetFactory corpseItemPresetFactory = new CorpseItemPresetFactory(creatureFactory); itemFactory = new ItemFactory(jsonItemPresetFactory, corpseItemPresetFactory); } /** * Returns a thorough description of what is currently visible in the world's sky. */ public String describeTheSky(Observer observer) { return sky.describeYourself(observer); } public ItemFactory getItemFactory() { return itemFactory; } public CreatureFactory getCreatureFactory() { return creatureFactory; } public Date getWorldCreationDate() { return worldCreationDate; } public Date getWorldDate() { return worldDate; } /** * Adds a Location to this World. */ public void addLocation(Location locationObject, Point coordinates) { if (locations.containsKey(coordinates)) { throw new IllegalStateException("tried to repeatedly add a location to " + coordinates + "."); } if (!locationObject.getWorld().equals(this)) { World world = locationObject.getWorld(); throw new IllegalStateException("tried to add location with World field " + world + " to " + this + "."); } if (!locationObject.getPoint().equals(coordinates)) { Point point = locationObject.getPoint(); throw new IllegalStateException("tried to add location with Point field " + point + " to " + coordinates + "."); } locations.put(coordinates, locationObject); worldStatistics.addLocation(locationObject.getName().getSingular()); } /** * Gets the Location in the specified Point. If the Location in the Point has not yet been created, the world * generator will do it. * * @param point a Point object * @return a Location */ @NotNull public Location getLocation(@NotNull Point point) { if (!locations.containsKey(point)) { generator.expand(point); } return locations.get(point); } /** * Returns the PartOfDay constant that represents the current part of the day. */ public PartOfDay getPartOfDay() { return PartOfDay.getCorrespondingConstant(worldDate); } /** * Returns the current Weather of this World. */ public Weather getWeather() { return weather; } /** * Rolls the world date a given amount of seconds forward. */ public void rollDate(int seconds) { if (seconds <= 0) { DungeonLogger.warning("Cannot roll the World's Date back."); } else { worldDate = worldDate.plus(seconds, DungeonTimeUnit.SECOND); } } /** * Checks if there is a location at the specified point. Invoking this method may trigger world expansion. */ public boolean hasLocationAt(Point point) { if (alreadyHasLocationAt(point)) { return true; } else { if (point.getZ() == 0) { generator.expand(point); } return alreadyHasLocationAt(point); } } /** * Checks if there is already a location at the specified point. This method should only be called from World and * WorldGenerator. */ public boolean alreadyHasLocationAt(Point point) { return locations.containsKey(point); } }