Splitting of building+mining into separate traits

This commit is contained in:
Anuken
2019-06-12 14:03:50 -04:00
parent dc3c27297f
commit 0aee75c1c1
10 changed files with 379 additions and 270 deletions

View File

@@ -113,9 +113,11 @@ android{
} }
} }
buildTypes{ if(project.hasProperty("RELEASE_STORE_FILE")) {
release{ buildTypes {
signingConfig signingConfigs.release release {
signingConfig signingConfigs.release
}
} }
} }
} }

View File

@@ -113,6 +113,8 @@ allprojects{
maven{ url 'https://jitpack.io' } maven{ url 'https://jitpack.io' }
jcenter() jcenter()
} }
tasks.withType(Javadoc).all{ enabled = false }
} }
project(":desktop"){ project(":desktop"){
@@ -175,7 +177,7 @@ project(":core"){
} }
dependencies{ dependencies{
if(System.properties["user.name"] == "anuke"){ if(System.properties["user.name"] == "anuke" && !System.properties["os.name"].contains("Mac")){
task cleanGen{ task cleanGen{
doFirst{ doFirst{
delete{ delete{

View File

@@ -0,0 +1,22 @@
package io.anuke.mindustry.entities.traits;
/** A class for gracefully merging mining and building traits.*/
public interface BuilderMinerTrait extends MinerTrait, BuilderTrait{
default void updateMechanics(){
updateBuilding();
//mine only when not building
if(getCurrentRequest() == null){
updateMining();
}
}
default void drawMechanics(){
if(isBuilding()){
drawBuilding();
}else{
drawMining();
}
}
}

View File

@@ -1,26 +1,18 @@
package io.anuke.mindustry.entities.traits; package io.anuke.mindustry.entities.traits;
import io.anuke.arc.Core; import io.anuke.arc.*;
import io.anuke.arc.Events; import io.anuke.arc.collection.*;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.Queue;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Angles; import io.anuke.arc.math.*;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.util.Time; import io.anuke.arc.util.Time;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.game.EventType.BuildSelectEvent;
import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.graphics.Shapes;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock;
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
@@ -29,21 +21,15 @@ import java.io.*;
import java.util.Arrays; import java.util.Arrays;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.entities.traits.BuilderTrait.BuildDataStatic.removal; import static io.anuke.mindustry.entities.traits.BuilderTrait.BuildDataStatic.*;
import static io.anuke.mindustry.entities.traits.BuilderTrait.BuildDataStatic.tmptr;
/** /** Interface for units that build things.*/
* Interface for units that build, break or mine things.
*/
public interface BuilderTrait extends Entity, TeamTrait{ public interface BuilderTrait extends Entity, TeamTrait{
//these are not instance variables! //these are not instance variables!
float placeDistance = 220f; float placeDistance = 220f;
float mineDistance = 70f; float mineDistance = 70f;
/** /** Updates building mechanism for this unit.*/
* Update building mechanism for this unit.
* This includes mining.
*/
default void updateBuilding(){ default void updateBuilding(){
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : placeDistance; float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : placeDistance;
Unit unit = (Unit)this; Unit unit = (Unit)this;
@@ -65,14 +51,8 @@ public interface BuilderTrait extends Entity, TeamTrait{
BuildRequest current = getCurrentRequest(); BuildRequest current = getCurrentRequest();
//update mining here
if(current == null){ if(current == null){
if(getMineTile() != null){
updateMining();
}
return; return;
}else{
setMineTile(null);
} }
Tile tile = world.tile(current.x, current.y); Tile tile = world.tile(current.x, current.y);
@@ -137,21 +117,9 @@ public interface BuilderTrait extends Entity, TeamTrait{
/** Returns the queue for storing build requests. */ /** Returns the queue for storing build requests. */
Queue<BuildRequest> getPlaceQueue(); Queue<BuildRequest> getPlaceQueue();
/** Returns the tile this builder is currently mining. */
Tile getMineTile();
/** Sets the tile this builder is currently mining. */
void setMineTile(Tile tile);
/** Returns the minining speed of this miner. 1 = standard, 0.5 = half speed, 2 = double speed, etc. */
float getMinePower();
/** Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all. */ /** Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all. */
float getBuildPower(Tile tile); float getBuildPower(Tile tile);
/** Returns whether or not this builder can mine a specific item type. */
boolean canMine(Item item);
/** Whether this type of builder can begin creating new blocks. */ /** Whether this type of builder can begin creating new blocks. */
default boolean canCreateBlocks(){ default boolean canCreateBlocks(){
return true; return true;
@@ -236,60 +204,18 @@ public interface BuilderTrait extends Entity, TeamTrait{
return getPlaceQueue().size == 0 ? null : getPlaceQueue().first(); return getPlaceQueue().size == 0 ? null : getPlaceQueue().first();
} }
//due to iOS wierdness, this is apparently required //due to iOS weirdness, this is apparently required
class BuildDataStatic{ class BuildDataStatic{
static Array<BuildRequest> removal = new Array<>(); static Array<BuildRequest> removal = new Array<>();
static Vector2[] tmptr = new Vector2[]{new Vector2(), new Vector2(), new Vector2(), new Vector2()}; static Vector2[] tmptr = new Vector2[]{new Vector2(), new Vector2(), new Vector2(), new Vector2()};
} }
/** Do not call directly. */ /** Draw placement effects for an entity. */
default void updateMining(){
Unit unit = (Unit)this;
Tile tile = getMineTile();
TileEntity core = unit.getClosestCore();
if(core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > mineDistance
|| tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){
setMineTile(null);
}else{
Item item = tile.drop();
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(tile.worldx(), tile.worldy()), 0.4f);
if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){
if(unit.dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1){
Call.transferItemTo(item, 1,
tile.worldx() + Mathf.range(tilesize / 2f),
tile.worldy() + Mathf.range(tilesize / 2f), core.tile);
}else if(unit.acceptsItem(item)){
Call.transferItemToUnit(item,
tile.worldx() + Mathf.range(tilesize / 2f),
tile.worldy() + Mathf.range(tilesize / 2f),
unit);
}
}
if(Mathf.chance(0.06 * Time.delta())){
Effects.effect(Fx.pulverizeSmall,
tile.worldx() + Mathf.range(tilesize / 2f),
tile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color);
}
}
}
/** Draw placement effects for an entity. This includes mining */
default void drawBuilding(){ default void drawBuilding(){
if(!isBuilding()) return;
Unit unit = (Unit)this; Unit unit = (Unit)this;
BuildRequest request; BuildRequest request = getCurrentRequest();
if(!isBuilding()){
if(getMineTile() != null){
drawMining();
}
return;
}
request = getCurrentRequest();
Tile tile = world.tile(request.x, request.y); Tile tile = world.tile(request.x, request.y);
if(dst(tile) > placeDistance && !state.isEditor()){ if(dst(tile) > placeDistance && !state.isEditor()){
@@ -310,10 +236,10 @@ public interface BuilderTrait extends Entity, TeamTrait{
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz); tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(unit.x, unit.y, a.x, a.y), ang), Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(unit.x, unit.y, a.x, a.y), ang),
Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang))); Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang)));
float x1 = tmptr[0].x, y1 = tmptr[0].y, float x1 = tmptr[0].x, y1 = tmptr[0].y,
x3 = tmptr[1].x, y3 = tmptr[1].y; x3 = tmptr[1].x, y3 = tmptr[1].y;
Draw.alpha(1f); Draw.alpha(1f);
@@ -325,35 +251,6 @@ public interface BuilderTrait extends Entity, TeamTrait{
Draw.color(); Draw.color();
} }
/** Internal use only. */
default void drawMining(){
Unit unit = (Unit)this;
Tile tile = getMineTile();
if(tile == null) return;
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
float swingScl = 12f, swingMag = tilesize / 8f;
float flashScl = 0.3f;
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
float ex = tile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag);
float ey = tile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag);
Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl));
Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey, 0.75f);
if(unit instanceof Player && ((Player)unit).isLocal){
Lines.stroke(1f, Pal.accent);
Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time());
}
Draw.color();
}
/** Class for storing build requests. Can be either a place or remove request. */ /** Class for storing build requests. Can be either a place or remove request. */
class BuildRequest{ class BuildRequest{
public final int x, y, rotation; public final int x, y, rotation;

View File

@@ -0,0 +1,101 @@
package io.anuke.mindustry.entities.traits;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Tile;
import static io.anuke.mindustry.Vars.*;
public interface MinerTrait extends Entity{
/** Returns the range at which this miner can mine blocks.*/
default float getMiningRange(){
return 70f;
}
default boolean isMining(){
return getMineTile() != null;
}
/** Returns the tile this builder is currently mining. */
Tile getMineTile();
/** Sets the tile this builder is currently mining. */
void setMineTile(Tile tile);
/** Returns the mining speed of this miner. 1 = standard, 0.5 = half speed, 2 = double speed, etc. */
float getMinePower();
/** Returns whether or not this builder can mine a specific item type. */
boolean canMine(Item item);
default void updateMining(){
Unit unit = (Unit)this;
Tile tile = getMineTile();
TileEntity core = unit.getClosestCore();
if(tile == null || core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > getMiningRange()
|| tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){
setMineTile(null);
}else{
Item item = tile.drop();
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(tile.worldx(), tile.worldy()), 0.4f);
if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){
if(unit.dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1){
Call.transferItemTo(item, 1,
tile.worldx() + Mathf.range(tilesize / 2f),
tile.worldy() + Mathf.range(tilesize / 2f), core.tile);
}else if(unit.acceptsItem(item)){
Call.transferItemToUnit(item,
tile.worldx() + Mathf.range(tilesize / 2f),
tile.worldy() + Mathf.range(tilesize / 2f),
unit);
}
}
if(Mathf.chance(0.06 * Time.delta())){
Effects.effect(Fx.pulverizeSmall,
tile.worldx() + Mathf.range(tilesize / 2f),
tile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color);
}
}
}
default void drawMining(){
Unit unit = (Unit)this;
Tile tile = getMineTile();
if(tile == null) return;
float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f);
float swingScl = 12f, swingMag = tilesize / 8f;
float flashScl = 0.3f;
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
float ex = tile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag);
float ey = tile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag);
Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl));
Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey, 0.75f);
if(unit instanceof Player && ((Player)unit).isLocal){
Lines.stroke(1f, Pal.accent);
Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time());
}
Draw.color();
}
}

