package org.mafagafogigante.dungeon.game; import org.mafagafogigante.dungeon.entity.Entity; import org.mafagafogigante.dungeon.entity.Luminosity; import org.mafagafogigante.dungeon.entity.creatures.Creature; import org.mafagafogigante.dungeon.entity.items.Item; import org.mafagafogigante.dungeon.entity.items.ItemFactory; import org.mafagafogigante.dungeon.entity.items.LocationInventory; import org.mafagafogigante.dungeon.util.Percentage; import org.jetbrains.annotations.NotNull; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; /** * The Location class that defines a Location of a World. */ public class Location implements Serializable { private final Id id; private final Name name; private final LocationDescription description; private final BlockedEntrances blockedEntrances; private final List<Creature> creatures; private final List<Spawner> spawners; private final LocationInventory items; private final Percentage lightPermittivity; private final World world; private final Point point; /** * Constructs a new location for the specified world based on the provided preset. * * <p>The creation date of the items in this location is the world date at the time this location was created. * * @param preset the LocationPreset object * @param world the World object */ public Location(@NotNull LocationPreset preset, @NotNull World world, @NotNull Point point) { this.id = preset.getId(); this.name = preset.getName(); this.description = preset.getDescription(); this.world = world; this.point = point; this.blockedEntrances = preset.getBlockedEntrances(); this.lightPermittivity = preset.getLightPermittivity(); this.creatures = new ArrayList<>(); this.spawners = new ArrayList<>(preset.getSpawners().size()); for (SpawnerPreset spawner : preset.getSpawners()) { spawners.add(new Spawner(spawner, this)); } this.items = new LocationInventory(); ItemFactory itemFactory = getWorld().getItemFactory(); for (Entry<Id, Percentage> entry : preset.getItems()) { if (Random.roll(entry.getValue())) { Id id = entry.getKey(); if (itemFactory.canMakeItem(id)) { this.addItem(itemFactory.makeItem(id, world.getWorldDate())); } } } } public Id getId() { return id; } public Name getName() { return name; } public LocationDescription getDescription() { return description; } /** * Refreshes all the Spawners of this location. */ public void refreshSpawners() { for (Spawner spawner : spawners) { spawner.refresh(); } } public Percentage getLightPermittivity() { return lightPermittivity; } /** * Returns the luminosity of the Location. This value depends on the World luminosity, on the Location's specific * light permittivity and on the luminosity of the Entities in this location. */ public Luminosity getLuminosity() { // Light permittivity is only applied to the luminosity that comes from the sky. Percentage fromEntities = Luminosity.resultantLuminosity(getEntities()).toPercentage(); Percentage fromTheWorld = getLightPermittivity().multiply(getWorld().getPartOfDay().getLuminosity().toPercentage()); return new Luminosity(new Percentage(Math.min(fromEntities.toDouble() + fromTheWorld.toDouble(), 1.0))); } public List<Creature> getCreatures() { return creatures; } public LocationInventory getInventory() { return items; } /** * Returns a list with all the entities in the current location. */ private List<Entity> getEntities() { List<Entity> entities = new ArrayList<>(); entities.addAll(getCreatures()); entities.addAll(getItemList()); return entities; } public List<Item> getItemList() { return items.getItems(); } public int getCreatureCount() { return creatures.size(); } /** * Returns the number of creatures in this Location. */ public int getCreatureCount(Id id) { int count = 0; for (Creature creature : creatures) { if (creature.getId().equals(id)) { count++; } } return count; } /** * Adds a Creature to this Location's Creature Collection. Also sets the location attribute of the specified Creature * to this Location. * * @param creature a Creature object */ public void addCreature(Creature creature) { creature.setLocation(this); creatures.add(creature); } public void addItem(Item item) { items.addItem(item); } public void removeItem(Item item) { items.removeItem(item); } /** * Removes a creature of this Location. */ public void removeCreature(Creature creature) { for (Spawner spawner : spawners) { spawner.notifyKill(creature); } // The creature must be removed after the spawns are notified. creatures.remove(creature); } public World getWorld() { return world; } /** * Returns at which point of the world this location is in it is. */ public Point getPoint() { return point; } public BlockedEntrances getBlockedEntrances() { return blockedEntrances; } public boolean isBlocked(Direction direction) { return blockedEntrances.isBlocked(direction); } /** * Refreshes all the items in this location's inventory and all the items in the inventories of the creatures in this * location. */ public void refreshItems() { getInventory().refreshItems(); for (Creature creature : creatures) { creature.getInventory().refreshItems(); } } @Override public String toString() { return name.getSingular(); } }