package com.asteria.game.object; import java.util.HashSet; import java.util.Iterator; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import com.asteria.game.World; import com.asteria.game.character.player.Player; import com.asteria.game.location.Position; import com.asteria.task.Task; /** * The node manager that manages all registered object nodes. * * @author lare96 <http://github.com/lare96> */ public final class ObjectNodeManager { /** * The hash collection of registered objects. */ public static final Set<ObjectNode> OBJECTS = new HashSet<>(); /** * The hash collection of objects that will be removed. */ public static final Set<Position> REMOVE_OBJECTS = new HashSet<>(); /** * The method that attempts to register {@code object}. * * @param object * the object to attempt to register. * @return {@code true} if the object was registered, {@code false} * otherwise. */ public static boolean register(ObjectNode object) { if (object.isRegistered()) return false; unregister(object.getPosition()); if (OBJECTS.add(object)) { object.setRegistered(true); object.create(); return true; } return false; } /** * The method that attempts to register {@code object} and then execute * {@code action} after specified amount of ticks. * * @param object * the object to attempt to register. * @param ticks * the amount of ticks to unregister this object after. * @return {@code true} if the object was registered, {@code false} * otherwise. */ public static boolean register(ObjectNode object, int ticks, Consumer<ObjectNode> action) { if (register(object)) { World.submit(new Task(ticks, false) { @Override public void execute() { action.accept(object); } }); return true; } return false; } /** * The method that attempts to register {@code object} for the specified * amount of ticks. * * @param object * the object to attempt to register. * @param ticks * the amount of ticks to unregister this object after. * @return {@code true} if the object was registered, {@code false} * otherwise. */ public static boolean register(ObjectNode object, int ticks) { return register(object, ticks, n -> { if (!unregister(n)) throw new IllegalStateException(n + " could not be removed " + "after " + ticks + " ticks!"); }); } /** * The method that attempts to unregister {@code object}. * * @param object * the object to attempt to unregister. * @return {@code true} if the object was unregistered, {@code false} * otherwise. */ public static boolean unregister(ObjectNode object) { if (!object.isRegistered()) return false; return unregister(object.getPosition()); } /** * The method that attempts to unregister the object on {@code position}. * * @param object * the object to attempt to unregister. * @return {@code true} if the object was unregistered, {@code false} * otherwise. */ public static boolean unregister(Position position) { for (Iterator<ObjectNode> iter = OBJECTS.iterator(); iter.hasNext();) { ObjectNode next = iter.next(); if (next.getPosition().equals(position)) { next.setRegistered(false); next.dispose(); iter.remove(); return true; } } return false; } /** * The method that retrieves the object on {@code position}. * * @param position * the position to retrieve the object on. * @return the object instance wrapped in an optional, or an empty optional * if no object is found. */ public static Optional<ObjectNode> getObject(Position position) { return OBJECTS.stream().filter(obj -> obj.getPosition().equals(position)).findFirst(); } /** * The method that updates all objects in the region for {@code player}. * * @param player * the player to update objects for. */ public static void updateRegion(Player player) { OBJECTS.forEach(obj -> { player.getMessages().sendRemoveObject(obj.getPosition()); if (obj.getPosition().withinDistance(player.getPosition(), 60)) { player.getMessages().sendObject(obj); } }); REMOVE_OBJECTS.forEach(obj -> { player.getMessages().sendRemoveObject(obj); }); } }