package com.asteria.game.item;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
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 item nodes.
*
* @author lare96 <http://github.com/lare96>
*/
public final class ItemNodeManager extends Task {
/**
* The amount of ticks to execute the sequence listener.
*/
private static final int SEQUENCE_TICKS = 100;
/**
* The linked collection of registered items.
*/
public static final List<ItemNode> ITEMS = new LinkedList<>();
/**
* Creates a new {@link ItemNodeManager}.
*/
public ItemNodeManager() {
super(10, true);
}
@Override
public void execute() {
Iterator<ItemNode> it = ITEMS.iterator();
while (it.hasNext()) {
ItemNode item = it.next();
if (item.getCounter().incrementAndGet(10) >= ItemNodeManager.SEQUENCE_TICKS) {
item.onSequence();
item.getCounter().set(0);
}
if (!item.isRegistered()) {
item.dispose();
it.remove();
}
}
}
@Override
public void onCancel() {
World.submit(new ItemNodeManager());
}
@Override
public void onThrowable(Throwable t) {
ITEMS.stream().forEach(i -> i.dispose());
ITEMS.clear();
}
/**
* The method that attempts to register {@code item}.
*
* @param item
* the item to attempt to register.
* @param stack
* if the item should stack upon registration.
* @return {@code true} if the item was registered, {@code false} otherwise.
*/
public static boolean register(ItemNode item, boolean stack) {
if (item.isRegistered())
return false;
if (stack) {
Iterator<ItemNode> it = ITEMS.iterator();
while (it.hasNext()) {
ItemNode next = it.next();
if (next.getPlayer() == null || next.getPosition() == null || next.getItem() == null)
continue;
if (next.getItem().getId() == item.getItem().getId() && next.getPosition().equals(item.getPosition()) && next.getPlayer()
.equals(item.getPlayer())) {
next.getItem().incrementAmountBy(item.getItem().getAmount());
if (next.getItem().getAmount() <= 5) {
next.dispose();
next.create();
}
return true;
}
}
ITEMS.add(item);
item.create();
item.setRegistered(true);
return true;
}
if (item.getItem().getDefinition().isStackable()) {
ITEMS.add(item);
item.create();
item.setRegistered(true);
return true;
}
int amount = item.getItem().getAmount();
item.getItem().setAmount(1);
for (int i = 0; i < amount; i++) {
ITEMS.add(item);
item.create();
item.setRegistered(true);
}
return true;
}
/**
* The method that attempts to register {@code item} and does not stack by
* default.
*
* @param item
* the item to attempt to register.
* @return {@code true} if the item was registered, {@code false} otherwise.
*/
public static boolean register(ItemNode item) {
return register(item, false);
}
/**
* The method that attempts to unregister {@code item}.
*
* @param item
* the item to attempt to unregister.
* @return {@code true} if the item was unregistered, {@code false}
* otherwise.
*/
public static boolean unregister(ItemNode item) {
if (!item.isRegistered())
return false;
if (ITEMS.remove(item)) {
item.dispose();
item.setRegistered(true);
return true;
}
return false;
}
/**
* The method that retrieves the item with {@code id} on {@code position}.
*
* @param id
* the identifier to retrieve the item with.
* @param position
* the position to retrieve the item on.
* @return the item instance wrapped in an optional, or an empty optional if
* no item is found.
*/
public static Optional<ItemNode> getItem(int id, Position position) {
return ITEMS.stream().filter(
i -> i.getState() != ItemState.HIDDEN && i.isRegistered() && i.getItem().getId() == id && i.getPosition().equals(position))
.findFirst();
}
/**
* The method that updates all items in the region for {@code player}.
*
* @param player
* the player to update items for.
*/
public static void updateRegion(Player player) {
for (ItemNode item : ITEMS) {
if (item.getState() == ItemState.HIDDEN || !item.isRegistered())
continue;
player.getMessages().sendRemoveGroundItem(item);
if (item.getPosition().withinDistance(player.getPosition(), 60)) {
if (item.getPlayer() == null && item.getState() == ItemState.SEEN_BY_EVERYONE) {
player.getMessages().sendGroundItem(item);
continue;
}
if (item.getPlayer().equals(player) && item.getState() == ItemState.SEEN_BY_OWNER) {
player.getMessages().sendGroundItem(item);
continue;
}
}
}
}
}