Files
Mindustry/core/src/mindustry/entities/EntityGroup.java
2020-02-10 15:51:01 -05:00

193 lines
4.8 KiB
Java

package mindustry.entities;
import arc.*;
import arc.func.*;
import arc.math.geom.*;
import arc.struct.*;
import mindustry.gen.*;
import java.util.*;
import static mindustry.Vars.collisions;
/** Represents a group of a certain type of entity.*/
@SuppressWarnings("unchecked")
public class EntityGroup<T extends Entityc> implements Iterable<T>{
private static int lastId = 0;
private final Array<T> array;
private final Array<T> intersectArray = new Array<>();
private final Rect viewport = new Rect();
private final Rect intersectRect = new Rect();
private IntMap<T> map;
private QuadTree tree;
private boolean clearing;
private int index;
public static int nextId(){
return lastId++;
}
public EntityGroup(Class<T> type, boolean spatial, boolean mapping){
array = new Array<>(false, 32, type);
if(spatial){
tree = new QuadTree<>(new Rect(0, 0, 0, 0));
}
if(mapping){
map = new IntMap<>();
}
}
public void sort(Comparator<? super T> comp){
array.sort(comp);
}
public void collide(EntityGroup<? extends Hitboxc> other){
collisions.collideGroups((EntityGroup<? extends Hitboxc>)this, other);
}
public void updatePhysics(){
collisions.updatePhysics((EntityGroup<? extends Hitboxc>)this);
}
public void update(){
each(Entityc::update);
}
public void each(Cons<T> cons){
for(index = 0; index < array.size; index++){
cons.get(array.items[index]);
}
}
public void each(Boolf<T> filter, Cons<T> cons){
for(index = 0; index < array.size; index++){
if(filter.get(array.items[index])) cons.get(array.items[index]);
}
}
public void draw(Cons<T> cons){
Core.camera.bounds(viewport);
each(e -> {
Drawc draw = (Drawc)e;
if(viewport.overlaps(draw.x() - draw.clipSize()/2f, draw.y() - draw.clipSize()/2f, draw.clipSize(), draw.clipSize())){
cons.get(e);
}
});
}
public boolean useTree(){
return map != null;
}
public boolean mappingEnabled(){
return map != null;
}
public T getByID(int id){
if(map == null) throw new RuntimeException("Mapping is not enabled for group " + id + "!");
return map.get(id);
}
public void removeByID(int id){
if(map == null) throw new RuntimeException("Mapping is not enabled for group " + id + "!");
T t = map.get(id);
if(t != null){ //remove if present in map already
remove(t);
}
}
public void intersect(float x, float y, float width, float height, Cons<? super T> out){
//don't waste time for empty groups
if(isEmpty()) return;
tree.getIntersect(out, x, y, width, height);
}
public Array<T> intersect(float x, float y, float width, float height){
intersectArray.clear();
//don't waste time for empty groups
if(isEmpty()) return intersectArray;
tree.getIntersect(intersectArray, intersectRect.set(x, y, width, height));
return intersectArray;
}
public QuadTree tree(){
if(tree == null) throw new RuntimeException("This group does not support quadtrees! Enable quadtrees when creating it.");
return tree;
}
/** Resizes the internal quadtree, if it is enabled.*/
public void resize(float x, float y, float w, float h){
if(tree != null){
tree = new QuadTree<>(new Rect(x, y, w, h));
}
}
public boolean isEmpty(){
return array.size == 0;
}
public T index(int i){
return array.get(i);
}
public int size(){
return array.size;
}
public boolean contains(Boolf<T> pred){
return array.contains(pred);
}
public int count(Boolf<T> pred){
return array.count(pred);
}
public void add(T type){
if(type == null) throw new RuntimeException("Cannot add a null entity!");
array.add(type);
if(mappingEnabled()){
map.put(type.id(), type);
}
}
public void remove(T type){
if(clearing) return;
if(type == null) throw new RuntimeException("Cannot remove a null entity!");
int idx = array.indexOf(type, true);
if(idx != -1){
array.remove(idx);
//fix iteration index when removing
if(index >= idx){
index --;
}
}
}
public void clear(){
clearing = true;
array.each(Entityc::remove);
array.clear();
if(map != null)
map.clear();
clearing = false;
}
public T find(Boolf<T> pred){
return array.find(pred);
}
@Override
public Iterator<T> iterator(){
return array.iterator();
}
}