Merge branch '4.0' of https://github.com/Anuken/Mindustry into 4.0
This commit is contained in:
@@ -30,10 +30,7 @@ import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.entities.trait.SolidTrait;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.ThreadQueue;
|
||||
import io.anuke.ucore.util.Timer;
|
||||
import io.anuke.ucore.util.*;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -58,6 +55,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
public float boostHeat;
|
||||
public Color color = new Color();
|
||||
public Mech mech;
|
||||
public int spawner;
|
||||
|
||||
public NetConnection con;
|
||||
public int playerIndex = 0;
|
||||
@@ -66,7 +64,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
public TargetTrait target;
|
||||
public TargetTrait moveTarget;
|
||||
|
||||
private boolean respawning;
|
||||
private float walktime;
|
||||
private Queue<BuildRequest> placeQueue = new ThreadQueue<>();
|
||||
private Tile mining;
|
||||
@@ -178,6 +175,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
return mech.weapon.getAmmoType(item) != null && inventory.canAcceptAmmo(mech.weapon.getAmmoType(item));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void added() {
|
||||
baseRotation = 90f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAmmo(Item item) {
|
||||
inventory.addAmmo(mech.weapon.getAmmoType(item));
|
||||
@@ -202,7 +204,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
public void damage(float amount){
|
||||
CallEntity.onPlayerDamage(this, calculateDamage(amount));
|
||||
|
||||
if(health <= 0 && !dead && isLocal){
|
||||
if(health <= 0 && !dead){
|
||||
CallEntity.onPlayerDeath(this);
|
||||
}
|
||||
}
|
||||
@@ -225,7 +227,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
if(player == null) return;
|
||||
|
||||
player.dead = true;
|
||||
player.respawning = false;
|
||||
player.placeQueue.clear();
|
||||
|
||||
player.dropCarry();
|
||||
@@ -438,12 +439,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
if(isDead()){
|
||||
isBoosting = false;
|
||||
boostHeat = 0f;
|
||||
CoreEntity entity = (CoreEntity)getClosestCore();
|
||||
|
||||
if (!respawning && entity != null) {
|
||||
entity.trySetPlayer(this);
|
||||
}
|
||||
updateRespawning();
|
||||
return;
|
||||
}else{
|
||||
spawner = -1;
|
||||
}
|
||||
|
||||
if(!isLocal){
|
||||
@@ -451,6 +450,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
updateBuilding(this); //building happens even with non-locals
|
||||
status.update(this); //status effect updating also happens with non locals for effect purposes
|
||||
|
||||
if(getCarrier() != null){
|
||||
x = getCarrier().getX();
|
||||
y = getCarrier().getY();
|
||||
}
|
||||
|
||||
if(Net.server()){
|
||||
updateShooting(); //server simulates player shooting
|
||||
}
|
||||
@@ -532,11 +536,16 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
|
||||
movement.limit(speed);
|
||||
|
||||
velocity.add(movement);
|
||||
|
||||
float prex = x, prey = y;
|
||||
updateVelocityStatus(mech.drag, 10f);
|
||||
moved = distanceTo(prex, prey) > 0.01f;
|
||||
if(getCarrier() == null){
|
||||
velocity.add(movement);
|
||||
float prex = x, prey = y;
|
||||
updateVelocityStatus(mech.drag, 10f);
|
||||
moved = distanceTo(prex, prey) > 0.01f;
|
||||
}else{
|
||||
velocity.setZero();
|
||||
x = Mathf.lerpDelta(x, getCarrier().getX(), 0.1f);
|
||||
y = Mathf.lerpDelta(y, getCarrier().getY(), 0.1f);
|
||||
}
|
||||
|
||||
if(!isShooting()){
|
||||
if(!movement.isZero()) {
|
||||
@@ -610,7 +619,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
if (target == null) {
|
||||
isShooting = false;
|
||||
target = Units.getClosestTarget(team, x, y, inventory.getAmmoRange());
|
||||
} else {
|
||||
} else if(target.isValid()){
|
||||
//rotate toward and shoot the target
|
||||
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
|
||||
|
||||
@@ -649,7 +658,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
inventory.clear();
|
||||
placeQueue.clear();
|
||||
dead = true;
|
||||
respawning = false;
|
||||
trail.clear();
|
||||
health = maxHealth();
|
||||
|
||||
@@ -660,12 +668,21 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
return isShooting && inventory.hasAmmo() && (!isBoosting || mech.flying);
|
||||
}
|
||||
|
||||
public void setRespawning(){
|
||||
respawning = true;
|
||||
public void updateRespawning(){
|
||||
|
||||
if (spawner != -1 && world.tile(spawner) != null && world.tile(spawner).entity instanceof SpawnerTrait) {
|
||||
((SpawnerTrait) world.tile(spawner).entity).updateSpawning(this);
|
||||
}else{
|
||||
CoreEntity entity = (CoreEntity)getClosestCore();
|
||||
if(entity != null){
|
||||
this.spawner = entity.tile.id();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setRespawning(boolean respawning){
|
||||
this.respawning = respawning;
|
||||
public void beginRespawning(SpawnerTrait spawner){
|
||||
this.spawner = spawner.getTile().packedPosition();
|
||||
this.dead = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -697,12 +714,18 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
public void readSave(DataInput stream) throws IOException {
|
||||
boolean local = stream.readBoolean();
|
||||
|
||||
if(local){
|
||||
if(local && !headless){
|
||||
byte mechid = stream.readByte();
|
||||
int index = stream.readByte();
|
||||
players[index].readSaveSuper(stream);
|
||||
players[index].mech = Upgrade.getByID(mechid);
|
||||
players[index].dead = false;
|
||||
}else if(local){
|
||||
byte mechid = stream.readByte();
|
||||
stream.readByte();
|
||||
readSaveSuper(stream);
|
||||
mech = Upgrade.getByID(mechid);
|
||||
dead = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,6 +745,9 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
buffer.writeByte(mech.id);
|
||||
buffer.writeBoolean(isBoosting);
|
||||
buffer.writeInt(mining == null ? -1 : mining.packedPosition());
|
||||
buffer.writeInt(spawner);
|
||||
|
||||
writeBuilding(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -735,6 +761,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
mech = Upgrade.getByID(buffer.readByte());
|
||||
boolean boosting = buffer.readBoolean();
|
||||
int mine = buffer.readInt();
|
||||
spawner = buffer.readInt();
|
||||
|
||||
readBuilding(buffer, !isLocal);
|
||||
|
||||
interpolator.read(lastx, lasty, x, y, time, rotation);
|
||||
rotation = lastrot;
|
||||
|
||||
|
||||
@@ -131,6 +131,10 @@ public class TileEntity extends BaseEntity implements TargetTrait {
|
||||
}
|
||||
}
|
||||
|
||||
public Tile getTile(){
|
||||
return tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Team getTeam() {
|
||||
return tile.getTeam();
|
||||
|
||||
@@ -132,6 +132,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
@Override
|
||||
public void readSave(DataInput stream) throws IOException {
|
||||
byte team = stream.readByte();
|
||||
boolean dead = stream.readBoolean();
|
||||
float x = stream.readFloat();
|
||||
float y = stream.readFloat();
|
||||
byte xv = stream.readByte();
|
||||
@@ -141,6 +142,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
|
||||
this.status.readSave(stream);
|
||||
this.inventory.readSave(stream);
|
||||
this.dead = dead;
|
||||
this.team = Team.all[team];
|
||||
this.health = health;
|
||||
this.x = x;
|
||||
@@ -151,6 +153,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
|
||||
public void writeSave(DataOutput stream, boolean net) throws IOException {
|
||||
stream.writeByte(team.ordinal());
|
||||
stream.writeBoolean(isDead());
|
||||
stream.writeFloat(net ? interpolator.target.x : x);
|
||||
stream.writeFloat(net ? interpolator.target.y : y);
|
||||
stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
||||
@@ -196,7 +199,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
public void avoidOthers(float avoidRange){
|
||||
|
||||
EntityPhysics.getNearby(getGroup(), x, y, avoidRange*2f, t -> {
|
||||
if(t == this || (t instanceof Unit && (((Unit) t).isDead() || (((Unit) t).isFlying() != isFlying())))) return;
|
||||
if(t == this || (t instanceof Unit && (((Unit) t).isDead() || (((Unit) t).isFlying() != isFlying()) || ((Unit) t).getCarrier() == this) || getCarrier() == t)) return;
|
||||
float dst = distanceTo(t);
|
||||
if(dst > avoidRange) return;
|
||||
velocity.add(moveVector.set(x, y).sub(t.getX(), t.getY()).setLength(1f * (1f - (dst / avoidRange))));
|
||||
|
||||
@@ -43,7 +43,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
||||
|
||||
/**Start a fire on the tile. If there already is a file there, refreshes its lifetime.*/
|
||||
public static void create(Tile tile){
|
||||
if(Net.client()) return; //not clientside.
|
||||
if(Net.client() || tile == null) return; //not clientside.
|
||||
|
||||
Fire fire = map.get(tile.packedPosition());
|
||||
|
||||
@@ -62,7 +62,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
||||
|
||||
/**Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing.*/
|
||||
public static void extinguish(Tile tile, float intensity) {
|
||||
if (map.containsKey(tile.packedPosition())) {
|
||||
if (tile != null && map.containsKey(tile.packedPosition())) {
|
||||
map.get(tile.packedPosition()).time += intensity * Timers.delta();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,7 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
||||
return drop;
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, in = In.entities)
|
||||
public static void createItemDrop(Item item, int amount, float x, float y, float velocityX, float velocityY){
|
||||
public static void create(Item item, int amount, float x, float y, float velocityX, float velocityY){
|
||||
create(item, amount, x, y, 0).getVelocity().set(velocityX, velocityY);
|
||||
}
|
||||
|
||||
@@ -69,6 +68,9 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
||||
Effects.effect(UnitFx.pickup, drop);
|
||||
}
|
||||
itemGroup.removeByID(itemid);
|
||||
if(Net.client()){
|
||||
netClient.addRemovedEntity(itemid);
|
||||
}
|
||||
}
|
||||
|
||||
/**Internal use only!*/
|
||||
|
||||
@@ -8,25 +8,29 @@ import io.anuke.mindustry.content.fx.BlockFx;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.gen.CallBlocks;
|
||||
import io.anuke.mindustry.gen.CallEntity;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.world.Build;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BreakBlock;
|
||||
import io.anuke.mindustry.world.blocks.BreakBlock.BreakEntity;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.trait.Entity;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Fill;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.graphics.Shapes;
|
||||
import io.anuke.ucore.util.*;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Translator;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
@@ -34,7 +38,7 @@ import static io.anuke.mindustry.Vars.tmptr;
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
/**Interface for units that build, break or mine things.*/
|
||||
public interface BuilderTrait {
|
||||
public interface BuilderTrait extends Entity{
|
||||
//these are not instance variables!
|
||||
float placeDistance = 140f;
|
||||
float mineDistance = 70f;
|
||||
@@ -54,6 +58,49 @@ public interface BuilderTrait {
|
||||
/**Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all.*/
|
||||
float getBuildPower(Tile tile);
|
||||
|
||||
default void writeBuilding(DataOutput output) throws IOException{
|
||||
BuildRequest request = getCurrentRequest();
|
||||
|
||||
if(request != null){
|
||||
output.writeByte(request.remove ? 1 : 0);
|
||||
output.writeInt(world.toPacked(request.x, request.y));
|
||||
if(!request.remove){
|
||||
output.writeByte(request.recipe.id);
|
||||
output.writeByte(request.rotation);
|
||||
}
|
||||
}else{
|
||||
output.writeByte(-1);
|
||||
}
|
||||
}
|
||||
|
||||
default void readBuilding(DataInput input) throws IOException{
|
||||
readBuilding(input, true);
|
||||
}
|
||||
|
||||
default void readBuilding(DataInput input, boolean applyChanges) throws IOException{
|
||||
synchronized (getPlaceQueue()) {
|
||||
if(applyChanges) getPlaceQueue().clear();
|
||||
|
||||
byte type = input.readByte();
|
||||
if (type != -1) {
|
||||
int position = input.readInt();
|
||||
BuildRequest request;
|
||||
|
||||
if (type == 1) { //remove
|
||||
request = new BuildRequest(position % world.width(), position / world.width());
|
||||
} else { //place
|
||||
byte recipe = input.readByte();
|
||||
byte rotation = input.readByte();
|
||||
request = new BuildRequest(position % world.width(), position / world.width(), rotation, Recipe.getByID(recipe));
|
||||
}
|
||||
|
||||
if(applyChanges){
|
||||
getPlaceQueue().addLast(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**Return whether this builder's place queue contains items.*/
|
||||
default boolean isBuilding(){
|
||||
return getPlaceQueue().size != 0;
|
||||
@@ -77,11 +124,7 @@ public interface BuilderTrait {
|
||||
|
||||
/**Clears the placement queue.*/
|
||||
default void clearBuilding(){
|
||||
if(this instanceof Player) {
|
||||
CallBlocks.onBuildDeselect((Player) this);
|
||||
}else{
|
||||
getPlaceQueue().clear();
|
||||
}
|
||||
getPlaceQueue().clear();
|
||||
}
|
||||
|
||||
/**Add another build requests to the tail of the queue, if it doesn't exist there yet.*/
|
||||
@@ -119,75 +162,40 @@ public interface BuilderTrait {
|
||||
setMineTile(null);
|
||||
}
|
||||
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
//if there is no core to build with, stop building!
|
||||
if(core == null){
|
||||
return;
|
||||
}
|
||||
|
||||
Tile tile = world.tile(current.x, current.y);
|
||||
|
||||
if(unit.distanceTo(tile) > placeDistance || //out of range, skip it
|
||||
(current.lastEntity != null && current.lastEntity.isDead())) { //build/destroy request has died, skip it
|
||||
getPlaceQueue().removeFirst();
|
||||
}else if(current.remove){
|
||||
|
||||
if (!(tile.block() instanceof BreakBlock)) { //check if haven't started placing
|
||||
if(Build.validBreak(unit.getTeam(), current.x, current.y)){
|
||||
|
||||
//if it's valid, place it
|
||||
if(!current.requested && unit instanceof Player){
|
||||
CallBlocks.breakBlock((Player)unit, unit.getTeam(), current.x, current.y);
|
||||
current.requested = true;
|
||||
}
|
||||
}else{
|
||||
//otherwise, skip it
|
||||
getPlaceQueue().removeFirst();
|
||||
}
|
||||
if (!(tile.block() instanceof BuildBlock)) {
|
||||
if(!current.remove && Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)) {
|
||||
Build.beginPlace(unit.getTeam(), current.x, current.y, current.recipe, current.rotation);
|
||||
}else if(current.remove && Build.validBreak(unit.getTeam(), current.x, current.y)){
|
||||
Build.beginBreak(unit.getTeam(), current.x, current.y);
|
||||
}else{
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
//if there is no core to build with, stop building!
|
||||
if(core == null){
|
||||
return;
|
||||
}
|
||||
|
||||
//otherwise, update it.
|
||||
BreakEntity entity = tile.entity();
|
||||
current.lastEntity = entity;
|
||||
|
||||
entity.addProgress(core, unit, 1f / entity.breakTime * Timers.delta() * getBuildPower(tile));
|
||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
|
||||
getCurrentRequest().progress = entity.progress();
|
||||
}
|
||||
}else{
|
||||
if (!(tile.block() instanceof BuildBlock)) { //check if haven't started placing
|
||||
if(Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){
|
||||
|
||||
//if it's valid, place it
|
||||
if(!current.requested && unit instanceof Player){
|
||||
CallBlocks.placeBlock((Player)unit, unit.getTeam(), current.x, current.y, current.recipe, current.rotation);
|
||||
current.requested = true;
|
||||
}
|
||||
|
||||
}else{
|
||||
//otherwise, skip it
|
||||
getPlaceQueue().removeFirst();
|
||||
}
|
||||
}else{
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
//if there is no core to build with, stop building!
|
||||
if(core == null){
|
||||
return;
|
||||
}
|
||||
|
||||
//otherwise, update it.
|
||||
BuildEntity entity = tile.entity();
|
||||
current.lastEntity = entity;
|
||||
|
||||
entity.addProgress(core.items, 1f / entity.recipe.cost * Timers.delta() * getBuildPower(tile));
|
||||
if(unit instanceof Player){
|
||||
entity.lastBuilder = (Player)unit;
|
||||
}
|
||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
|
||||
getCurrentRequest().progress = entity.progress();
|
||||
getPlaceQueue().removeFirst();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//otherwise, update it.
|
||||
BuildEntity entity = tile.entity();
|
||||
|
||||
//deconstructing is 2x as fast
|
||||
if(current.remove){
|
||||
entity.deconstruct(unit, core, 2f / entity.buildCost * Timers.delta() * getBuildPower(tile));
|
||||
}else{
|
||||
entity.construct(unit, core, 1f / entity.buildCost * Timers.delta() * getBuildPower(tile));
|
||||
}
|
||||
|
||||
if(unit.distanceTo(tile) <= placeDistance){
|
||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
|
||||
}
|
||||
current.progress = entity.progress();
|
||||
}
|
||||
|
||||
/**Do not call directly.*/
|
||||
@@ -233,7 +241,11 @@ public interface BuilderTrait {
|
||||
|
||||
Tile tile = world.tile(request.x, request.y);
|
||||
|
||||
Draw.color(unit.distanceTo(tile) > placeDistance || request.remove ? Palette.remove : Palette.accent);
|
||||
if(unit.distanceTo(tile) > placeDistance){
|
||||
return;
|
||||
}
|
||||
|
||||
Draw.color(Palette.accent);
|
||||
float focusLen = 3.8f + Mathf.absin(Timers.time(), 1.1f, 0.6f);
|
||||
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
|
||||
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
|
||||
@@ -302,9 +314,6 @@ public interface BuilderTrait {
|
||||
public final Recipe recipe;
|
||||
public final boolean remove;
|
||||
|
||||
public boolean requested;
|
||||
public TileEntity lastEntity;
|
||||
|
||||
public float progress;
|
||||
|
||||
/**This creates a build request.*/
|
||||
|
||||
@@ -32,14 +32,14 @@ public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{
|
||||
CallEntity.setCarryOf(this instanceof Player ? (Player)this : null, this, unit);
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, targets = Loc.both, forward = true, in = In.entities)
|
||||
@Remote(called = Loc.both, targets = Loc.both, forward = true, in = In.entities)
|
||||
static void dropSelf(Player player){
|
||||
if(player.getCarrier() != null){
|
||||
player.getCarrier().dropCarry();
|
||||
}
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, targets = Loc.both, forward = true, in = In.entities)
|
||||
@Remote(called = Loc.both, targets = Loc.both, forward = true, in = In.entities)
|
||||
static void setCarryOf(Player player, CarryTrait trait, CarriableTrait unit){
|
||||
if(player != null){ //when a server recieves this called from a player, set the carrier to the player.
|
||||
trait = player;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package io.anuke.mindustry.entities.traits;
|
||||
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
|
||||
public interface SpawnerTrait {
|
||||
Tile getTile();
|
||||
void updateSpawning(Unit unit);
|
||||
float getSpawnProgress();
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.entities.effect.ScorchDecal;
|
||||
import io.anuke.mindustry.entities.traits.ShooterTrait;
|
||||
import io.anuke.mindustry.entities.traits.SpawnerTrait;
|
||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
||||
@@ -52,7 +53,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
|
||||
protected boolean isWave;
|
||||
protected Squad squad;
|
||||
protected int spawner = -1;
|
||||
protected int spawner;
|
||||
|
||||
/**Initialize the type and team of this unit. Only call once!*/
|
||||
public void init(UnitType type, Team team){
|
||||
@@ -62,8 +63,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
this.team = team;
|
||||
}
|
||||
|
||||
public void setSpawner(UnitFactoryEntity spawner) {
|
||||
this.spawner = spawner.tile.packedPosition();
|
||||
public void setSpawner(Tile tile) {
|
||||
this.spawner = tile.packedPosition();
|
||||
}
|
||||
|
||||
public UnitType getType() {
|
||||
@@ -92,6 +93,19 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
((TileEntity)target).tile.block().flags.contains(flag);
|
||||
}
|
||||
|
||||
public void updateRespawning(){
|
||||
if(spawner == -1) return;
|
||||
|
||||
Tile tile = world.tile(spawner);
|
||||
if(tile != null && tile.entity != null){
|
||||
if(tile.entity instanceof SpawnerTrait){
|
||||
((SpawnerTrait) tile.entity).updateSpawning(this);
|
||||
}
|
||||
}else{
|
||||
spawner = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void setState(UnitState state){
|
||||
this.state.set(state);
|
||||
}
|
||||
@@ -162,6 +176,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return super.isValid() && isAdded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timer getTimer() {
|
||||
return timer;
|
||||
@@ -249,6 +268,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
|
||||
if(hitTime < 0) hitTime = 0;
|
||||
|
||||
if(isDead()){
|
||||
updateRespawning();
|
||||
return;
|
||||
}
|
||||
|
||||
if(Net.client()){
|
||||
interpolate();
|
||||
status.update(this);
|
||||
@@ -317,7 +341,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
hitboxTile.setSize(type.hitsizeTile);
|
||||
state.set(getStartState());
|
||||
|
||||
heal();
|
||||
health(maxHealth());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -348,6 +372,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
public void write(DataOutput data) throws IOException{
|
||||
super.writeSave(data);
|
||||
data.writeByte(type.id);
|
||||
data.writeInt(spawner);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -355,6 +380,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
float lastx = x, lasty = y, lastrot = rotation;
|
||||
super.readSave(data);
|
||||
this.type = UnitType.getByID(data.readByte());
|
||||
this.spawner = data.readInt();
|
||||
|
||||
interpolator.read(lastx, lasty, x, y, time, rotation);
|
||||
rotation = lastrot;
|
||||
@@ -368,7 +394,9 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
public static void onUnitDeath(BaseUnit unit){
|
||||
if(unit == null) return;
|
||||
|
||||
UnitDrops.dropItems(unit);
|
||||
if(Net.server() || !Net.active()){
|
||||
UnitDrops.dropItems(unit);
|
||||
}
|
||||
|
||||
float explosiveness = 2f + (unit.inventory.hasItem() ? unit.inventory.getItem().item.explosiveness * unit.inventory.getItem().amount : 0f);
|
||||
float flammability = (unit.inventory.hasItem() ? unit.inventory.getItem().item.flammability * unit.inventory.getItem().amount : 0f);
|
||||
|
||||
@@ -22,7 +22,6 @@ import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public abstract class FlyingUnit extends BaseUnit implements CarryTrait{
|
||||
protected static Translator vec = new Translator();
|
||||
protected static float maxAim = 30f;
|
||||
protected static float wobblyness = 0.6f;
|
||||
|
||||
protected Trail trail = new Trail(8);
|
||||
|
||||
@@ -2,7 +2,7 @@ package io.anuke.mindustry.entities.units;
|
||||
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.content.Items;
|
||||
import io.anuke.mindustry.gen.CallEntity;
|
||||
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
@@ -21,9 +21,9 @@ public class UnitDrops {
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for(Item item : dropTable){
|
||||
if(Mathf.chance(0.2)){
|
||||
int amount = Mathf.random(1, 5);
|
||||
CallEntity.createItemDrop(item, amount, unit.x + Mathf.range(2f), unit.y + Mathf.range(2f),
|
||||
if(Mathf.chance(0.03)){
|
||||
int amount = Mathf.random(20, 40);
|
||||
ItemDrop.create(item, amount, unit.x + Mathf.range(2f), unit.y + Mathf.range(2f),
|
||||
unit.getVelocity().x + Mathf.range(3f), unit.getVelocity().y + Mathf.range(3f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import io.anuke.mindustry.gen.CallEntity;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
@@ -206,26 +205,19 @@ public class Drone extends FlyingUnit implements BuilderTrait {
|
||||
public void write(DataOutput data) throws IOException {
|
||||
super.write(data);
|
||||
data.writeInt(mineTile == null ? -1 : mineTile.packedPosition());
|
||||
data.writeInt(placeQueue.size == 0 ? -1 : world.tile(placeQueue.last().x, placeQueue.last().y).packedPosition());
|
||||
data.writeByte(placeQueue.size == 0 ? -1 : placeQueue.last().recipe.id);
|
||||
writeBuilding(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput data, long time) throws IOException {
|
||||
super.read(data, time);
|
||||
int mined = data.readInt();
|
||||
int pp = data.readInt();
|
||||
byte rid = data.readByte();
|
||||
|
||||
readBuilding(data);
|
||||
|
||||
if(mined != -1){
|
||||
mineTile = world.tile(mined);
|
||||
}
|
||||
|
||||
if(pp != -1){
|
||||
Tile tile = world.tile(pp);
|
||||
placeQueue.clear();
|
||||
placeQueue.addLast(new BuildRequest(tile.x, tile.y, tile.getRotation(), Recipe.getByID(rid)));
|
||||
}
|
||||
}
|
||||
|
||||
public final UnitState
|
||||
|
||||
Reference in New Issue
Block a user