Auto-rebuilding enemy drones / GC improvements
This commit is contained in:
@@ -13,7 +13,6 @@ import io.anuke.mindustry.entities.traits.Entity;
|
||||
import static io.anuke.mindustry.Vars.collisions;
|
||||
|
||||
public class Entities{
|
||||
public static final int maxLeafObjects = 4;
|
||||
private static final Array<EntityGroup<?>> groupArray = new Array<>();
|
||||
private static final IntMap<EntityGroup<?>> groups = new IntMap<>();
|
||||
private static final Rectangle viewport = new Rectangle();
|
||||
|
||||
@@ -17,7 +17,7 @@ public class EntityGroup<T extends Entity>{
|
||||
private final Array<T> entitiesToRemove = new Array<>(false, 16);
|
||||
private final Array<T> entitiesToAdd = new Array<>(false, 16);
|
||||
private IntMap<T> map;
|
||||
private QuadTree<T> tree;
|
||||
private QuadTree tree;
|
||||
private Consumer<T> removeListener;
|
||||
private Consumer<T> addListener;
|
||||
|
||||
@@ -27,7 +27,7 @@ public class EntityGroup<T extends Entity>{
|
||||
this.type = type;
|
||||
|
||||
if(useTree){
|
||||
tree = new QuadTree<>(Entities.maxLeafObjects, new Rectangle(0, 0, 0, 0));
|
||||
tree = new QuadTree<>(new Rectangle(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ public class EntityGroup<T extends Entity>{
|
||||
/** Resizes the internal quadtree, if it is enabled.*/
|
||||
public void resize(float x, float y, float w, float h){
|
||||
if(useTree){
|
||||
tree = new QuadTree<>(Entities.maxLeafObjects, new Rectangle(x, y, w, h));
|
||||
tree = new QuadTree<>(new Rectangle(x, y, w, h));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ public interface BuilderMinerTrait extends MinerTrait, BuilderTrait{
|
||||
updateBuilding();
|
||||
|
||||
//mine only when not building
|
||||
if(getCurrentRequest() == null){
|
||||
if(buildRequest() == null){
|
||||
updateMining();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,21 +35,21 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
Unit unit = (Unit)this;
|
||||
//remove already completed build requests
|
||||
removal.clear();
|
||||
for(BuildRequest req : getPlaceQueue()){
|
||||
for(BuildRequest req : buildQueue()){
|
||||
removal.add(req);
|
||||
}
|
||||
|
||||
getPlaceQueue().clear();
|
||||
buildQueue().clear();
|
||||
|
||||
for(BuildRequest request : removal){
|
||||
if(!((request.breaking && world.tile(request.x, request.y).block() == Blocks.air) ||
|
||||
(!request.breaking && (world.tile(request.x, request.y).rotation() == request.rotation || !request.block.rotate)
|
||||
&& world.tile(request.x, request.y).block() == request.block))){
|
||||
getPlaceQueue().addLast(request);
|
||||
buildQueue().addLast(request);
|
||||
}
|
||||
}
|
||||
|
||||
BuildRequest current = getCurrentRequest();
|
||||
BuildRequest current = buildRequest();
|
||||
|
||||
if(current == null){
|
||||
return;
|
||||
@@ -58,9 +58,9 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
Tile tile = world.tile(current.x, current.y);
|
||||
|
||||
if(dst(tile) > finalPlaceDst){
|
||||
if(getPlaceQueue().size > 1){
|
||||
getPlaceQueue().removeFirst();
|
||||
getPlaceQueue().addLast(current);
|
||||
if(buildQueue().size > 1){
|
||||
buildQueue().removeFirst();
|
||||
buildQueue().addLast(current);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
}else if(canCreateBlocks() && current.breaking && Build.validBreak(getTeam(), current.x, current.y)){
|
||||
Call.beginBreak(getTeam(), current.x, current.y);
|
||||
}else{
|
||||
getPlaceQueue().removeFirst();
|
||||
buildQueue().removeFirst();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
}
|
||||
|
||||
/** Returns the queue for storing build requests. */
|
||||
Queue<BuildRequest> getPlaceQueue();
|
||||
Queue<BuildRequest> buildQueue();
|
||||
|
||||
/** Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all. */
|
||||
float getBuildPower(Tile tile);
|
||||
@@ -126,7 +126,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
}
|
||||
|
||||
default void writeBuilding(DataOutput output) throws IOException{
|
||||
BuildRequest request = getCurrentRequest();
|
||||
BuildRequest request = buildRequest();
|
||||
|
||||
if(request != null){
|
||||
output.writeByte(request.breaking ? 1 : 0);
|
||||
@@ -146,7 +146,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
}
|
||||
|
||||
default void readBuilding(DataInput input, boolean applyChanges) throws IOException{
|
||||
if(applyChanges) getPlaceQueue().clear();
|
||||
if(applyChanges) buildQueue().clear();
|
||||
|
||||
byte type = input.readByte();
|
||||
if(type != -1){
|
||||
@@ -165,26 +165,26 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
request.progress = progress;
|
||||
|
||||
if(applyChanges){
|
||||
getPlaceQueue().addLast(request);
|
||||
buildQueue().addLast(request);
|
||||
}else if(isBuilding()){
|
||||
getCurrentRequest().progress = progress;
|
||||
buildRequest().progress = progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return whether this builder's place queue contains items. */
|
||||
default boolean isBuilding(){
|
||||
return getPlaceQueue().size != 0;
|
||||
return buildQueue().size != 0;
|
||||
}
|
||||
|
||||
/** Clears the placement queue. */
|
||||
default void clearBuilding(){
|
||||
getPlaceQueue().clear();
|
||||
buildQueue().clear();
|
||||
}
|
||||
|
||||
/** Add another build requests to the tail of the queue, if it doesn't exist there yet. */
|
||||
default void addBuildRequest(BuildRequest place){
|
||||
for(BuildRequest request : getPlaceQueue()){
|
||||
for(BuildRequest request : buildQueue()){
|
||||
if(request.x == place.x && request.y == place.y){
|
||||
return;
|
||||
}
|
||||
@@ -193,15 +193,15 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
if(tile != null && tile.entity instanceof BuildEntity){
|
||||
place.progress = tile.<BuildEntity>entity().progress;
|
||||
}
|
||||
getPlaceQueue().addLast(place);
|
||||
buildQueue().addLast(place);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the build requests currently active, or the one at the top of the queue.
|
||||
* May return null.
|
||||
*/
|
||||
default BuildRequest getCurrentRequest(){
|
||||
return getPlaceQueue().size == 0 ? null : getPlaceQueue().first();
|
||||
default BuildRequest buildRequest(){
|
||||
return buildQueue().size == 0 ? null : buildQueue().first();
|
||||
}
|
||||
|
||||
//due to iOS weirdness, this is apparently required
|
||||
@@ -215,7 +215,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
if(!isBuilding()) return;
|
||||
|
||||
Unit unit = (Unit)this;
|
||||
BuildRequest request = getCurrentRequest();
|
||||
BuildRequest request = buildRequest();
|
||||
Tile tile = world.tile(request.x, request.y);
|
||||
|
||||
if(dst(tile) > placeDistance && !state.isEditor()){
|
||||
|
||||
@@ -112,10 +112,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
this.state.set(state);
|
||||
}
|
||||
|
||||
public void retarget(Runnable run){
|
||||
if(timer.get(timerTarget, 20)){
|
||||
run.run();
|
||||
}
|
||||
public boolean retarget(){
|
||||
return timer.get(timerTarget, 20);
|
||||
}
|
||||
|
||||
/** Only runs when the unit has a target. */
|
||||
|
||||
@@ -32,7 +32,7 @@ public abstract class FlyingUnit extends BaseUnit{
|
||||
target = null;
|
||||
}
|
||||
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
targetClosest();
|
||||
|
||||
if(target == null) targetClosestEnemyFlag(BlockFlag.producer);
|
||||
@@ -41,7 +41,7 @@ public abstract class FlyingUnit extends BaseUnit{
|
||||
if(target == null){
|
||||
setState(patrol);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if(target != null){
|
||||
attack(type.attackLength);
|
||||
@@ -71,7 +71,7 @@ public abstract class FlyingUnit extends BaseUnit{
|
||||
},
|
||||
patrol = new UnitState(){
|
||||
public void update(){
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
targetClosest();
|
||||
targetClosestEnemyFlag(BlockFlag.target);
|
||||
|
||||
@@ -81,7 +81,7 @@ public abstract class FlyingUnit extends BaseUnit{
|
||||
}
|
||||
|
||||
target = getClosestCore();
|
||||
});
|
||||
};
|
||||
|
||||
if(target != null){
|
||||
circle(60f + Mathf.absin(Time.time() + Mathf.randomSeed(id) * 1200f, 70f, 1200f));
|
||||
|
||||
@@ -176,7 +176,9 @@ public abstract class GroundUnit extends BaseUnit{
|
||||
target = null;
|
||||
}
|
||||
|
||||
retarget(this::targetClosest);
|
||||
if(retarget()){
|
||||
targetClosest();
|
||||
}
|
||||
}
|
||||
|
||||
protected void patrol(){
|
||||
|
||||
@@ -241,7 +241,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<BuildRequest> getPlaceQueue(){
|
||||
public Queue<BuildRequest> buildQueue(){
|
||||
return placeQueue;
|
||||
}
|
||||
|
||||
@@ -428,8 +428,8 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
/** Draw all current build requests. Does not draw the beam effect, only the positions. */
|
||||
public void drawBuildRequests(){
|
||||
BuildRequest last = null;
|
||||
for(BuildRequest request : getPlaceQueue()){
|
||||
if(request.progress > 0.01f || (getCurrentRequest() == request && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue;
|
||||
for(BuildRequest request : buildQueue()){
|
||||
if(request.progress > 0.01f || (buildRequest() == request && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue;
|
||||
|
||||
if(request.breaking){
|
||||
Block block = world.ltile(request.x, request.y).block();
|
||||
|
||||
@@ -19,14 +19,14 @@ public abstract class BaseDrone extends FlyingUnit{
|
||||
if(health >= maxHealth()){
|
||||
state.set(attack);
|
||||
}else if(!targetHasFlag(BlockFlag.repair)){
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
Tile repairPoint = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair));
|
||||
if(repairPoint != null){
|
||||
target = repairPoint;
|
||||
}else{
|
||||
setState(getStartState());
|
||||
}
|
||||
});
|
||||
}
|
||||
}else{
|
||||
circle(40f);
|
||||
}
|
||||
|
||||
@@ -6,12 +6,15 @@ import io.anuke.arc.collection.IntIntMap;
|
||||
import io.anuke.arc.collection.Queue;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.util.*;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.entities.EntityGroup;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait;
|
||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||
import io.anuke.mindustry.entities.type.*;
|
||||
import io.anuke.mindustry.entities.units.UnitState;
|
||||
import io.anuke.mindustry.game.EventType.BuildSelectEvent;
|
||||
import io.anuke.mindustry.game.Teams.TeamData;
|
||||
import io.anuke.mindustry.gen.BrokenBlock;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
@@ -20,7 +23,6 @@ import java.io.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
//TODO follow players
|
||||
public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
private static final StaticReset reset = new StaticReset();
|
||||
private static final IntIntMap totals = new IntIntMap();
|
||||
@@ -43,12 +45,22 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
BuildEntity entity = (BuildEntity)target;
|
||||
TileEntity core = getClosestCore();
|
||||
|
||||
if(entity != null && core != null && (entity.progress < 1f || entity.progress > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid
|
||||
if(isBuilding() && entity == null && isRebuild()){
|
||||
target = world.tile(buildRequest().x, buildRequest().y);
|
||||
circle(placeDistance * 0.7f);
|
||||
target = null;
|
||||
|
||||
BuildRequest request = buildRequest();
|
||||
|
||||
if(world.tile(request.x, request.y).entity instanceof BuildEntity){
|
||||
target = world.tile(request.x, request.y).entity;
|
||||
}
|
||||
}else if(entity != null && core != null && (entity.progress < 1f || entity.progress > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid
|
||||
if(!isBuilding() && dst(target) < placeDistance * 0.9f){ //within distance, begin placing
|
||||
if(isBreaking){
|
||||
getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y));
|
||||
buildQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y));
|
||||
}else{
|
||||
getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.rotation(), entity.cblock));
|
||||
buildQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.rotation(), entity.cblock));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +70,7 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
if(playerTarget == null || playerTarget.getTeam() != team || !playerTarget.isValid()){
|
||||
playerTarget = null;
|
||||
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
float minDst = Float.POSITIVE_INFINITY;
|
||||
int minDrones = Integer.MAX_VALUE;
|
||||
|
||||
@@ -75,7 +87,13 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(getSpawner() != null){
|
||||
target = getSpawner();
|
||||
circle(40f);
|
||||
target = null;
|
||||
}
|
||||
}else{
|
||||
incDrones(playerTarget);
|
||||
TargetTrait prev = target;
|
||||
@@ -103,7 +121,7 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
BuilderDrone drone = (BuilderDrone)unit;
|
||||
if(drone.isBuilding()){
|
||||
//stop building if opposite building begins.
|
||||
BuildRequest req = drone.getCurrentRequest();
|
||||
BuildRequest req = drone.buildRequest();
|
||||
if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){
|
||||
drone.clearBuilding();
|
||||
drone.target = null;
|
||||
@@ -131,13 +149,17 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
}
|
||||
}
|
||||
|
||||
boolean isRebuild(){
|
||||
return Vars.state.rules.enemyCheat && team == waveTeam;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBuildPower(Tile tile){
|
||||
return type.buildPower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<BuildRequest> getPlaceQueue(){
|
||||
public Queue<BuildRequest> buildQueue(){
|
||||
return placeQueue;
|
||||
}
|
||||
|
||||
@@ -147,8 +169,8 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
|
||||
if(!isBuilding() && timer.get(timerTarget2, 15)){
|
||||
for(Player player : playerGroup.all()){
|
||||
if(player.getTeam() == team && player.getCurrentRequest() != null){
|
||||
BuildRequest req = player.getCurrentRequest();
|
||||
if(player.getTeam() == team && player.buildRequest() != null){
|
||||
BuildRequest req = player.buildRequest();
|
||||
Tile tile = world.tile(req.x, req.y);
|
||||
if(tile != null && tile.entity instanceof BuildEntity){
|
||||
BuildEntity b = tile.entity();
|
||||
@@ -162,6 +184,16 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isRebuild()){
|
||||
TeamData data = Vars.state.teams.get(team);
|
||||
if(!data.brokenBlocks.isEmpty()){
|
||||
long block = data.brokenBlocks.removeLast();
|
||||
|
||||
placeQueue.addFirst(new BuildRequest(BrokenBlock.x(block), BrokenBlock.y(block), BrokenBlock.rotation(block), content.block(BrokenBlock.block(block))));
|
||||
setState(build);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateBuilding();
|
||||
|
||||
@@ -52,13 +52,13 @@ public class MinerDrone extends BaseDrone implements MinerTrait{
|
||||
return;
|
||||
}
|
||||
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
findItem();
|
||||
|
||||
if(targetItem == null) return;
|
||||
|
||||
target = world.indexer.findClosestOre(x, y, targetItem);
|
||||
});
|
||||
};
|
||||
|
||||
if(target instanceof Tile){
|
||||
moveTo(type.range / 1.5f);
|
||||
|
||||
@@ -19,7 +19,9 @@ public class RepairDrone extends BaseDrone{
|
||||
|
||||
public void update(){
|
||||
|
||||
retarget(() -> target = Units.findDamagedTile(team, x, y));
|
||||
if(retarget()){
|
||||
target = Units.findDamagedTile(team, x, y);
|
||||
}
|
||||
|
||||
if(target != null){
|
||||
if(target.dst(RepairDrone.this) > type.range){
|
||||
|
||||
Reference in New Issue
Block a user