View File

@@ -33,7 +33,7 @@ import java.io.*;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class Player extends Unit implements BuilderTrait, ShooterTrait{ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
public static final int timerSync = 2; public static final int timerSync = 2;
public static final int timerAbility = 3; public static final int timerAbility = 3;
private static final int timerShootLeft = 0; private static final int timerShootLeft = 0;
@@ -362,7 +362,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
public void drawOver(){ public void drawOver(){
if(dead) return; if(dead) return;
drawBuilding(); drawMechanics();
} }
@Override @Override
@@ -551,7 +551,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
if(!isLocal){ if(!isLocal){
interpolate(); interpolate();
updateBuilding(); //building happens even with non-locals updateMechanics(); //building happens even with non-locals
status.update(this); //status effect updating also happens with non locals for effect purposes status.update(this); //status effect updating also happens with non locals for effect purposes
updateVelocityStatus(); //velocity too, for visual purposes updateVelocityStatus(); //velocity too, for visual purposes
@@ -572,7 +572,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
isTyping = ui.chatfrag.chatOpen(); isTyping = ui.chatfrag.chatOpen();
updateBuilding(); updateMechanics();
if(!mech.flying){ if(!mech.flying){
clampPosition(); clampPosition();

View File

@@ -0,0 +1,217 @@
package io.anuke.mindustry.entities.type.base;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Geometry;
import io.anuke.arc.util.Structs;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.entities.traits.MinerTrait;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.units.UnitState;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.meta.BlockFlag;
import java.io.*;
import static io.anuke.mindustry.Vars.world;
/** A drone that only mines.*/
public class MinerDrone extends FlyingUnit implements MinerTrait{
protected Item targetItem;
protected Tile mineTile;
public final UnitState
mine = new UnitState(){
public void entered(){
target = null;
}
public void update(){
TileEntity entity = getClosestCore();
if(entity == null) return;
if(targetItem == null){
findItem();
}
//core full
if(targetItem != null && entity.block.acceptStack(targetItem, 1, entity.tile, MinerDrone.this) == 0){
MinerDrone.this.clearItem();
return;
}
//if inventory is full, drop it off.
if(item.amount >= getItemCapacity()){
setState(drop);
}else{
if(targetItem != null && !acceptsItem(targetItem)){
setState(drop);
return;
}
retarget(() -> {
if(getMineTile() == null){
findItem();
}
if(targetItem == null) return;
target = world.indexer.findClosestOre(x, y, targetItem);
});
if(target instanceof Tile){
moveTo(type.range / 1.5f);
if(dst(target) < type.range && mineTile != target){
setMineTile((Tile)target);
}
if(((Tile)target).block() != Blocks.air){
setState(drop);
}
}else{
//nothing to mine anymore, core full: circle spawnpoint
if(getSpawner() != null){
target = getSpawner();
circle(40f);
}
}
}
}
public void exited(){
setMineTile(null);
}
},
drop = new UnitState(){
public void entered(){
target = null;
}
public void update(){
if(item.amount == 0){
setState(mine);
return;
}
if(item.item.type != ItemType.material){
item.amount = 0;
setState(mine);
return;
}
target = getClosestCore();
if(target == null) return;
TileEntity tile = (TileEntity)target;
if(dst(target) < type.range){
if(tile.tile.block().acceptStack(item.item, item.amount, tile.tile, MinerDrone.this) == item.amount){
Call.transferItemTo(item.item, item.amount, x, y, tile.tile);
item.amount = 0;
}
setState(mine);
}
circle(type.range / 1.8f);
}
},
retreat = new UnitState(){
public void entered(){
target = null;
}
public void update(){
if(health >= maxHealth()){
state.set(attack);
}else if(!targetHasFlag(BlockFlag.repair)){
retarget(() -> {
Tile repairPoint = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair));
if(repairPoint != null){
target = repairPoint;
}else{
setState(mine);
}
});
}else{
circle(40f);
}
}
};
@Override
public void update(){
super.update();
updateMining();
}
@Override
protected void updateRotation(){
if(target != null && state.is(mine)){
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f);
}else{
rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f);
}
}
@Override
public void behavior(){
if(health <= health * type.retreatPercent){
setState(retreat);
}
}
@Override
public void drawOver(){
drawMining();
}
@Override
public boolean canMine(Item item){
return type.toMine.contains(item);
}
@Override
public float getMinePower(){
return type.minePower;
}
@Override
public Tile getMineTile(){
return mineTile;
}
@Override
public void setMineTile(Tile tile){
mineTile = tile;
}
@Override
public void write(DataOutput data) throws IOException{
super.write(data);
data.writeInt(mineTile == null || !state.is(mine) ? Pos.invalid : mineTile.pos());
}
@Override
public void read(DataInput data) throws IOException{
super.read(data);
mineTile = world.tile(data.readInt());
}
protected void findItem(){
TileEntity entity = getClosestCore();
if(entity == null){
return;
}
targetItem = Structs.findMin(type.toMine, world.indexer::hasOre, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b)));
}
}

