From 625fbdb2d7faac3a0fc3580d933db20f2c1c96bb Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 16 Jun 2019 18:50:51 -0400 Subject: [PATCH] Auto-rebuilding enemy drones / GC improvements --- core/assets/maps/saltFlats.msav | Bin 16132 -> 16490 bytes core/src/io/anuke/mindustry/content/Fx.java | 6 +- core/src/io/anuke/mindustry/core/Logic.java | 2 +- .../io/anuke/mindustry/core/NetClient.java | 4 +- .../io/anuke/mindustry/core/NetServer.java | 4 +- .../io/anuke/mindustry/entities/Entities.java | 1 - .../anuke/mindustry/entities/EntityGroup.java | 6 +- .../entities/traits/BuilderMinerTrait.java | 2 +- .../entities/traits/BuilderTrait.java | 40 +++++++------- .../mindustry/entities/type/BaseUnit.java | 6 +- .../mindustry/entities/type/FlyingUnit.java | 8 +-- .../mindustry/entities/type/GroundUnit.java | 4 +- .../anuke/mindustry/entities/type/Player.java | 6 +- .../entities/type/base/BaseDrone.java | 4 +- .../entities/type/base/BuilderDrone.java | 52 ++++++++++++++---- .../entities/type/base/MinerDrone.java | 4 +- .../entities/type/base/RepairDrone.java | 4 +- core/src/io/anuke/mindustry/game/Teams.java | 10 +++- .../anuke/mindustry/input/DesktopInput.java | 4 +- core/src/io/anuke/mindustry/io/JsonIO.java | 25 ++++++++- .../io/anuke/mindustry/io/SaveVersion.java | 36 ++++++++++-- .../ui/dialogs/CustomRulesDialog.java | 1 + .../ui/dialogs/SettingsMenuDialog.java | 2 +- 23 files changed, 159 insertions(+), 72 deletions(-) diff --git a/core/assets/maps/saltFlats.msav b/core/assets/maps/saltFlats.msav index c982e27d4ea64eac40302b494241d90799a33b4d..a0688e922d2f03940c0486b906d134e5b9542587 100644 GIT binary patch literal 16490 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Ξ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 J#-b;N$^Z)6%z^*_ diff --git a/core/src/io/anuke/mindustry/content/Fx.java b/core/src/io/anuke/mindustry/content/Fx.java index 3846f8afbf..681340e4e9 100644 --- a/core/src/io/anuke/mindustry/content/Fx.java +++ b/core/src/io/anuke/mindustry/content/Fx.java @@ -792,8 +792,9 @@ public class Fx implements ContentList{ Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); for(int i : Mathf.signs){ + float ex = e.x, ey = e.y, fout = e.fout(); Angles.randLenVectors(e.id, 4, 1f + e.finpow() * 11f, e.rotation + 90f * i, 20f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f); + Fill.circle(ex + x, ey + y, fout * 1.5f); }); } @@ -816,8 +817,9 @@ public class Fx implements ContentList{ Draw.color(Color.LIGHT_GRAY); for(int i : Mathf.signs){ + float ex = e.x, ey = e.y, fout = e.fout(); Angles.randLenVectors(e.id, 4, -e.finpow() * 15f, e.rotation + 90f * i, 25f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 2f); + Fill.circle(ex + x, ey + y, fout * 2f); }); } diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 3d5901dc97..c6eddd548f 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -61,7 +61,7 @@ public class Logic implements ApplicationListener{ } TeamData data = state.teams.get(tile.getTeam()); - data.brokenBlocks.addFirst(BrokenBlock.get(tile.x, tile.y, block.id, tile.rotation())); + data.brokenBlocks.addFirst(BrokenBlock.get(tile.x, tile.y, tile.rotation(), block.id)); }); } diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 658afabd2c..dab0c9b31b 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -360,11 +360,11 @@ public class NetClient implements ApplicationListener{ if(timer.get(0, playerSyncTime)){ BuildRequest[] requests; //limit to 10 to prevent buffer overflows - int usedRequests = Math.min(player.getPlaceQueue().size, 10); + int usedRequests = Math.min(player.buildQueue().size, 10); requests = new BuildRequest[usedRequests]; for(int i = 0; i < usedRequests; i++){ - requests[i] = player.getPlaceQueue().get(i); + requests[i] = player.buildQueue().get(i); } Call.onClientShapshot(lastSent++, player.x, player.y, diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 7da3a47a24..ab4eca7e0d 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -282,7 +282,7 @@ public class NetServer implements ApplicationListener{ player.isTyping = chatting; player.isBoosting = boosting; player.isShooting = shooting; - player.getPlaceQueue().clear(); + player.buildQueue().clear(); for(BuildRequest req : requests){ Tile tile = world.tile(req.x, req.y); if(tile == null) continue; @@ -292,7 +292,7 @@ public class NetServer implements ApplicationListener{ }else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || tile.rotation() == req.rotation)){ continue; } - player.getPlaceQueue().addLast(req); + player.buildQueue().addLast(req); } vector.set(x - player.getInterpolator().target.x, y - player.getInterpolator().target.y); diff --git a/core/src/io/anuke/mindustry/entities/Entities.java b/core/src/io/anuke/mindustry/entities/Entities.java index d0d5d16dea..2a6f388ff5 100755 --- a/core/src/io/anuke/mindustry/entities/Entities.java +++ b/core/src/io/anuke/mindustry/entities/Entities.java @@ -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> groupArray = new Array<>(); private static final IntMap> groups = new IntMap<>(); private static final Rectangle viewport = new Rectangle(); diff --git a/core/src/io/anuke/mindustry/entities/EntityGroup.java b/core/src/io/anuke/mindustry/entities/EntityGroup.java index 314aa63d76..d3010c84f3 100644 --- a/core/src/io/anuke/mindustry/entities/EntityGroup.java +++ b/core/src/io/anuke/mindustry/entities/EntityGroup.java @@ -17,7 +17,7 @@ public class EntityGroup{ private final Array entitiesToRemove = new Array<>(false, 16); private final Array entitiesToAdd = new Array<>(false, 16); private IntMap map; - private QuadTree tree; + private QuadTree tree; private Consumer removeListener; private Consumer addListener; @@ -27,7 +27,7 @@ public class EntityGroup{ 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{ /** 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)); } } diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderMinerTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderMinerTrait.java index 253e5c41d0..5fbde29251 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderMinerTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderMinerTrait.java @@ -7,7 +7,7 @@ public interface BuilderMinerTrait extends MinerTrait, BuilderTrait{ updateBuilding(); //mine only when not building - if(getCurrentRequest() == null){ + if(buildRequest() == null){ updateMining(); } } diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index 45cb67da96..27361d61d5 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -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 getPlaceQueue(); + Queue 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.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()){ diff --git a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java index 440cab7a2b..de040681cc 100644 --- a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java @@ -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. */ diff --git a/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java index dc92379241..e0a95b7866 100644 --- a/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java @@ -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)); diff --git a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java index 0239f9bdf2..e319063e9d 100644 --- a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java @@ -176,7 +176,9 @@ public abstract class GroundUnit extends BaseUnit{ target = null; } - retarget(this::targetClosest); + if(retarget()){ + targetClosest(); + } } protected void patrol(){ diff --git a/core/src/io/anuke/mindustry/entities/type/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java index 9389b2d95e..3f1cf60d6d 100644 --- a/core/src/io/anuke/mindustry/entities/type/Player.java +++ b/core/src/io/anuke/mindustry/entities/type/Player.java @@ -241,7 +241,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{ } @Override - public Queue getPlaceQueue(){ + public Queue 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(); diff --git a/core/src/io/anuke/mindustry/entities/type/base/BaseDrone.java b/core/src/io/anuke/mindustry/entities/type/base/BaseDrone.java index f0bba823af..27ac0c86ff 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/BaseDrone.java +++ b/core/src/io/anuke/mindustry/entities/type/base/BaseDrone.java @@ -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); } diff --git a/core/src/io/anuke/mindustry/entities/type/base/BuilderDrone.java b/core/src/io/anuke/mindustry/entities/type/base/BuilderDrone.java index 2477128a88..4b75d6e734 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/BuilderDrone.java +++ b/core/src/io/anuke/mindustry/entities/type/base/BuilderDrone.java @@ -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 getPlaceQueue(){ + public Queue 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(); diff --git a/core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java b/core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java index 605bebb148..9cc5f4f31c 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java +++ b/core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java @@ -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); diff --git a/core/src/io/anuke/mindustry/entities/type/base/RepairDrone.java b/core/src/io/anuke/mindustry/entities/type/base/RepairDrone.java index 9375e6ca8e..e5be4d3d07 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/RepairDrone.java +++ b/core/src/io/anuke/mindustry/entities/type/base/RepairDrone.java @@ -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){ diff --git a/core/src/io/anuke/mindustry/game/Teams.java b/core/src/io/anuke/mindustry/game/Teams.java index 077729ddd0..be4d1a7e2c 100644 --- a/core/src/io/anuke/mindustry/game/Teams.java +++ b/core/src/io/anuke/mindustry/game/Teams.java @@ -42,11 +42,17 @@ public class Teams{ return enemiesOf(team).contains(other); } - public class TeamData{ + /** Allocates a new array with the active teams. + * Never call in the main game loop.*/ + public Array getActive(){ + return Array.select(map, t -> t != null); + } + + public static class TeamData{ public final ObjectSet cores = new ObjectSet<>(); - public final LongQueue brokenBlocks = new LongQueue(); public final EnumSet enemies; public final Team team; + public LongQueue brokenBlocks = new LongQueue(); public TeamData(Team team, EnumSet enemies){ this.team = team; diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index 2198f002ef..ebac7e421e 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -214,7 +214,7 @@ public class DesktopInput extends InputHandler{ mode = placing; }else if(selected != null){ //only begin shooting if there's no cursor event - if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem && + if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.buildQueue().size == 0 && !droppingItem && !tryBeginMine(selected) && player.getMineTile() == null && !ui.chatfrag.chatOpen()){ player.isShooting = true; } @@ -222,7 +222,7 @@ public class DesktopInput extends InputHandler{ player.isShooting = true; } }else if(Core.input.keyTap(Binding.deselect) && (block != null || mode != none || player.isBuilding()) && - !(player.getCurrentRequest() != null && player.getCurrentRequest().breaking && Core.keybinds.get(Binding.deselect) == Core.keybinds.get(Binding.break_block))){ + !(player.buildRequest() != null && player.buildRequest().breaking && Core.keybinds.get(Binding.deselect) == Core.keybinds.get(Binding.break_block))){ if(block == null){ player.clearBuilding(); } diff --git a/core/src/io/anuke/mindustry/io/JsonIO.java b/core/src/io/anuke/mindustry/io/JsonIO.java index 3c1ce9520c..6cee4ca311 100644 --- a/core/src/io/anuke/mindustry/io/JsonIO.java +++ b/core/src/io/anuke/mindustry/io/JsonIO.java @@ -1,10 +1,12 @@ package io.anuke.mindustry.io; +import io.anuke.arc.collection.EnumSet; +import io.anuke.arc.collection.LongQueue; import io.anuke.arc.util.serialization.Json; import io.anuke.arc.util.serialization.JsonValue; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.game.Rules; -import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.game.Teams.TeamData; import io.anuke.mindustry.type.*; @SuppressWarnings("unchecked") @@ -36,6 +38,25 @@ public class JsonIO{ return Vars.content.getByName(ContentType.item, jsonData.asString()); } }); + + setSerializer(TeamData.class, new Serializer(){ + @Override + public void write(Json json, TeamData object, Class knownType){ + json.writeObjectStart(); + json.writeValue("brokenBlocks", object.brokenBlocks.toArray()); + json.writeValue("team", object.team.ordinal()); + json.writeObjectEnd(); + } + + @Override + public TeamData read(Json json, JsonValue jsonData, Class type){ + long[] blocks = jsonData.get("brokenBlocks").asLongArray(); + Team team = Team.all[jsonData.getInt("team", 0)]; + TeamData out = new TeamData(team, EnumSet.of(new Team[]{})); + out.brokenBlocks = new LongQueue(blocks); + return out; + } + }); }}; public static String write(Object object){ diff --git a/core/src/io/anuke/mindustry/io/SaveVersion.java b/core/src/io/anuke/mindustry/io/SaveVersion.java index fee4bf058d..839bed89fe 100644 --- a/core/src/io/anuke/mindustry/io/SaveVersion.java +++ b/core/src/io/anuke/mindustry/io/SaveVersion.java @@ -1,13 +1,14 @@ package io.anuke.mindustry.io; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.StringMap; +import io.anuke.arc.collection.*; import io.anuke.arc.util.Time; import io.anuke.arc.util.io.CounterInputStream; import io.anuke.mindustry.entities.Entities; import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.game.*; +import io.anuke.mindustry.game.Teams.TeamData; +import io.anuke.mindustry.gen.BrokenBlock; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.world.*; @@ -64,6 +65,7 @@ public abstract class SaveVersion extends SaveFileReader{ "wavetime", state.wavetime, "stats", JsonIO.write(state.stats), "rules", JsonIO.write(state.rules), + "teamdata", JsonIO.write(state.teams.getActive().toArray(TeamData.class)), "width", world.width(), "height", world.height() ).merge(tags)); @@ -77,6 +79,13 @@ public abstract class SaveVersion extends SaveFileReader{ state.stats = JsonIO.read(Stats.class, map.get("stats", "{}")); state.rules = JsonIO.read(Rules.class, map.get("rules", "{}")); if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get(); + + //only broken blocks are transferred over right now; nothing else + TeamData[] teams = JsonIO.read(TeamData[].class, map.get("teamdata", "[]")); + for(TeamData data : teams){ + state.teams.get(data.team).brokenBlocks = data.brokenBlocks; + } + Map worldmap = world.maps.byName(map.get("mapname", "\\\\\\")); world.setMap(worldmap == null ? new Map(StringMap.of( "name", map.get("mapname", "Unknown"), @@ -92,13 +101,13 @@ public abstract class SaveVersion extends SaveFileReader{ //floor + overlay for(int i = 0; i < world.width() * world.height(); i++){ - Tile tile = world.tile(i % world.width(), i / world.width()); + Tile tile = world.rawTile(i % world.width(), i / world.width()); stream.writeShort(tile.floorID()); stream.writeShort(tile.overlayID()); int consecutives = 0; for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){ - Tile nextTile = world.tile(j % world.width(), j / world.width()); + Tile nextTile = world.rawTile(j % world.width(), j / world.width()); if(nextTile.floorID() != tile.floorID() || nextTile.overlayID() != tile.overlayID()){ break; @@ -113,7 +122,7 @@ public abstract class SaveVersion extends SaveFileReader{ //blocks for(int i = 0; i < world.width() * world.height(); i++){ - Tile tile = world.tile(i % world.width(), i / world.width()); + Tile tile = world.rawTile(i % world.width(), i / world.width()); stream.writeShort(tile.blockID()); if(tile.entity != null){ @@ -126,7 +135,7 @@ public abstract class SaveVersion extends SaveFileReader{ int consecutives = 0; for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){ - Tile nextTile = world.tile(j % world.width(), j / world.width()); + Tile nextTile = world.rawTile(j % world.width(), j / world.width()); if(nextTile.blockID() != tile.blockID()){ break; @@ -264,6 +273,8 @@ public abstract class SaveVersion extends SaveFileReader{ } content.setTemporaryMapper(map); + + remapContent(); } public void writeContentHeader(DataOutput stream) throws IOException{ @@ -287,4 +298,17 @@ public abstract class SaveVersion extends SaveFileReader{ } } } + + /** sometimes it's necessary to remap IDs after the content header is read.*/ + public void remapContent(){ + for(Team team : Team.all){ + if(state.teams.isActive(team)){ + LongQueue queue = state.teams.get(team).brokenBlocks; + for(int i = 0; i < queue.size; i++){ + //remap broken block IDs + queue.set(i, BrokenBlock.block(queue.get(i), content.block(BrokenBlock.block(queue.get(i))).id)); + } + } + } + } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java index 9d7cb84325..588d1410f2 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java @@ -69,6 +69,7 @@ public class CustomRulesDialog extends FloatingDialog{ title("$rules.title.enemy"); check("$rules.attack", b -> rules.attackMode = b, () -> rules.attackMode); + check("$rules.enemyCheat", b -> rules.enemyCheat = b, () -> rules.enemyCheat); number("$rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200)); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index ac19e1a480..c47f7524ce 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -123,7 +123,6 @@ public class SettingsMenuDialog extends SettingsDialog{ sound.add("[LIGHT_GRAY]there is no sound implemented in v4 yet"); game.screenshakePref(); - game.checkPref("effects", true); if(mobile){ game.checkPref("autotarget", true); } @@ -212,6 +211,7 @@ public class SettingsMenuDialog extends SettingsDialog{ } } + graphics.checkPref("effects", true); graphics.checkPref("playerchat", true); graphics.checkPref("minimap", !mobile); graphics.checkPref("fps", false);