package net.scapeemulator.game.model;
import java.util.Iterator;
import java.util.NoSuchElementException;
import net.scapeemulator.game.model.mob.Mob;
/**
* A {@link MobList} can store a certain amount of a certain {@link Mob} type.
* It provides a way to retrieve, add and remove as well as an
* {@link MobListIterator}.
*
* @author Graham?
* @param <T> The type of {@link Mob} this {@link MobList} should store.
*/
public final class MobList<T extends Mob> implements Iterable<T> {
private final Mob[] mobs;
private int size = 0;
/**
* Create a {@link MobList} with a certain maximum capacity.
* @param capacity The capacity of this {@link MobList}.
*/
public MobList(int capacity) {
mobs = new Mob[capacity];
}
/**
* The size of the list.
* @return The amount of {@link Mob}-s stored.
*/
public int getSize() {
return size;
}
/**
* Add mob to this {@link MobList}. Seeks the first empty spot in the list
* and fills it up. The Id of mob will be updated as well.
* ({@link Mob#setId(int)})
*
* @param mob The element to add.
* @return True when successfully added, false otherwise.
*/
public boolean add(T mob) {
for (int id = 0; id < mobs.length; id++) {
if (mobs[id] == null) {
mobs[id] = mob;
size++;
mob.setId(id + 1);
return true;
}
}
return false;
}
/**
* Gets the element on the index specified.
*
* @param index The index where to find retrieve the element from.
* @return The element on that index. null is returned when index exceeds
* the boundaries.
*/
@SuppressWarnings("unchecked")
public T get(int index) {
if (index <= 0 || index >= mobs.length + 1) {
return null;
}
return (T) mobs[index - 1];
}
/**
* Remove the element from this {@link MobList}.
*
* @param mob The element to remove.
*/
public void remove(T mob) {
int id = mob.getId();
assert id != 0;
id--;
assert mobs[id] == mob;
mobs[id] = null;
size--;
mob.resetId();
}
/**
* Gets a new {@link MobListIterator} to iterate over this {@link MobList}'s
* elements.
* @return A new {@link MobListIterator}.
*/
@Override
public Iterator<T> iterator() {
return new MobListIterator();
}
/**
* An {@link Iterator} to iterate over elements the {@link MobList}
* contains.
*/
private class MobListIterator implements Iterator<T> {
private int index = 0;
/**
* Gets whether there is another element left for {@link next()}.
* @return Whether there exists a next non-null element.
*/
@Override
public boolean hasNext() {
for (int i = index; i < mobs.length; i++) {
if (mobs[i] != null) {
return true;
}
}
return false;
}
/**
* Gets the next element.
*
* @return The next element.
* @throws NoSuchElementException When there is no next element.
* @see hasNext()
*/
@SuppressWarnings("unchecked")
@Override
public T next() {
for (; index < mobs.length; index++) {
if (mobs[index] != null) {
return (T) mobs[index++];
}
}
throw new NoSuchElementException();
}
/**
* Remove the current element.
* @throws IllegalStateException When there is no current element.
*/
@SuppressWarnings("unchecked")
@Override
public void remove() {
if (index == 0 || mobs[index - 1] == null) {
throw new IllegalStateException();
}
MobList.this.remove((T) mobs[index - 1]);
}
}
}