View File

@@ -1,5 +1,5 @@
package io.anuke.mindustry.entities.type.base; package io.anuke.mindustry.entities.type.base;
public class Phantom extends Drone{ public class Phantom extends UtilityDrone{
} }

View File

@@ -1,4 +1,4 @@
package io.anuke.mindustry.entities.type.base; package io.anuke.mindustry.entities.type.base;
public class Spirit extends Drone{ public class Spirit extends UtilityDrone{
} }

View File

@@ -4,17 +4,11 @@ import io.anuke.arc.Events;
import io.anuke.arc.collection.Queue; import io.anuke.arc.collection.Queue;
import io.anuke.arc.math.Mathf; import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Geometry;
import io.anuke.arc.util.Structs; import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.entities.EntityGroup;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.traits.BuilderTrait; import io.anuke.mindustry.entities.traits.BuilderTrait;
import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.units.UnitState; import io.anuke.mindustry.entities.units.UnitState;
import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.game.EventType.BuildSelectEvent;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemType;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock;
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
@@ -24,9 +18,8 @@ import java.io.*;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class Drone extends FlyingUnit implements BuilderTrait{ /** A drone that only builds and/or repairs.*/
protected Item targetItem; public class UtilityDrone extends FlyingUnit implements BuilderTrait{
protected Tile mineTile;
protected Queue<BuildRequest> placeQueue = new Queue<>(); protected Queue<BuildRequest> placeQueue = new Queue<>();
protected boolean isBreaking; protected boolean isBreaking;
@@ -34,6 +27,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
build = new UnitState(){ build = new UnitState(){
//TODO follow players
public void entered(){ public void entered(){
if(!(target instanceof BuildEntity)){ if(!(target instanceof BuildEntity)){
target = null; target = null;
@@ -78,12 +72,13 @@ public class Drone extends FlyingUnit implements BuilderTrait{
retarget(() -> target = Units.findDamagedTile(team, x, y)); retarget(() -> target = Units.findDamagedTile(team, x, y));
if(target != null){ if(target != null){
if(target.dst(Drone.this) > type.range){ if(target.dst(UtilityDrone.this) > type.range){
circle(type.range * 0.9f); circle(type.range * 0.9f);
}else{ }else{
getWeapon().update(Drone.this, target.getX(), target.getY()); getWeapon().update(UtilityDrone.this, target.getX(), target.getY());
} }
}else{ }else{
//circle spawner if there's nothing to repair
if(getSpawner() != null){ if(getSpawner() != null){
target = getSpawner(); target = getSpawner();
circle(type.range * 0.9f); circle(type.range * 0.9f);
@@ -91,99 +86,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{
} }
} }
}, },
mine = new UnitState(){
public void entered(){
target = null;
}
public void update(){
TileEntity entity = getClosestCore();
if(entity == null) return;
if(targetItem == null){
findItem();
}
//core full
if(targetItem != null && entity.block.acceptStack(targetItem, 1, entity.tile, Drone.this) == 0){
setState(repair);
return;
}
//if inventory is full, drop it off.
if(item.amount >= getItemCapacity()){
setState(drop);
}else{
if(targetItem != null && !acceptsItem(targetItem)){
setState(drop);
return;
}
retarget(() -> {
if(getMineTile() == null){
findItem();
}
if(targetItem == null) return;
target = world.indexer.findClosestOre(x, y, targetItem);
});
if(target instanceof Tile){
moveTo(type.range / 1.5f);
if(dst(target) < type.range && mineTile != target){
setMineTile((Tile)target);
}
if(((Tile)target).block() != Blocks.air){
setState(drop);
}
}
}
}
public void exited(){
setMineTile(null);
}
},
drop = new UnitState(){
public void entered(){
target = null;
}
public void update(){
if(item.amount == 0){
setState(mine);
return;
}
if(item.item.type != ItemType.material){
item.amount = 0;
setState(mine);
return;
}
target = getClosestCore();
if(target == null) return;
TileEntity tile = (TileEntity)target;
if(dst(target) < type.range){
if(tile.tile.block().acceptStack(item.item, item.amount, tile.tile, Drone.this) == item.amount){
Call.transferItemTo(item.item, item.amount, x, y, tile.tile);
item.amount = 0;
}
setState(repair);
}
circle(type.range / 1.8f);
}
},
retreat = new UnitState(){ retreat = new UnitState(){
public void entered(){ public void entered(){
target = null; target = null;
@@ -197,8 +99,8 @@ public class Drone extends FlyingUnit implements BuilderTrait{
Tile repairPoint = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)); Tile repairPoint = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair));
if(repairPoint != null){ if(repairPoint != null){
target = repairPoint; target = repairPoint;
}else if(getSpawner() != null){ }else{
target = getSpawner(); setState(repair);
} }
}); });
}else{ }else{
@@ -215,8 +117,8 @@ public class Drone extends FlyingUnit implements BuilderTrait{
if(!(event.tile.entity instanceof BuildEntity)) return; if(!(event.tile.entity instanceof BuildEntity)) return;
for(BaseUnit unit : group.all()){ for(BaseUnit unit : group.all()){
if(unit instanceof Drone){ if(unit instanceof UtilityDrone){
Drone drone = (Drone)unit; UtilityDrone drone = (UtilityDrone)unit;
if(drone.isBuilding()){ if(drone.isBuilding()){
//stop building if opposite building begins. //stop building if opposite building begins.
BuildRequest req = drone.getCurrentRequest(); BuildRequest req = drone.getCurrentRequest();
@@ -230,36 +132,16 @@ public class Drone extends FlyingUnit implements BuilderTrait{
}); });
} }
@Override
public boolean canMine(Item item){
return type.toMine.contains(item);
}
@Override @Override
public float getBuildPower(Tile tile){ public float getBuildPower(Tile tile){
return type.buildPower; return type.buildPower;
} }
@Override
public float getMinePower(){
return type.minePower;
}
@Override @Override
public Queue<BuildRequest> getPlaceQueue(){ public Queue<BuildRequest> getPlaceQueue(){
return placeQueue; return placeQueue;
} }
@Override
public Tile getMineTile(){
return mineTile;
}
@Override
public void setMineTile(Tile tile){
mineTile = tile;
}
@Override @Override
public void update(){ public void update(){
super.update(); super.update();
@@ -292,7 +174,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
@Override @Override
protected void updateRotation(){ protected void updateRotation(){
if(target != null && ((state.is(repair) && target.dst(this) < type.range) || state.is(mine))){ if(target != null && state.is(repair) && target.dst(this) < type.range){
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f); rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f);
}else{ }else{
rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f); rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f);
@@ -321,14 +203,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{
return isBuilding() ? placeDistance * 2f : 30f; return isBuilding() ? placeDistance * 2f : 30f;
} }
protected void findItem(){
TileEntity entity = getClosestCore();
if(entity == null){
return;
}
targetItem = Structs.findMin(type.toMine, world.indexer::hasOre, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b)));
}
@Override @Override
public boolean canCreateBlocks(){ public boolean canCreateBlocks(){
return true; return true;
@@ -337,7 +211,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{
@Override @Override
public void write(DataOutput data) throws IOException{ public void write(DataOutput data) throws IOException{
super.write(data); super.write(data);
data.writeInt(mineTile == null || !state.is(mine) ? -1 : mineTile.pos());
data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.pos() : -1); data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.pos() : -1);
writeBuilding(data); writeBuilding(data);
} }
@@ -345,15 +218,10 @@ public class Drone extends FlyingUnit implements BuilderTrait{
@Override @Override
public void read(DataInput data) throws IOException{ public void read(DataInput data) throws IOException{
super.read(data); super.read(data);
int mined = data.readInt();
int repairing = data.readInt(); int repairing = data.readInt();
readBuilding(data); readBuilding(data);
if(mined != -1){
mineTile = world.tile(mined);
}
if(repairing != -1){ if(repairing != -1){
Tile tile = world.tile(repairing); Tile tile = world.tile(repairing);
target = tile.entity; target = tile.entity;