From 5c98283932775fc4b8af835b6664d1370de881d9 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 10 Jun 2018 13:03:52 -0400 Subject: [PATCH] Implemented unit syncing, new instantiation system --- .../anuke/mindustry/core/ContentLoader.java | 17 ++++++ .../io/anuke/mindustry/core/NetClient.java | 19 +++--- .../io/anuke/mindustry/core/NetServer.java | 10 ++-- .../io/anuke/mindustry/entities/Player.java | 12 ++-- .../src/io/anuke/mindustry/entities/Unit.java | 17 ++++-- .../anuke/mindustry/entities/effect/Fire.java | 8 ++- .../mindustry/entities/effect/ItemDrop.java | 7 +++ .../mindustry/entities/traits/SyncTrait.java | 48 ++++++++++++--- .../mindustry/entities/units/BaseUnit.java | 60 ++++++++++++++----- .../mindustry/entities/units/FlyingUnit.java | 9 ++- .../mindustry/entities/units/GroundUnit.java | 15 +++-- .../mindustry/entities/units/UnitType.java | 1 + .../mindustry/entities/units/types/Drone.java | 13 +++- .../mindustry/entities/units/types/Scout.java | 10 ++++ .../mindustry/entities/units/types/Vtol.java | 15 ++++- core/src/io/anuke/mindustry/io/TypeIO.java | 29 +++++++-- 16 files changed, 232 insertions(+), 58 deletions(-) diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index 17734bdf17..71ea957850 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -7,8 +7,14 @@ import io.anuke.mindustry.content.*; import io.anuke.mindustry.content.blocks.*; import io.anuke.mindustry.content.bullets.*; import io.anuke.mindustry.content.fx.*; +import io.anuke.mindustry.entities.Player; 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.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.type.ContentList; import io.anuke.mindustry.type.Liquid; @@ -86,6 +92,8 @@ public class ContentLoader { return; } + registerTypes(); + for (ContentList list : content){ list.load(); } @@ -117,4 +125,13 @@ public class ContentLoader { public static void dispose(){ //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); + } } diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 09d2e9fb78..006fd88c36 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -2,8 +2,6 @@ package io.anuke.mindustry.core; import com.badlogic.gdx.graphics.Color; 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.Variant; import io.anuke.mindustry.core.GameState.State; @@ -217,38 +215,45 @@ public class NetClient extends Module { world.tile(pos).entity.items.read(input); } + long timestamp = input.readLong(); + byte totalGroups = input.readByte(); //for each group... for (int i = 0; i < totalGroups; i++) { //read group info byte groupID = input.readByte(); short amount = input.readShort(); - long timestamp = input.readLong(); - EntityGroup group = Entities.getGroup(groupID); + EntityGroup group = Entities.getGroup(groupID); //go through each entity for (int j = 0; j < amount; j++) { int id = input.readInt(); + byte typeID = input.readByte(); SyncTrait entity = (SyncTrait) group.getByID(id); + boolean add = false; //entity must not be added yet, so create it 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.add(); + add = true; } //read the entity entity.read(input, timestamp); + + if(add){ + entity.add(); + } } } //confirm that snapshot has been recieved netClient.lastSnapshotID = snapshotID; - }catch (IOException | ReflectionException e){ + }catch (IOException e){ e.printStackTrace(); } } diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index e4ff9e6489..d127751395 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -243,6 +243,9 @@ public class NetServer extends Module{ tile.entity.items.write(dataStream); } + //write timestamp + dataStream.writeLong(TimeUtils.millis()); + //write total amount of serializable groups dataStream.writeByte(totalGroups); @@ -259,13 +262,12 @@ public class NetServer extends Module{ //write group ID + group size dataStream.writeByte(group.getID()); dataStream.writeShort(group.size()); - //write timestamp - dataStream.writeLong(TimeUtils.millis()); for(Entity entity : group.all()){ //write all entities now - dataStream.writeInt(entity.getID()); - ((SyncTrait)entity).write(dataStream); + dataStream.writeInt(entity.getID()); //write id + dataStream.writeByte(((SyncTrait)entity).getTypeID()); //write type ID + ((SyncTrait)entity).write(dataStream); //write entity } } diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index a30d27055a..1672a0da2e 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -12,10 +12,7 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.content.Weapons; import io.anuke.mindustry.entities.effect.ItemDrop; -import io.anuke.mindustry.entities.traits.BuilderTrait; -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.entities.traits.*; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.CallEntity; 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 Vector2 movement = new Vector2(); + public static int typeID = -1; + public static final int timerShootLeft = 0; public static final int timerShootRight = 1; 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 public CarriableTrait getCarry() { return carrying; diff --git a/core/src/io/anuke/mindustry/entities/Unit.java b/core/src/io/anuke/mindustry/entities/Unit.java index fd377a8e71..2f895b088e 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/Unit.java @@ -29,6 +29,10 @@ import static io.anuke.mindustry.Vars.world; public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait, CarriableTrait { /**total duration of hit flash effect*/ 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 float rotation; @@ -103,10 +107,12 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ stream.writeByte(team.ordinal()); stream.writeFloat(x); 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.writeByte(status.current().id); - stream.writeFloat(status.getTime()); + stream.writeShort((short)(status.getTime()*2)); inventory.write(stream); } @@ -115,16 +121,19 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ byte team = stream.readByte(); float x = 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(); byte effect = stream.readByte(); - float etime = stream.readFloat(); + float etime = stream.readShort()/2f; this.inventory.read(stream); this.team = Team.values()[team]; this.health = health; this.x = x; this.y = y; + this.velocity.set(xv / velocityPercision, yv / velocityPercision); this.rotation = rotation; this.status.set(StatusEffect.getByID(effect), etime); } diff --git a/core/src/io/anuke/mindustry/entities/effect/Fire.java b/core/src/io/anuke/mindustry/entities/effect/Fire.java index 7d213df3a9..ad3cf50889 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fire.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fire.java @@ -34,7 +34,7 @@ public class Fire extends TimedEntity implements SaveTrait, Poolable { private float baseFlammability = -1, puddleFlammability; 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){ Fire fire = map.get(tile.packedPosition()); @@ -67,7 +67,11 @@ public class Fire extends TimedEntity implements SaveTrait, Poolable { @Override public void update() { - super.update(); + time = Mathf.clamp(time + Timers.delta(), 0, lifetime()); + + if(time >= lifetime()){ + remove(); + } TileEntity entity = tile.target().entity; boolean damage = entity != null; diff --git a/core/src/io/anuke/mindustry/entities/effect/ItemDrop.java b/core/src/io/anuke/mindustry/entities/effect/ItemDrop.java index a3f223d541..c7df1d6ff4 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ItemDrop.java +++ b/core/src/io/anuke/mindustry/entities/effect/ItemDrop.java @@ -32,6 +32,8 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class ItemDrop extends SolidEntity implements SyncTrait, DrawTrait, VelocityTrait, TimeTrait, Poolable { + public static int typeID = -1; + private static final float sinkLifetime = 80f; private Interpolator interpolator = new Interpolator(); @@ -64,6 +66,11 @@ public class ItemDrop extends SolidEntity implements SyncTrait, DrawTrait, Veloc hitboxTile.setSize(5f); } + @Override + public int getTypeID() { + return typeID; + } + @Override public float lifetime() { return 60*60; diff --git a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java index 251ba1e9ec..591505af32 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java @@ -1,8 +1,10 @@ package io.anuke.mindustry.entities.traits; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.net.Interpolator; import io.anuke.ucore.entities.trait.Entity; +import io.anuke.ucore.function.Supplier; import java.io.DataInput; import java.io.DataOutput; @@ -11,31 +13,59 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.threads; public interface SyncTrait extends Entity { + int[] lastRegisteredID = {0}; + Array> registeredTypes = new Array<>(); + /**Register and return a type ID. The supplier should return a fresh instace of that type.*/ + static int registerType(Supplier supplier){ + registeredTypes.add(supplier); + int result = lastRegisteredID[0]; + lastRegisteredID[0] ++; + return result; + } + + /**Registers a syncable type by ID.*/ + static Supplier 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(){ return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f; } - default boolean doSync(){ - return true; - } - + /**Sets the position of this entity and updated the interpolator.*/ default void setNet(float x, float y){ set(x, y); - getInterpolator().target.set(x, y); - getInterpolator().last.set(x, y); - getInterpolator().spacing = 1f; - getInterpolator().time = 0f; + + if(getInterpolator() != null) { + getInterpolator().target.set(x, y); + 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(){ + if(getInterpolator() == null) throw new RuntimeException("This entity must have an interpolator to interpolate()!"); + getInterpolator().update(); setX(getInterpolator().pos.x); 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 void write(DataOutput data) throws IOException; diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java index 8fdedabd2d..736e089357 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java @@ -1,5 +1,7 @@ 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.entities.TileEntity; 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.traits.TargetTrait; 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.type.AmmoType; 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){ - 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){ @@ -117,6 +115,15 @@ public abstract class BaseUnit extends Unit{ return null; } + @Override + public void interpolate() { + super.interpolate(); + + if(interpolator.values.length > 0){ + rotation = interpolator.values[0]; + } + } + @Override public float maxHealth() { return type.health; @@ -200,12 +207,7 @@ public abstract class BaseUnit extends Unit{ @Override public void onDeath(){ - super.onDeath(); - - Effects.effect(ExplosionFx.explosion, this); - Effects.shake(2f, 2f, this); - - remove(); + CallEntity.onUnitDeath(this); } @Override @@ -244,12 +246,42 @@ public abstract class BaseUnit extends Unit{ @Override public void write(DataOutput data) throws IOException{ - writeSave(data); + super.writeSave(data); + data.writeByte(type.id); } @Override public void read(DataInput data, long time) throws IOException{ + float lastx = x, lasty = y, lastrot = rotation; super.readSave(data); 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(); } } diff --git a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java b/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java index 58f00041f0..e8e7840c78 100644 --- a/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/FlyingUnit.java @@ -7,8 +7,8 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Trail; import io.anuke.mindustry.type.AmmoType; -import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Angles; @@ -18,7 +18,7 @@ import io.anuke.ucore.util.Translator; 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 float maxAim = 30f; protected static float wobblyness = 0.6f; @@ -30,6 +30,11 @@ public class FlyingUnit extends BaseUnit implements CarryTrait{ super(type, team); } + //instantiation only + public FlyingUnit(){ + + } + @Override public CarriableTrait getCarry() { return carrying; diff --git a/core/src/io/anuke/mindustry/entities/units/GroundUnit.java b/core/src/io/anuke/mindustry/entities/units/GroundUnit.java index a42227e547..f5ccfb4e67 100644 --- a/core/src/io/anuke/mindustry/entities/units/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/GroundUnit.java @@ -5,9 +5,9 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.type.AmmoType; -import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.*; @@ -25,14 +25,17 @@ public abstract class GroundUnit extends BaseUnit { super(type, team); } + public GroundUnit(){ + + } + @Override public void interpolate() { - interpolator.update(); + super.interpolate(); - x = interpolator.pos.x; - y = interpolator.pos.y; - rotation = interpolator.values[0]; - baseRotation = interpolator.values[1]; + if(interpolator.values.length > 1) { + baseRotation = interpolator.values[1]; + } } @Override diff --git a/core/src/io/anuke/mindustry/entities/units/UnitType.java b/core/src/io/anuke/mindustry/entities/units/UnitType.java index c807a38e75..413c4cc60b 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitType.java +++ b/core/src/io/anuke/mindustry/entities/units/UnitType.java @@ -21,6 +21,7 @@ public class UnitType { public float speed = 0.4f; public float range = 160; public float rotatespeed = 0.1f; + public float shootTranslation = 4f; public float baseRotateSpeed = 0.1f; public float mass = 1f; public boolean isFlying; diff --git a/core/src/io/anuke/mindustry/entities/units/types/Drone.java b/core/src/io/anuke/mindustry/entities/units/types/Drone.java index f3d91a6c1d..2064f3d8c4 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Drone.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Drone.java @@ -13,10 +13,10 @@ import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.game.EventType.BlockBuildEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BuildBlock; 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.Timers; import io.anuke.ucore.entities.EntityGroup; @@ -31,6 +31,8 @@ import static io.anuke.mindustry.Vars.unitGroups; import static io.anuke.mindustry.Vars.world; public class Drone extends FlyingUnit implements BuilderTrait { + public static int typeID = -1; + protected static float healSpeed = 0.1f; protected static float discoverRange = 120f; protected static boolean initialized; @@ -64,6 +66,10 @@ public class Drone extends FlyingUnit implements BuilderTrait { } } + public Drone(){ + + } + private void notifyPlaced(BuildEntity entity){ float timeToBuild = entity.recipe.cost; 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 public float getBuildPower(Tile tile) { return 0.3f; diff --git a/core/src/io/anuke/mindustry/entities/units/types/Scout.java b/core/src/io/anuke/mindustry/entities/units/types/Scout.java index aae30cb866..711ee6684a 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Scout.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Scout.java @@ -5,8 +5,18 @@ import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.game.Team; public class Scout extends GroundUnit { + public static int typeID = -1; public Scout(UnitType type, Team team) { super(type, team); } + + public Scout(){ + + } + + @Override + public int getTypeID() { + return typeID; + } } diff --git a/core/src/io/anuke/mindustry/entities/units/types/Vtol.java b/core/src/io/anuke/mindustry/entities/units/types/Vtol.java index 67232a4631..33c731e524 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Vtol.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Vtol.java @@ -3,16 +3,27 @@ package io.anuke.mindustry.entities.units.types; import io.anuke.mindustry.entities.units.FlyingUnit; import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.net.Net; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; public class Vtol extends FlyingUnit { + public static int typeID = -1; public Vtol(UnitType type, Team team) { super(type, team); } + public Vtol(){ + + } + + @Override + public int getTypeID() { + return typeID; + } + @Override public void draw() { Draw.alpha(hitTime / hitDuration); @@ -31,10 +42,12 @@ public class Vtol extends FlyingUnit { public void update() { super.update(); + if(Net.client()) return; + x += Mathf.sin(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); } } diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index 8f7d37a54f..af7b7a8a4e 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -4,12 +4,10 @@ import io.anuke.annotations.Annotations.ReadClass; import io.anuke.annotations.Annotations.WriteClass; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Packets.KickReason; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Recipe; -import io.anuke.mindustry.type.Upgrade; -import io.anuke.mindustry.type.Weapon; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.entities.Entities; @@ -49,6 +47,19 @@ public class TypeIO { 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) public static void writeTile(ByteBuffer buffer, Tile tile){ buffer.putInt(tile.packedPosition()); @@ -89,6 +100,16 @@ public class TypeIO { 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) public static void writeItem(ByteBuffer buffer, Item item){ buffer.put((byte)item.id);