Implemented unit syncing, new instantiation system
This commit is contained in:
@@ -7,8 +7,14 @@ import io.anuke.mindustry.content.*;
|
|||||||
import io.anuke.mindustry.content.blocks.*;
|
import io.anuke.mindustry.content.blocks.*;
|
||||||
import io.anuke.mindustry.content.bullets.*;
|
import io.anuke.mindustry.content.bullets.*;
|
||||||
import io.anuke.mindustry.content.fx.*;
|
import io.anuke.mindustry.content.fx.*;
|
||||||
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.bullet.BulletType;
|
import io.anuke.mindustry.entities.bullet.BulletType;
|
||||||
|
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||||
|
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||||
import io.anuke.mindustry.entities.units.UnitType;
|
import io.anuke.mindustry.entities.units.UnitType;
|
||||||
|
import io.anuke.mindustry.entities.units.types.Drone;
|
||||||
|
import io.anuke.mindustry.entities.units.types.Scout;
|
||||||
|
import io.anuke.mindustry.entities.units.types.Vtol;
|
||||||
import io.anuke.mindustry.game.Content;
|
import io.anuke.mindustry.game.Content;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
import io.anuke.mindustry.type.Liquid;
|
import io.anuke.mindustry.type.Liquid;
|
||||||
@@ -86,6 +92,8 @@ public class ContentLoader {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerTypes();
|
||||||
|
|
||||||
for (ContentList list : content){
|
for (ContentList list : content){
|
||||||
list.load();
|
list.load();
|
||||||
}
|
}
|
||||||
@@ -117,4 +125,13 @@ public class ContentLoader {
|
|||||||
public static void dispose(){
|
public static void dispose(){
|
||||||
//TODO clear all content.
|
//TODO clear all content.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Registers sync IDs for all types of sync entities.*/
|
||||||
|
private static void registerTypes(){
|
||||||
|
Player.typeID = SyncTrait.registerType(Player::new);
|
||||||
|
Drone.typeID = SyncTrait.registerType(Drone::new);
|
||||||
|
Vtol.typeID = SyncTrait.registerType(Vtol::new);
|
||||||
|
Scout.typeID = SyncTrait.registerType(Scout::new);
|
||||||
|
ItemDrop.typeID = SyncTrait.registerType(ItemDrop::new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package io.anuke.mindustry.core;
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.utils.Pools;
|
import com.badlogic.gdx.utils.Pools;
|
||||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
|
||||||
import com.badlogic.gdx.utils.reflect.ReflectionException;
|
|
||||||
import io.anuke.annotations.Annotations.Remote;
|
import io.anuke.annotations.Annotations.Remote;
|
||||||
import io.anuke.annotations.Annotations.Variant;
|
import io.anuke.annotations.Annotations.Variant;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
@@ -217,38 +215,45 @@ public class NetClient extends Module {
|
|||||||
world.tile(pos).entity.items.read(input);
|
world.tile(pos).entity.items.read(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long timestamp = input.readLong();
|
||||||
|
|
||||||
byte totalGroups = input.readByte();
|
byte totalGroups = input.readByte();
|
||||||
//for each group...
|
//for each group...
|
||||||
for (int i = 0; i < totalGroups; i++) {
|
for (int i = 0; i < totalGroups; i++) {
|
||||||
//read group info
|
//read group info
|
||||||
byte groupID = input.readByte();
|
byte groupID = input.readByte();
|
||||||
short amount = input.readShort();
|
short amount = input.readShort();
|
||||||
long timestamp = input.readLong();
|
|
||||||
|
|
||||||
EntityGroup<?> group = Entities.getGroup(groupID);
|
EntityGroup group = Entities.getGroup(groupID);
|
||||||
|
|
||||||
//go through each entity
|
//go through each entity
|
||||||
for (int j = 0; j < amount; j++) {
|
for (int j = 0; j < amount; j++) {
|
||||||
int id = input.readInt();
|
int id = input.readInt();
|
||||||
|
byte typeID = input.readByte();
|
||||||
|
|
||||||
SyncTrait entity = (SyncTrait) group.getByID(id);
|
SyncTrait entity = (SyncTrait) group.getByID(id);
|
||||||
|
boolean add = false;
|
||||||
|
|
||||||
//entity must not be added yet, so create it
|
//entity must not be added yet, so create it
|
||||||
if(entity == null){
|
if(entity == null){
|
||||||
entity = (SyncTrait) ClassReflection.newInstance(group.getType()); //TODO solution without reflection?
|
entity = SyncTrait.getTypeByID(typeID).get(); //create entity from supplier
|
||||||
entity.resetID(id);
|
entity.resetID(id);
|
||||||
entity.add();
|
add = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//read the entity
|
//read the entity
|
||||||
entity.read(input, timestamp);
|
entity.read(input, timestamp);
|
||||||
|
|
||||||
|
if(add){
|
||||||
|
entity.add();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//confirm that snapshot has been recieved
|
//confirm that snapshot has been recieved
|
||||||
netClient.lastSnapshotID = snapshotID;
|
netClient.lastSnapshotID = snapshotID;
|
||||||
|
|
||||||
}catch (IOException | ReflectionException e){
|
}catch (IOException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,6 +243,9 @@ public class NetServer extends Module{
|
|||||||
tile.entity.items.write(dataStream);
|
tile.entity.items.write(dataStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//write timestamp
|
||||||
|
dataStream.writeLong(TimeUtils.millis());
|
||||||
|
|
||||||
//write total amount of serializable groups
|
//write total amount of serializable groups
|
||||||
dataStream.writeByte(totalGroups);
|
dataStream.writeByte(totalGroups);
|
||||||
|
|
||||||
@@ -259,13 +262,12 @@ public class NetServer extends Module{
|
|||||||
//write group ID + group size
|
//write group ID + group size
|
||||||
dataStream.writeByte(group.getID());
|
dataStream.writeByte(group.getID());
|
||||||
dataStream.writeShort(group.size());
|
dataStream.writeShort(group.size());
|
||||||
//write timestamp
|
|
||||||
dataStream.writeLong(TimeUtils.millis());
|
|
||||||
|
|
||||||
for(Entity entity : group.all()){
|
for(Entity entity : group.all()){
|
||||||
//write all entities now
|
//write all entities now
|
||||||
dataStream.writeInt(entity.getID());
|
dataStream.writeInt(entity.getID()); //write id
|
||||||
((SyncTrait)entity).write(dataStream);
|
dataStream.writeByte(((SyncTrait)entity).getTypeID()); //write type ID
|
||||||
|
((SyncTrait)entity).write(dataStream); //write entity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,7 @@ import io.anuke.mindustry.Vars;
|
|||||||
import io.anuke.mindustry.content.Mechs;
|
import io.anuke.mindustry.content.Mechs;
|
||||||
import io.anuke.mindustry.content.Weapons;
|
import io.anuke.mindustry.content.Weapons;
|
||||||
import io.anuke.mindustry.entities.effect.ItemDrop;
|
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||||
import io.anuke.mindustry.entities.traits.BuilderTrait;
|
import io.anuke.mindustry.entities.traits.*;
|
||||||
import io.anuke.mindustry.entities.traits.CarriableTrait;
|
|
||||||
import io.anuke.mindustry.entities.traits.CarryTrait;
|
|
||||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.gen.CallEntity;
|
import io.anuke.mindustry.gen.CallEntity;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
@@ -49,6 +46,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
|||||||
private static final float dashSpeed = 1.8f;
|
private static final float dashSpeed = 1.8f;
|
||||||
private static final Vector2 movement = new Vector2();
|
private static final Vector2 movement = new Vector2();
|
||||||
|
|
||||||
|
public static int typeID = -1;
|
||||||
|
|
||||||
public static final int timerShootLeft = 0;
|
public static final int timerShootLeft = 0;
|
||||||
public static final int timerShootRight = 1;
|
public static final int timerShootRight = 1;
|
||||||
public static final int timeSync = 2;
|
public static final int timeSync = 2;
|
||||||
@@ -104,6 +103,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTypeID() {
|
||||||
|
return typeID;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CarriableTrait getCarry() {
|
public CarriableTrait getCarry() {
|
||||||
return carrying;
|
return carrying;
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ import static io.anuke.mindustry.Vars.world;
|
|||||||
public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait, CarriableTrait {
|
public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait, CarriableTrait {
|
||||||
/**total duration of hit flash effect*/
|
/**total duration of hit flash effect*/
|
||||||
public static final float hitDuration = 9f;
|
public static final float hitDuration = 9f;
|
||||||
|
/**Percision divisor of velocity, used when writing. For example a value of '2' would mean the percision is 1/2 = 0.5-size chunks.*/
|
||||||
|
public static final float velocityPercision = 8f;
|
||||||
|
/**Maximum absolute value of a velocity vector component.*/
|
||||||
|
public static final float maxAbsVelocity = 127f/velocityPercision;
|
||||||
|
|
||||||
public UnitInventory inventory = new UnitInventory(100, 100);
|
public UnitInventory inventory = new UnitInventory(100, 100);
|
||||||
public float rotation;
|
public float rotation;
|
||||||
@@ -103,10 +107,12 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
stream.writeByte(team.ordinal());
|
stream.writeByte(team.ordinal());
|
||||||
stream.writeFloat(x);
|
stream.writeFloat(x);
|
||||||
stream.writeFloat(y);
|
stream.writeFloat(y);
|
||||||
stream.writeFloat(rotation);
|
stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
||||||
|
stream.writeByte((byte)(Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
||||||
|
stream.writeShort((short)(rotation*2));
|
||||||
stream.writeShort((short)health);
|
stream.writeShort((short)health);
|
||||||
stream.writeByte(status.current().id);
|
stream.writeByte(status.current().id);
|
||||||
stream.writeFloat(status.getTime());
|
stream.writeShort((short)(status.getTime()*2));
|
||||||
inventory.write(stream);
|
inventory.write(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,16 +121,19 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
byte team = stream.readByte();
|
byte team = stream.readByte();
|
||||||
float x = stream.readFloat();
|
float x = stream.readFloat();
|
||||||
float y = stream.readFloat();
|
float y = stream.readFloat();
|
||||||
float rotation = stream.readFloat();
|
byte xv = stream.readByte();
|
||||||
|
byte yv = stream.readByte();
|
||||||
|
float rotation = stream.readShort()/2f;
|
||||||
int health = stream.readShort();
|
int health = stream.readShort();
|
||||||
byte effect = stream.readByte();
|
byte effect = stream.readByte();
|
||||||
float etime = stream.readFloat();
|
float etime = stream.readShort()/2f;
|
||||||
|
|
||||||
this.inventory.read(stream);
|
this.inventory.read(stream);
|
||||||
this.team = Team.values()[team];
|
this.team = Team.values()[team];
|
||||||
this.health = health;
|
this.health = health;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
|
this.velocity.set(xv / velocityPercision, yv / velocityPercision);
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
this.status.set(StatusEffect.getByID(effect), etime);
|
this.status.set(StatusEffect.getByID(effect), etime);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class Fire extends TimedEntity implements SaveTrait, Poolable {
|
|||||||
private float baseFlammability = -1, puddleFlammability;
|
private float baseFlammability = -1, puddleFlammability;
|
||||||
private float lifetime;
|
private float lifetime;
|
||||||
|
|
||||||
/**Start a fire on the tile. If there already is a file there, refreshes its lifetime..*/
|
/**Start a fire on the tile. If there already is a file there, refreshes its lifetime.*/
|
||||||
public static void create(Tile tile){
|
public static void create(Tile tile){
|
||||||
Fire fire = map.get(tile.packedPosition());
|
Fire fire = map.get(tile.packedPosition());
|
||||||
|
|
||||||
@@ -67,7 +67,11 @@ public class Fire extends TimedEntity implements SaveTrait, Poolable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
super.update();
|
time = Mathf.clamp(time + Timers.delta(), 0, lifetime());
|
||||||
|
|
||||||
|
if(time >= lifetime()){
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
|
||||||
TileEntity entity = tile.target().entity;
|
TileEntity entity = tile.target().entity;
|
||||||
boolean damage = entity != null;
|
boolean damage = entity != null;
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import java.io.IOException;
|
|||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class ItemDrop extends SolidEntity implements SyncTrait, DrawTrait, VelocityTrait, TimeTrait, Poolable {
|
public class ItemDrop extends SolidEntity implements SyncTrait, DrawTrait, VelocityTrait, TimeTrait, Poolable {
|
||||||
|
public static int typeID = -1;
|
||||||
|
|
||||||
private static final float sinkLifetime = 80f;
|
private static final float sinkLifetime = 80f;
|
||||||
|
|
||||||
private Interpolator interpolator = new Interpolator();
|
private Interpolator interpolator = new Interpolator();
|
||||||
@@ -64,6 +66,11 @@ public class ItemDrop extends SolidEntity implements SyncTrait, DrawTrait, Veloc
|
|||||||
hitboxTile.setSize(5f);
|
hitboxTile.setSize(5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTypeID() {
|
||||||
|
return typeID;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float lifetime() {
|
public float lifetime() {
|
||||||
return 60*60;
|
return 60*60;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package io.anuke.mindustry.entities.traits;
|
package io.anuke.mindustry.entities.traits;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
import io.anuke.mindustry.net.Interpolator;
|
import io.anuke.mindustry.net.Interpolator;
|
||||||
import io.anuke.ucore.entities.trait.Entity;
|
import io.anuke.ucore.entities.trait.Entity;
|
||||||
|
import io.anuke.ucore.function.Supplier;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
@@ -11,31 +13,59 @@ import java.io.IOException;
|
|||||||
import static io.anuke.mindustry.Vars.threads;
|
import static io.anuke.mindustry.Vars.threads;
|
||||||
|
|
||||||
public interface SyncTrait extends Entity {
|
public interface SyncTrait extends Entity {
|
||||||
|
int[] lastRegisteredID = {0};
|
||||||
|
Array<Supplier<? extends SyncTrait>> registeredTypes = new Array<>();
|
||||||
|
|
||||||
|
/**Register and return a type ID. The supplier should return a fresh instace of that type.*/
|
||||||
|
static int registerType(Supplier<? extends SyncTrait> supplier){
|
||||||
|
registeredTypes.add(supplier);
|
||||||
|
int result = lastRegisteredID[0];
|
||||||
|
lastRegisteredID[0] ++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Registers a syncable type by ID.*/
|
||||||
|
static Supplier<? extends SyncTrait> getTypeByID(int id){
|
||||||
|
if(id == -1){
|
||||||
|
throw new IllegalArgumentException("Attempt to retrieve invalid entity type ID! Did you forget to set it in ContentLoader.registerTypes()?");
|
||||||
|
}
|
||||||
|
return registeredTypes.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Whether smoothing of entities is enabled; not yet implemented.*/
|
||||||
static boolean isSmoothing(){
|
static boolean isSmoothing(){
|
||||||
return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f;
|
return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean doSync(){
|
/**Sets the position of this entity and updated the interpolator.*/
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default void setNet(float x, float y){
|
default void setNet(float x, float y){
|
||||||
set(x, y);
|
set(x, y);
|
||||||
getInterpolator().target.set(x, y);
|
|
||||||
getInterpolator().last.set(x, y);
|
if(getInterpolator() != null) {
|
||||||
getInterpolator().spacing = 1f;
|
getInterpolator().target.set(x, y);
|
||||||
getInterpolator().time = 0f;
|
getInterpolator().last.set(x, y);
|
||||||
|
getInterpolator().spacing = 1f;
|
||||||
|
getInterpolator().time = 0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Interpolate entity position only. Override if you need to interpolate rotations or other values.*/
|
||||||
default void interpolate(){
|
default void interpolate(){
|
||||||
|
if(getInterpolator() == null) throw new RuntimeException("This entity must have an interpolator to interpolate()!");
|
||||||
|
|
||||||
getInterpolator().update();
|
getInterpolator().update();
|
||||||
|
|
||||||
setX(getInterpolator().pos.x);
|
setX(getInterpolator().pos.x);
|
||||||
setY(getInterpolator().pos.y);
|
setY(getInterpolator().pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Interpolator getInterpolator();
|
/**Return the interpolator used for smoothing the position. Optional.*/
|
||||||
|
default Interpolator getInterpolator(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Returns the type ID of this entity used for intstantiation. Should be < BYTE_MAX.*/
|
||||||
|
int getTypeID();
|
||||||
|
|
||||||
//Read and write sync data, usually position
|
//Read and write sync data, usually position
|
||||||
void write(DataOutput data) throws IOException;
|
void write(DataOutput data) throws IOException;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package io.anuke.mindustry.entities.units;
|
package io.anuke.mindustry.entities.units;
|
||||||
|
|
||||||
|
import io.anuke.annotations.Annotations.Loc;
|
||||||
|
import io.anuke.annotations.Annotations.Remote;
|
||||||
import io.anuke.mindustry.content.fx.ExplosionFx;
|
import io.anuke.mindustry.content.fx.ExplosionFx;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.entities.Unit;
|
import io.anuke.mindustry.entities.Unit;
|
||||||
@@ -7,6 +9,8 @@ import io.anuke.mindustry.entities.Units;
|
|||||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
import io.anuke.mindustry.entities.bullet.Bullet;
|
||||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
|
import io.anuke.mindustry.gen.CallEntity;
|
||||||
|
import io.anuke.mindustry.net.In;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.type.AmmoType;
|
import io.anuke.mindustry.type.AmmoType;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
@@ -84,13 +88,7 @@ public abstract class BaseUnit extends Unit{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void shoot(AmmoType type, float rotation, float translation){
|
public void shoot(AmmoType type, float rotation, float translation){
|
||||||
Bullet.create(type.bullet, this,
|
|
||||||
x + Angles.trnsx(rotation, translation),
|
|
||||||
y + Angles.trnsy(rotation, translation), rotation);
|
|
||||||
Effects.effect(type.shootEffect, x + Angles.trnsx(rotation, translation),
|
|
||||||
y + Angles.trnsy(rotation, translation), rotation, this);
|
|
||||||
Effects.effect(type.smokeEffect, x + Angles.trnsx(rotation, translation),
|
|
||||||
y + Angles.trnsy(rotation, translation), rotation, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void targetClosestAllyFlag(BlockFlag flag){
|
public void targetClosestAllyFlag(BlockFlag flag){
|
||||||
@@ -117,6 +115,15 @@ public abstract class BaseUnit extends Unit{
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interpolate() {
|
||||||
|
super.interpolate();
|
||||||
|
|
||||||
|
if(interpolator.values.length > 0){
|
||||||
|
rotation = interpolator.values[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float maxHealth() {
|
public float maxHealth() {
|
||||||
return type.health;
|
return type.health;
|
||||||
@@ -200,12 +207,7 @@ public abstract class BaseUnit extends Unit{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeath(){
|
public void onDeath(){
|
||||||
super.onDeath();
|
CallEntity.onUnitDeath(this);
|
||||||
|
|
||||||
Effects.effect(ExplosionFx.explosion, this);
|
|
||||||
Effects.shake(2f, 2f, this);
|
|
||||||
|
|
||||||
remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,12 +246,42 @@ public abstract class BaseUnit extends Unit{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput data) throws IOException{
|
public void write(DataOutput data) throws IOException{
|
||||||
writeSave(data);
|
super.writeSave(data);
|
||||||
|
data.writeByte(type.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput data, long time) throws IOException{
|
public void read(DataInput data, long time) throws IOException{
|
||||||
|
float lastx = x, lasty = y, lastrot = rotation;
|
||||||
super.readSave(data);
|
super.readSave(data);
|
||||||
this.type = UnitType.getByID(data.readByte());
|
this.type = UnitType.getByID(data.readByte());
|
||||||
|
|
||||||
|
interpolator.read(lastx, lasty, x, y, time, rotation);
|
||||||
|
rotation = lastrot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSuperDeath(){
|
||||||
|
super.onDeath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(called = Loc.server, in = In.entities)
|
||||||
|
public static void onUnitShoot(BaseUnit unit, AmmoType type, float rotation){
|
||||||
|
Bullet.create(type.bullet, unit,
|
||||||
|
unit.x + Angles.trnsx(rotation, unit.type.shootTranslation),
|
||||||
|
unit.y + Angles.trnsy(rotation, unit.type.shootTranslation), rotation);
|
||||||
|
Effects.effect(type.shootEffect, unit.x + Angles.trnsx(rotation, unit.type.shootTranslation),
|
||||||
|
unit.y + Angles.trnsy(rotation, unit.type.shootTranslation), rotation, unit);
|
||||||
|
Effects.effect(type.smokeEffect, unit.x + Angles.trnsx(rotation, unit.type.shootTranslation),
|
||||||
|
unit.y + Angles.trnsy(rotation, unit.type.shootTranslation), rotation, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(called = Loc.server, in = In.entities)
|
||||||
|
public static void onUnitDeath(BaseUnit unit){
|
||||||
|
unit.onSuperDeath();
|
||||||
|
|
||||||
|
Effects.effect(ExplosionFx.explosion, unit);
|
||||||
|
Effects.shake(2f, 2f, unit);
|
||||||
|
|
||||||
|
unit.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import io.anuke.mindustry.game.Team;
|
|||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.graphics.Trail;
|
import io.anuke.mindustry.graphics.Trail;
|
||||||
import io.anuke.mindustry.type.AmmoType;
|
import io.anuke.mindustry.type.AmmoType;
|
||||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
@@ -18,7 +18,7 @@ import io.anuke.ucore.util.Translator;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class FlyingUnit extends BaseUnit implements CarryTrait{
|
public abstract class FlyingUnit extends BaseUnit implements CarryTrait{
|
||||||
protected static Translator vec = new Translator();
|
protected static Translator vec = new Translator();
|
||||||
protected static float maxAim = 30f;
|
protected static float maxAim = 30f;
|
||||||
protected static float wobblyness = 0.6f;
|
protected static float wobblyness = 0.6f;
|
||||||
@@ -30,6 +30,11 @@ public class FlyingUnit extends BaseUnit implements CarryTrait{
|
|||||||
super(type, team);
|
super(type, team);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//instantiation only
|
||||||
|
public FlyingUnit(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CarriableTrait getCarry() {
|
public CarriableTrait getCarry() {
|
||||||
return carrying;
|
return carrying;
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import io.anuke.mindustry.Vars;
|
|||||||
import io.anuke.mindustry.entities.Units;
|
import io.anuke.mindustry.entities.Units;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.type.AmmoType;
|
import io.anuke.mindustry.type.AmmoType;
|
||||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.blocks.Floor;
|
import io.anuke.mindustry.world.blocks.Floor;
|
||||||
|
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.util.*;
|
import io.anuke.ucore.util.*;
|
||||||
@@ -25,14 +25,17 @@ public abstract class GroundUnit extends BaseUnit {
|
|||||||
super(type, team);
|
super(type, team);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GroundUnit(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate() {
|
public void interpolate() {
|
||||||
interpolator.update();
|
super.interpolate();
|
||||||
|
|
||||||
x = interpolator.pos.x;
|
if(interpolator.values.length > 1) {
|
||||||
y = interpolator.pos.y;
|
baseRotation = interpolator.values[1];
|
||||||
rotation = interpolator.values[0];
|
}
|
||||||
baseRotation = interpolator.values[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public class UnitType {
|
|||||||
public float speed = 0.4f;
|
public float speed = 0.4f;
|
||||||
public float range = 160;
|
public float range = 160;
|
||||||
public float rotatespeed = 0.1f;
|
public float rotatespeed = 0.1f;
|
||||||
|
public float shootTranslation = 4f;
|
||||||
public float baseRotateSpeed = 0.1f;
|
public float baseRotateSpeed = 0.1f;
|
||||||
public float mass = 1f;
|
public float mass = 1f;
|
||||||
public boolean isFlying;
|
public boolean isFlying;
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import io.anuke.mindustry.entities.units.UnitType;
|
|||||||
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
|
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
|
||||||
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;
|
||||||
|
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||||
import io.anuke.ucore.core.Events;
|
import io.anuke.ucore.core.Events;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.entities.EntityGroup;
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
@@ -31,6 +31,8 @@ import static io.anuke.mindustry.Vars.unitGroups;
|
|||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class Drone extends FlyingUnit implements BuilderTrait {
|
public class Drone extends FlyingUnit implements BuilderTrait {
|
||||||
|
public static int typeID = -1;
|
||||||
|
|
||||||
protected static float healSpeed = 0.1f;
|
protected static float healSpeed = 0.1f;
|
||||||
protected static float discoverRange = 120f;
|
protected static float discoverRange = 120f;
|
||||||
protected static boolean initialized;
|
protected static boolean initialized;
|
||||||
@@ -64,6 +66,10 @@ public class Drone extends FlyingUnit implements BuilderTrait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Drone(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyPlaced(BuildEntity entity){
|
private void notifyPlaced(BuildEntity entity){
|
||||||
float timeToBuild = entity.recipe.cost;
|
float timeToBuild = entity.recipe.cost;
|
||||||
float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0);
|
float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0);
|
||||||
@@ -74,6 +80,11 @@ public class Drone extends FlyingUnit implements BuilderTrait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTypeID() {
|
||||||
|
return typeID;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getBuildPower(Tile tile) {
|
public float getBuildPower(Tile tile) {
|
||||||
return 0.3f;
|
return 0.3f;
|
||||||
|
|||||||
@@ -5,8 +5,18 @@ import io.anuke.mindustry.entities.units.UnitType;
|
|||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
|
|
||||||
public class Scout extends GroundUnit {
|
public class Scout extends GroundUnit {
|
||||||
|
public static int typeID = -1;
|
||||||
|
|
||||||
public Scout(UnitType type, Team team) {
|
public Scout(UnitType type, Team team) {
|
||||||
super(type, team);
|
super(type, team);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Scout(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTypeID() {
|
||||||
|
return typeID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,27 @@ package io.anuke.mindustry.entities.units.types;
|
|||||||
import io.anuke.mindustry.entities.units.FlyingUnit;
|
import io.anuke.mindustry.entities.units.FlyingUnit;
|
||||||
import io.anuke.mindustry.entities.units.UnitType;
|
import io.anuke.mindustry.entities.units.UnitType;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class Vtol extends FlyingUnit {
|
public class Vtol extends FlyingUnit {
|
||||||
|
public static int typeID = -1;
|
||||||
|
|
||||||
public Vtol(UnitType type, Team team) {
|
public Vtol(UnitType type, Team team) {
|
||||||
super(type, team);
|
super(type, team);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vtol(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTypeID() {
|
||||||
|
return typeID;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw() {
|
public void draw() {
|
||||||
Draw.alpha(hitTime / hitDuration);
|
Draw.alpha(hitTime / hitDuration);
|
||||||
@@ -31,10 +42,12 @@ public class Vtol extends FlyingUnit {
|
|||||||
public void update() {
|
public void update() {
|
||||||
super.update();
|
super.update();
|
||||||
|
|
||||||
|
if(Net.client()) return;
|
||||||
|
|
||||||
x += Mathf.sin(Timers.time() + id * 999, 25f, 0.07f);
|
x += Mathf.sin(Timers.time() + id * 999, 25f, 0.07f);
|
||||||
y += Mathf.cos(Timers.time() + id * 999, 25f, 0.07f);
|
y += Mathf.cos(Timers.time() + id * 999, 25f, 0.07f);
|
||||||
|
|
||||||
if(velocity.len() <= 0.2f){
|
if (velocity.len() <= 0.2f) {
|
||||||
rotation += Mathf.sin(Timers.time() + id * 99, 10f, 8f);
|
rotation += Mathf.sin(Timers.time() + id * 99, 10f, 8f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,10 @@ import io.anuke.annotations.Annotations.ReadClass;
|
|||||||
import io.anuke.annotations.Annotations.WriteClass;
|
import io.anuke.annotations.Annotations.WriteClass;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.Unit;
|
import io.anuke.mindustry.entities.Unit;
|
||||||
|
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.net.Packets.KickReason;
|
import io.anuke.mindustry.net.Packets.KickReason;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.type.Recipe;
|
|
||||||
import io.anuke.mindustry.type.Upgrade;
|
|
||||||
import io.anuke.mindustry.type.Weapon;
|
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
|
||||||
@@ -49,6 +47,19 @@ public class TypeIO {
|
|||||||
return (Unit)Entities.getGroup(gid).getByID(id);
|
return (Unit)Entities.getGroup(gid).getByID(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WriteClass(BaseUnit.class)
|
||||||
|
public static void writeBaseUnit(ByteBuffer buffer, BaseUnit unit){
|
||||||
|
buffer.put((byte)unit.getGroup().getID());
|
||||||
|
buffer.putInt(unit.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadClass(BaseUnit.class)
|
||||||
|
public static BaseUnit writeBaseUnit(ByteBuffer buffer){
|
||||||
|
byte gid = buffer.get();
|
||||||
|
int id = buffer.getInt();
|
||||||
|
return (BaseUnit)Entities.getGroup(gid).getByID(id);
|
||||||
|
}
|
||||||
|
|
||||||
@WriteClass(Tile.class)
|
@WriteClass(Tile.class)
|
||||||
public static void writeTile(ByteBuffer buffer, Tile tile){
|
public static void writeTile(ByteBuffer buffer, Tile tile){
|
||||||
buffer.putInt(tile.packedPosition());
|
buffer.putInt(tile.packedPosition());
|
||||||
@@ -89,6 +100,16 @@ public class TypeIO {
|
|||||||
return Upgrade.getByID(buffer.get());
|
return Upgrade.getByID(buffer.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WriteClass(AmmoType.class)
|
||||||
|
public static void writeAmmo(ByteBuffer buffer, AmmoType type){
|
||||||
|
buffer.put(type.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadClass(AmmoType.class)
|
||||||
|
public static AmmoType readAmmo(ByteBuffer buffer){
|
||||||
|
return AmmoType.getByID(buffer.get());
|
||||||
|
}
|
||||||
|
|
||||||
@WriteClass(Item.class)
|
@WriteClass(Item.class)
|
||||||
public static void writeItem(ByteBuffer buffer, Item item){
|
public static void writeItem(ByteBuffer buffer, Item item){
|
||||||
buffer.put((byte)item.id);
|
buffer.put((byte)item.id);
|
||||||
|
|||||||
Reference in New Issue
Block a user