diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index 6a66286118c..f3cba3a1735 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -34,6 +34,8 @@ public class BlockIndexer{ private Bits[] structQuadrants; /** Stores all damaged tile entities by team. */ private ObjectSet[] damagedTiles = new ObjectSet[Team.all.length]; + /**All ores available on this map.*/ + private ObjectSet allOres = new ObjectSet<>(); /** Maps teams to a map of flagged tiles by type. */ private ObjectSet[][] flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length]; @@ -67,6 +69,7 @@ public BlockIndexer(){ } typeMap.clear(); + allOres.clear(); ores = null; //create bitset for each team type that contains each quadrant @@ -84,6 +87,8 @@ public BlockIndexer(){ if(tile.entity != null && tile.entity.damaged()){ notifyTileDamaged(tile.entity); } + + if(tile.drop() != null) allOres.add(tile.drop()); } } @@ -101,6 +106,11 @@ private ObjectSet[] getFlagged(Team team){ return flagMap[team.ordinal()]; } + /** @return whether this item is present on this map.*/ + public boolean hasOre(Item item){ + return allOres.contains(item); + } + /** Returns all damaged tiles by team. */ public ObjectSet getDamaged(Team team){ returnArray.clear(); diff --git a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java index a64128d392c..54553c20365 100644 --- a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java @@ -35,6 +35,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ protected static int timerIndex = 0; protected static final int timerTarget = timerIndex++; + protected static final int timerTarget2 = timerIndex++; protected static final int timerShootLeft = timerIndex++; protected static final int timerShootRight = timerIndex++; diff --git a/core/src/io/anuke/mindustry/entities/type/base/Drone.java b/core/src/io/anuke/mindustry/entities/type/base/Drone.java index 5b09640e573..5d6fe4c1e1a 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/Drone.java +++ b/core/src/io/anuke/mindustry/entities/type/base/Drone.java @@ -13,7 +13,8 @@ import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.type.*; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; @@ -21,10 +22,11 @@ import java.io.*; -import static io.anuke.mindustry.Vars.unitGroups; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class Drone extends FlyingUnit implements BuilderTrait{ + + protected Item targetItem; protected Tile mineTile; protected Queue placeQueue = new Queue<>(); @@ -51,24 +53,12 @@ public void update(){ if(core == null) return; - if((entity.progress() < 1f || entity.progress() > 0f) && entity.block instanceof BuildBlock){ //building is valid + if((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)); }else{ - getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.block)); - } - } - - //if it's missing requirements, try and mine them - if(entity.block != null){ - for(ItemStack stack : entity.block.buildRequirements){ - if(!core.items.has(stack.item, stack.amount) && type.toMine.contains(stack.item)){ - targetItem = stack.item; - getPlaceQueue().clear(); - setState(mine); - return; - } + getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.cblock)); } } @@ -222,7 +212,6 @@ public void update(){ EntityGroup group = unitGroups[event.team.ordinal()]; if(!(event.builder instanceof Player) || !(event.tile.entity instanceof BuildEntity)) return; - BuildEntity entity = event.tile.entity(); for(BaseUnit unit : group.all()){ if(unit instanceof Drone){ @@ -235,23 +224,11 @@ public void update(){ drone.setState(drone.repair); } } - - drone.notifyPlaced(entity, event.breaking); } } }); } - private void notifyPlaced(BuildEntity entity, boolean isBreaking){ - float dist = Math.min(entity.dst(x, y) - placeDistance, 0); - - if(!state.is(build) && dist / type.maxVelocity < entity.buildCost * 0.9f){ - target = entity; - this.isBreaking = isBreaking; - setState(build); - } - } - @Override public boolean canMine(Item item){ return type.toMine.contains(item); @@ -290,6 +267,25 @@ public void update(){ target = null; } + if(!state.is(build) && timer.get(timerTarget2, 15)){ + for(Player player : playerGroup.all()){ + if(player.getTeam() == team && player.getCurrentRequest() != null){ + BuildRequest req = player.getCurrentRequest(); + Tile tile = world.tile(req.x, req.y); + if(tile != null && tile.entity instanceof BuildEntity){ + BuildEntity b = tile.entity(); + float dist = Math.min(b.dst(x, y) - placeDistance, 0); + if(dist / type.maxVelocity < b.buildCost * 0.9f){ + target = b; + this.isBreaking = req.breaking; + setState(build); + break; + } + } + } + } + } + updateBuilding(); } @@ -330,7 +326,7 @@ protected void findItem(){ if(entity == null){ return; } - targetItem = Structs.findMin(type.toMine, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b))); + targetItem = Structs.findMin(type.toMine, world.indexer::hasOre, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b))); } @Override diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 2b902dc36b0..eb8d4790260 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -383,6 +383,9 @@ public void updateOcclusion(){ for(int i = 0; i < 8; i++){ Point2 point = Geometry.d8[i]; Tile tile = world.tile(x + point.x, y + point.y); + if(tile != null && tile.floor.isLiquid){ + cost += 3; + } if(tile != null && tile.solid()){ occluded = true; break; diff --git a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java index 076bb4d3013..41e6041449d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java @@ -76,19 +76,19 @@ public boolean isHidden(){ @Override public String getDisplayName(Tile tile){ BuildEntity entity = tile.entity(); - return Core.bundle.format("block.constructing", entity.block == null ? entity.previous.localizedName : entity.block.localizedName); + return Core.bundle.format("block.constructing", entity.cblock == null ? entity.previous.localizedName : entity.cblock.localizedName); } @Override public TextureRegion getDisplayIcon(Tile tile){ BuildEntity entity = tile.entity(); - return (entity.block == null ? entity.previous : entity.block).icon(Icon.full); + return (entity.cblock == null ? entity.previous : entity.cblock).icon(Icon.full); } @Override public boolean isSolidFor(Tile tile){ BuildEntity entity = tile.entity(); - return entity == null || (entity.block != null && entity.block.solid) || entity.previous == null || entity.previous.solid; + return entity == null || (entity.cblock != null && entity.cblock.solid) || entity.previous == null || entity.previous.solid; } @Override @@ -101,9 +101,9 @@ public void tapped(Tile tile, Player player){ BuildEntity entity = tile.entity(); //if the target is constructible, begin constructing - if(entity.block != null){ + if(entity.cblock != null){ player.clearBuilding(); - player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.getRotation(), entity.block)); + player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.getRotation(), entity.cblock)); } } @@ -121,7 +121,7 @@ public void draw(Tile tile){ BuildEntity entity = tile.entity(); //When breaking, don't draw the previous block... since it's the thing you were breaking - if(entity.block != null && entity.previous == entity.block){ + if(entity.cblock != null && entity.previous == entity.cblock){ return; } @@ -139,7 +139,7 @@ public void drawLayer(Tile tile){ Shaders.blockbuild.color = Pal.accent; - Block target = entity.block == null ? entity.previous : entity.block; + Block target = entity.cblock == null ? entity.previous : entity.cblock; if(target == null) return; @@ -162,7 +162,7 @@ public class BuildEntity extends TileEntity{ * The recipe of the block that is being constructed. * If there is no recipe for this block, as is the case with rocks, 'previous' is used. */ - public Block block; + public Block cblock; public float progress = 0; public float buildCost; @@ -177,15 +177,15 @@ public class BuildEntity extends TileEntity{ private float[] totalAccumulator; public void construct(Unit builder, TileEntity core, float amount){ - if(block == null){ + if(cblock == null){ kill(); return; } float maxProgress = checkRequired(core.items, amount, false); - for(int i = 0; i < block.buildRequirements.length; i++){ - int reqamount = Math.round(state.rules.buildCostMultiplier * block.buildRequirements[i].amount); + for(int i = 0; i < cblock.buildRequirements.length; i++){ + int reqamount = Math.round(state.rules.buildCostMultiplier * cblock.buildRequirements[i].amount); accumulator[i] += Math.min(reqamount * maxProgress, reqamount - totalAccumulator[i] + 0.00001f); //add min amount progressed to the accumulator totalAccumulator[i] = Math.min(totalAccumulator[i] + reqamount * maxProgress, reqamount); } @@ -199,15 +199,15 @@ public void construct(Unit builder, TileEntity core, float amount){ } if(progress >= 1f || state.rules.infiniteResources){ - Call.onConstructFinish(tile, block, builderID, tile.getRotation(), builder.getTeam()); + Call.onConstructFinish(tile, cblock, builderID, tile.getRotation(), builder.getTeam()); } } public void deconstruct(Unit builder, TileEntity core, float amount){ float deconstructMultiplier = 0.5f; - if(block != null){ - ItemStack[] requirements = block.buildRequirements; + if(cblock != null){ + ItemStack[] requirements = cblock.buildRequirements; if(requirements.length != accumulator.length || totalAccumulator.length != requirements.length){ setDeconstruct(previous); } @@ -231,22 +231,22 @@ public void deconstruct(Unit builder, TileEntity core, float amount){ progress = Mathf.clamp(progress - amount); if(progress <= 0 || state.rules.infiniteResources){ - Call.onDeconstructFinish(tile, this.block == null ? previous : this.block); + Call.onDeconstructFinish(tile, this.cblock == null ? previous : this.cblock); } } private float checkRequired(ItemModule inventory, float amount, boolean remove){ float maxProgress = amount; - for(int i = 0; i < block.buildRequirements.length; i++){ - int sclamount = Math.round(state.rules.buildCostMultiplier * block.buildRequirements[i].amount); + for(int i = 0; i < cblock.buildRequirements.length; i++){ + int sclamount = Math.round(state.rules.buildCostMultiplier * cblock.buildRequirements[i].amount); int required = (int)(accumulator[i]); //calculate items that are required now - if(inventory.get(block.buildRequirements[i].item) == 0 && sclamount != 0){ + if(inventory.get(cblock.buildRequirements[i].item) == 0 && sclamount != 0){ maxProgress = 0f; }else if(required > 0){ //if this amount is positive... //calculate how many items it can actually use - int maxUse = Math.min(required, inventory.get(block.buildRequirements[i].item)); + int maxUse = Math.min(required, inventory.get(cblock.buildRequirements[i].item)); //get this as a fraction float fraction = maxUse / (float)required; @@ -257,7 +257,7 @@ private float checkRequired(ItemModule inventory, float amount, boolean remove){ //remove stuff that is actually used if(remove){ - inventory.remove(block.buildRequirements[i].item, maxUse); + inventory.remove(cblock.buildRequirements[i].item, maxUse); } } //else, no items are required yet, so just keep going @@ -271,7 +271,7 @@ public float progress(){ } public void setConstruct(Block previous, Block block){ - this.block = block; + this.cblock = block; this.previous = previous; this.accumulator = new float[block.buildRequirements.length]; this.totalAccumulator = new float[block.buildRequirements.length]; @@ -282,7 +282,7 @@ public void setDeconstruct(Block previous){ this.previous = previous; this.progress = 1f; if(previous.buildCost >= 0.01f){ - this.block = previous; + this.cblock = previous; this.accumulator = new float[previous.buildRequirements.length]; this.totalAccumulator = new float[previous.buildRequirements.length]; this.buildCost = previous.buildCost * state.rules.buildCostMultiplier; @@ -295,7 +295,7 @@ public void setDeconstruct(Block previous){ public void write(DataOutput stream) throws IOException{ stream.writeFloat(progress); stream.writeShort(previous == null ? -1 : previous.id); - stream.writeShort(block == null ? -1 : block.id); + stream.writeShort(cblock == null ? -1 : cblock.id); if(accumulator == null){ stream.writeByte(-1); @@ -325,10 +325,10 @@ public void read(DataInput stream) throws IOException{ } if(pid != -1) previous = content.block(pid); - if(rid != -1) block = content.block(rid); + if(rid != -1) cblock = content.block(rid); - if(block != null){ - buildCost = block.buildCost * state.rules.buildCostMultiplier; + if(cblock != null){ + buildCost = cblock.buildCost * state.rules.buildCostMultiplier; }else{ buildCost = 20f; }