Entity cleanup

This commit is contained in:
Anuken
2019-08-30 16:00:09 -04:00
parent f8f140090f
commit 39e0977231
10 changed files with 80 additions and 97 deletions

View File

@ -206,21 +206,21 @@ public class Vars implements Loadable{
pathfinder = new Pathfinder();
entities = new Entities();
playerGroup = entities.addGroup(Player.class).enableMapping();
tileGroup = entities.addGroup(TileEntity.class, false);
bulletGroup = entities.addGroup(Bullet.class).enableMapping();
effectGroup = entities.addGroup(EffectEntity.class, false);
groundEffectGroup = entities.addGroup(DrawTrait.class, false);
puddleGroup = entities.addGroup(Puddle.class).enableMapping();
shieldGroup = entities.addGroup(ShieldEntity.class, false);
fireGroup = entities.addGroup(Fire.class).enableMapping();
playerGroup = entities.add(Player.class).enableMapping();
tileGroup = entities.add(TileEntity.class, false);
bulletGroup = entities.add(Bullet.class).enableMapping();
effectGroup = entities.add(EffectEntity.class, false);
groundEffectGroup = entities.add(DrawTrait.class, false);
puddleGroup = entities.add(Puddle.class).enableMapping();
shieldGroup = entities.add(ShieldEntity.class, false);
fireGroup = entities.add(Fire.class).enableMapping();
unitGroups = new EntityGroup[Team.all.length];
for(Team team : Team.all){
unitGroups[team.ordinal()] = entities.addGroup(BaseUnit.class).enableMapping();
unitGroups[team.ordinal()] = entities.add(BaseUnit.class).enableMapping();
}
for(EntityGroup<?> group : entities.getAllGroups()){
for(EntityGroup<?> group : entities.all()){
group.setRemoveListener(entity -> {
if(entity instanceof SyncTrait && Net.client()){
netClient.addRemovedEntity((entity).getID());

View File

@ -12,7 +12,6 @@ import io.anuke.arc.util.io.ReusableByteInStream;
import io.anuke.arc.util.serialization.Base64Coder;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Entities;
import io.anuke.mindustry.entities.EntityGroup;
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
import io.anuke.mindustry.entities.traits.SyncTrait;
@ -253,7 +252,7 @@ public class NetClient implements ApplicationListener{
netClient.byteStream.setBytes(Net.decompressSnapshot(data, dataLen));
DataInputStream input = netClient.dataStream;
EntityGroup group = entities.getGroup(groupID);
EntityGroup group = entities.get(groupID);
//go through each entity
for(int j = 0; j < amount; j++){

View File

@ -15,7 +15,6 @@ import io.anuke.arc.util.CommandHandler.*;
import io.anuke.arc.util.io.*;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Entities;
import io.anuke.mindustry.entities.EntityGroup;
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
import io.anuke.mindustry.entities.traits.Entity;
@ -589,7 +588,7 @@ public class NetServer implements ApplicationListener{
viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY);
//check for syncable groups
for(EntityGroup<?> group : entities.getAllGroups()){
for(EntityGroup<?> group : entities.all()){
if(group.isEmpty() || !(group.all().get(0) instanceof SyncTrait)) continue;
//make sure mapping is enabled for this group

View File

@ -209,9 +209,9 @@ public class Renderer implements ApplicationListener{
blocks.floor.drawFloor();
draw(groundEffectGroup, e -> e instanceof BelowLiquidTrait);
draw(puddleGroup);
draw(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait));
groundEffectGroup.draw(e -> e instanceof BelowLiquidTrait);
puddleGroup.draw();
groundEffectGroup.draw(e -> !(e instanceof BelowLiquidTrait));
blocks.processBlocks();
@ -248,8 +248,8 @@ public class Renderer implements ApplicationListener{
bloom.capture();
}
draw(bulletGroup);
draw(effectGroup);
bulletGroup.draw();
effectGroup.draw();
Draw.flush();
if(bloom != null && !pixelator.enabled()){
@ -257,15 +257,15 @@ public class Renderer implements ApplicationListener{
}
overlays.drawBottom();
draw(playerGroup, p -> true, Player::drawBuildRequests);
playerGroup.draw(p -> true, Player::drawBuildRequests);
if(entities.countInBounds(shieldGroup) > 0){
if(shieldGroup.countInBounds() > 0){
if(settings.getBool("animatedshields") && Shaders.shield != null){
Draw.flush();
shieldBuffer.begin();
graphics.clear(Color.CLEAR);
entities.draw(shieldGroup);
entities.draw(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver());
shieldGroup.draw();
shieldGroup.draw(shield -> true, ShieldEntity::drawOver);
Draw.flush();
shieldBuffer.end();
Draw.shader(Shaders.shield);
@ -274,13 +274,13 @@ public class Renderer implements ApplicationListener{
Draw.color();
Draw.shader();
}else{
entities.draw(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawSimple());
shieldGroup.draw(shield -> true, ShieldEntity::drawSimple);
}
}
overlays.drawTop();
draw(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName);
playerGroup.draw(p -> !p.isDead() && !p.isLocal, Player::drawName);
Draw.color();
Draw.flush();
@ -297,12 +297,12 @@ public class Renderer implements ApplicationListener{
for(EntityGroup<? extends BaseUnit> group : unitGroups){
if(!group.isEmpty()){
draw(group, unit -> !unit.isDead(), draw::accept);
group.draw(unit -> !unit.isDead(), draw::accept);
}
}
if(!playerGroup.isEmpty()){
draw(playerGroup, unit -> !unit.isDead(), draw::accept);
playerGroup.draw(unit -> !unit.isDead(), draw::accept);
}
Draw.color();
@ -314,12 +314,12 @@ public class Renderer implements ApplicationListener{
for(EntityGroup<? extends BaseUnit> group : unitGroups){
if(!group.isEmpty()){
draw(group, unit -> unit.isFlying() && !unit.isDead(), baseUnit -> baseUnit.drawShadow(trnsX, trnsY));
group.draw(unit -> unit.isFlying() && !unit.isDead(), baseUnit -> baseUnit.drawShadow(trnsX, trnsY));
}
}
if(!playerGroup.isEmpty()){
draw(playerGroup, unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY));
playerGroup.draw(unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY));
}
Draw.color();
@ -331,29 +331,17 @@ public class Renderer implements ApplicationListener{
if(group.count(p -> p.isFlying() == flying) + playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue;
draw(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
draw(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team && !p.isDead(), Unit::drawUnder);
unitGroups[team.ordinal()].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team && !p.isDead(), Unit::drawUnder);
draw(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll);
draw(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawAll);
unitGroups[team.ordinal()].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll);
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawAll);
draw(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
draw(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
unitGroups[team.ordinal()].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
}
}
public <T extends DrawTrait> void draw(EntityGroup<T> group){
draw(group, t -> true, DrawTrait::draw);
}
public <T extends DrawTrait> void draw(EntityGroup<T> group, Predicate<T> toDraw){
draw(group, toDraw, DrawTrait::draw);
}
public <T extends DrawTrait> void draw(EntityGroup<T> group, Predicate<T> toDraw, Consumer<T> drawer){
entities.draw(group, toDraw, drawer);
}
public void scaleCamera(float amount){
targetscale += amount;
clampScale();

View File

@ -178,7 +178,7 @@ public class World{
addDarkness(tiles);
}
entities.getAllGroups().each(group -> group.resize(-finalWorldBounds, -finalWorldBounds, tiles.length * tilesize + finalWorldBounds * 2, tiles[0].length * tilesize + finalWorldBounds * 2));
entities.all().each(group -> group.resize(-finalWorldBounds, -finalWorldBounds, tiles.length * tilesize + finalWorldBounds * 2, tiles[0].length * tilesize + finalWorldBounds * 2));
generating = false;
Events.fire(new WorldLoadEvent());

View File

@ -1,17 +1,11 @@
package io.anuke.mindustry.entities;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.math.geom.*;
import io.anuke.mindustry.entities.traits.*;
/** Simple container for managing entity groups.*/
public class Entities{
private final Array<EntityGroup<?>> groupArray = new Array<>();
private final Rectangle viewport = new Rectangle();
private final boolean clip = true;
private int count = 0;
public void clear(){
for(EntityGroup group : groupArray){
@ -19,52 +13,21 @@ public class Entities{
}
}
public EntityGroup<?> getGroup(int id){
public EntityGroup<?> get(int id){
return groupArray.get(id);
}
public Array<EntityGroup<?>> getAllGroups(){
public Array<EntityGroup<?>> all(){
return groupArray;
}
public <T extends Entity> EntityGroup<T> addGroup(Class<T> type){
return addGroup(type, true);
public <T extends Entity> EntityGroup<T> add(Class<T> type){
return add(type, true);
}
public <T extends Entity> EntityGroup<T> addGroup(Class<T> type, boolean useTree){
public <T extends Entity> EntityGroup<T> add(Class<T> type, boolean useTree){
EntityGroup<T> group = new EntityGroup<>(groupArray.size, type, useTree);
groupArray.add(group);
return group;
}
public int countInBounds(EntityGroup<?> group){
count = 0;
draw(group, e -> true, e -> count++);
return count;
}
public void draw(EntityGroup<?> group){
draw(group, e -> true);
}
public <T extends DrawTrait> void draw(EntityGroup<?> group, Predicate<T> toDraw){
draw(group, toDraw, DrawTrait::draw);
}
@SuppressWarnings("unchecked")
public <T extends DrawTrait> void draw(EntityGroup<?> group, Predicate<T> toDraw, Consumer<T> cons){
if(clip){
Camera cam = Core.camera;
viewport.set(cam.position.x - cam.width / 2, cam.position.y - cam.height / 2, cam.width, cam.height);
}
for(Entity e : group.all()){
if(!(e instanceof DrawTrait) || !toDraw.test((T)e) || !e.isAdded()) continue;
DrawTrait draw = (DrawTrait)e;
if(!clip || viewport.overlaps(draw.getX() - draw.drawSize()/2f, draw.getY() - draw.drawSize()/2f, draw.drawSize(), draw.drawSize())){
cons.accept((T)e);
}
}
}
}

View File

@ -1,12 +1,15 @@
package io.anuke.mindustry.entities;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.math.geom.*;
import io.anuke.mindustry.entities.traits.*;
import static io.anuke.mindustry.Vars.collisions;
@SuppressWarnings("unchecked")
public class EntityGroup<T extends Entity>{
private final boolean useTree;
private final int id;
@ -19,6 +22,10 @@ public class EntityGroup<T extends Entity>{
private Consumer<T> removeListener;
private Consumer<T> addListener;
private final Rectangle viewport = new Rectangle();
private final boolean clip = true;
private int count = 0;
public EntityGroup(int id, Class<T> type, boolean useTree){
this.useTree = useTree;
this.id = id;
@ -41,6 +48,34 @@ public class EntityGroup<T extends Entity>{
}
}
public int countInBounds(){
count = 0;
draw(e -> true, e -> count++);
return count;
}
public void draw(){
draw(e -> true);
}
public void draw(Predicate<T> toDraw){
draw(toDraw, t -> ((DrawTrait)t).draw());
}
public void draw(Predicate<T> toDraw, Consumer<T> cons){
Camera cam = Core.camera;
viewport.set(cam.position.x - cam.width / 2, cam.position.y - cam.height / 2, cam.width, cam.height);
for(Entity e : all()){
if(!(e instanceof DrawTrait) || !toDraw.test((T)e) || !e.isAdded()) continue;
DrawTrait draw = (DrawTrait)e;
if(viewport.overlaps(draw.getX() - draw.drawSize()/2f, draw.getY() - draw.drawSize()/2f, draw.drawSize(), draw.drawSize())){
cons.accept((T)e);
}
}
}
public boolean useTree(){
return useTree;
}

View File

@ -55,7 +55,7 @@ public class Pixelator implements Disposable{
Draw.rect(Draw.wrap(buffer.getTexture()), Core.camera.position.x, Core.camera.position.y, Core.camera.width, -Core.camera.height);
Draw.blend();
renderer.draw(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName);
playerGroup.draw(p -> !p.isDead() && !p.isLocal, Player::drawName);
Core.camera.position.set(px, py);
Core.settings.put("animatedwater", hadWater);

View File

@ -209,7 +209,7 @@ public abstract class SaveVersion extends SaveFileReader{
//write entity chunk
int groups = 0;
for(EntityGroup<?> group : entities.getAllGroups()){
for(EntityGroup<?> group : entities.all()){
if(!group.isEmpty() && group.all().get(0) instanceof SaveTrait){
groups++;
}
@ -217,7 +217,7 @@ public abstract class SaveVersion extends SaveFileReader{
stream.writeByte(groups);
for(EntityGroup<?> group : entities.getAllGroups()){
for(EntityGroup<?> group : entities.all()){
if(!group.isEmpty() && group.all().get(0) instanceof SaveTrait){
stream.writeInt(group.size());
for(Entity entity : group.all()){

View File

@ -5,7 +5,6 @@ import io.anuke.annotations.Annotations.WriteClass;
import io.anuke.arc.graphics.Color;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.Effects.Effect;
import io.anuke.mindustry.entities.Entities;
import io.anuke.mindustry.entities.bullet.Bullet;
import io.anuke.mindustry.entities.bullet.BulletType;
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
@ -58,7 +57,7 @@ public class TypeIO{
byte gid = buffer.get();
if(gid == -1) return null;
int id = buffer.getInt();
return (Unit)entities.getGroup(gid).getByID(id);
return (Unit)entities.get(gid).getByID(id);
}
@WriteClass(ShooterTrait.class)
@ -71,7 +70,7 @@ public class TypeIO{
public static ShooterTrait readShooter(ByteBuffer buffer){
byte gid = buffer.get();
int id = buffer.getInt();
return (ShooterTrait)entities.getGroup(gid).getByID(id);
return (ShooterTrait)entities.get(gid).getByID(id);
}
@WriteClass(Bullet.class)