mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-04-27 16:00:51 -07:00
Implemented new syncing system
This commit is contained in:
parent
e545b7cca7
commit
cc45e5afca
16 changed files with 237 additions and 191 deletions
|
|
@ -21,7 +21,7 @@ allprojects {
|
|||
appName = "Mindustry"
|
||||
gdxVersion = '1.9.8'
|
||||
aiVersion = '1.8.1'
|
||||
uCoreVersion = '89fa665';
|
||||
uCoreVersion = '7a567c6';
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 303 B After Width: | Height: | Size: 301 B |
Binary file not shown.
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
|
|
@ -9,6 +9,7 @@ import io.anuke.mindustry.core.GameState.State;
|
|||
import io.anuke.mindustry.entities.Bullet;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.SyncEntity;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.EnemyType;
|
||||
import io.anuke.mindustry.graphics.Fx;
|
||||
|
|
@ -16,8 +17,6 @@ import io.anuke.mindustry.io.NetworkIO;
|
|||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.Net.SendMode;
|
||||
import io.anuke.mindustry.net.Packets.*;
|
||||
import io.anuke.mindustry.net.Syncable;
|
||||
import io.anuke.mindustry.net.Syncable.Interpolator;
|
||||
import io.anuke.mindustry.resource.Recipe;
|
||||
import io.anuke.mindustry.resource.Recipes;
|
||||
import io.anuke.mindustry.resource.Upgrade;
|
||||
|
|
@ -30,10 +29,12 @@ import io.anuke.ucore.core.Timers;
|
|||
import io.anuke.ucore.entities.BaseBulletType;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.modules.Module;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static io.anuke.mindustry.Vars.ui;
|
||||
|
||||
|
|
@ -113,33 +114,30 @@ public class NetClient extends Module {
|
|||
Net.handle(SyncPacket.class, packet -> {
|
||||
if(!gotData) return;
|
||||
|
||||
//TODO awful code
|
||||
for(int i = 0; i < packet.ids.length; i ++){
|
||||
int id = packet.ids[i];
|
||||
if(id != Vars.player.id){
|
||||
Entity entity;
|
||||
if(i >= packet.enemyStart){
|
||||
entity = Vars.control.enemyGroup.getByID(id);
|
||||
}else {
|
||||
entity = Vars.control.playerGroup.getByID(id);
|
||||
ByteBuffer data = ByteBuffer.wrap(packet.data);
|
||||
|
||||
byte groupid = data.get();
|
||||
|
||||
EntityGroup<?> group = Entities.getGroup(groupid);
|
||||
|
||||
while(data.position() < data.capacity()){
|
||||
int id = data.getInt();
|
||||
|
||||
SyncEntity entity = (SyncEntity) group.getByID(id);
|
||||
|
||||
if (entity == null || id == Vars.player.id) {
|
||||
if (!requests.contains(id) && id != Vars.player.id) {
|
||||
UCore.log("Requesting entity " + id, "group " + group.getType());
|
||||
requests.add(id);
|
||||
EntityRequestPacket req = new EntityRequestPacket();
|
||||
req.id = id;
|
||||
Net.send(req, SendMode.tcp);
|
||||
}
|
||||
|
||||
Syncable sync = ((Syncable)entity);
|
||||
|
||||
if(sync == null){
|
||||
if(!requests.contains(id)){
|
||||
requests.add(id);
|
||||
Gdx.app.error("Mindustry", "Sending entity request: " + id);
|
||||
EntityRequestPacket req = new EntityRequestPacket();
|
||||
req.id = id;
|
||||
Net.send(req, SendMode.tcp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//augh
|
||||
((Interpolator)sync.getInterpolator()).type.read(entity, packet.data[i]);
|
||||
data.position(data.position() + SyncEntity.getWriteSize((Class<? extends SyncEntity>) group.getType()));
|
||||
} else {
|
||||
entity.read(data);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -281,8 +279,8 @@ public class NetClient extends Module {
|
|||
recieved.contains(player.id)) return;
|
||||
recieved.add(player.id);
|
||||
|
||||
player.getInterpolator().last.set(player.x, player.y);
|
||||
player.getInterpolator().target.set(player.x, player.y);
|
||||
player.interpolator.last.set(player.x, player.y);
|
||||
player.interpolator.target.set(player.x, player.y);
|
||||
player.add();
|
||||
});
|
||||
});
|
||||
|
|
@ -412,8 +410,12 @@ public class NetClient extends Module {
|
|||
|
||||
void sync(){
|
||||
if(Timers.get("syncPlayer", playerSyncTime)){
|
||||
byte[] bytes = new byte[Vars.player.getWriteSize()];
|
||||
ByteBuffer buffer = ByteBuffer.wrap(bytes);
|
||||
Vars.player.write(buffer);
|
||||
|
||||
PositionPacket packet = new PositionPacket();
|
||||
packet.data = Vars.player.getInterpolator().type.write(Vars.player);
|
||||
packet.data = bytes;
|
||||
Net.send(packet, SendMode.udp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import io.anuke.mindustry.Vars;
|
|||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.SyncEntity;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.io.NetworkIO;
|
||||
|
|
@ -17,7 +18,9 @@ import io.anuke.mindustry.world.Block;
|
|||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.UCore;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.modules.Module;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
|
@ -26,6 +29,7 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class NetServer extends Module{
|
||||
/**Maps connection IDs to players.*/
|
||||
|
|
@ -49,8 +53,8 @@ public class NetServer extends Module{
|
|||
player.name = packet.name;
|
||||
player.isAndroid = packet.android;
|
||||
player.set(Vars.control.core.worldx(), Vars.control.core.worldy() - Vars.tilesize*2);
|
||||
player.getInterpolator().last.set(player.x, player.y);
|
||||
player.getInterpolator().target.set(player.x, player.y);
|
||||
player.interpolator.last.set(player.x, player.y);
|
||||
player.interpolator.target.set(player.x, player.y);
|
||||
connections.put(id, player);
|
||||
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
|
|
@ -95,7 +99,7 @@ public class NetServer extends Module{
|
|||
|
||||
Net.handleServer(PositionPacket.class, pos -> {
|
||||
Player player = connections.get(Net.getLastConnection());
|
||||
player.getInterpolator().type.read(player, pos.data);
|
||||
player.read(ByteBuffer.wrap(pos.data));
|
||||
});
|
||||
|
||||
Net.handleServer(ShootPacket.class, packet -> {
|
||||
|
|
@ -270,32 +274,71 @@ public class NetServer extends Module{
|
|||
void sync(){
|
||||
|
||||
if(Timers.get("serverSync", serverSyncTime)){
|
||||
SyncPacket packet = new SyncPacket();
|
||||
int amount = Vars.control.playerGroup.amount() + Vars.control.enemyGroup.amount();
|
||||
packet.ids = new int[amount];
|
||||
packet.data = new float[amount][0];
|
||||
//scan through all groups with syncable entities
|
||||
for(EntityGroup<?> group : Entities.getAllGroups()) {
|
||||
if(group.amount() == 0 || !(group.all().first() instanceof SyncEntity)) continue;
|
||||
|
||||
short index = 0;
|
||||
UCore.log("Writing group " + group.getType(), "amount: " + group.amount());
|
||||
|
||||
for(Player player : Vars.control.playerGroup.all()){
|
||||
float[] out = player.getInterpolator().type.write(player);
|
||||
packet.data[index] = out;
|
||||
packet.ids[index] = player.id;
|
||||
//get write size for one entity (adding 4, as you need to write the ID as well)
|
||||
int writesize = SyncEntity.getWriteSize((Class<? extends SyncEntity>)group.getType()) + 4;
|
||||
//amount of entities
|
||||
int amount = group.amount();
|
||||
//maximum amount of entities per packet
|
||||
int maxsize = 64;
|
||||
|
||||
index ++;
|
||||
//current buffer you're writing to
|
||||
ByteBuffer current = null;
|
||||
//number of entities written to this packet/buffer
|
||||
int written = 0;
|
||||
|
||||
//for all the entities...
|
||||
for (int i = 0; i < amount; i++) {
|
||||
//if the buffer is null, create a new one
|
||||
if(current == null){
|
||||
//calculate amount of entities to go into this packet
|
||||
int csize = Math.min(amount-i, maxsize);
|
||||
//create a byte array to write to
|
||||
byte[] bytes = new byte[csize*writesize + 1];
|
||||
//wrap it for easy writing
|
||||
current = ByteBuffer.wrap(bytes);
|
||||
//write the group ID so the client knows which group this is
|
||||
current.put((byte)group.getID());
|
||||
UCore.log(" Writing new packet: " + i);
|
||||
}
|
||||
|
||||
SyncEntity entity = (SyncEntity) group.all().get(i);
|
||||
UCore.log("Writing entity: " + entity.id);
|
||||
|
||||
//write ID to the buffer
|
||||
current.putInt(entity.id);
|
||||
|
||||
int previous = current.position();
|
||||
//write extra data to the buffer
|
||||
entity.write(current);
|
||||
|
||||
written ++;
|
||||
|
||||
//if the packet is too big now...
|
||||
if(written >= maxsize){
|
||||
//send the packet.
|
||||
SyncPacket packet = new SyncPacket();
|
||||
packet.data = current.array();
|
||||
Net.send(packet, SendMode.udp);
|
||||
|
||||
//reset data, send the next packet
|
||||
current = null;
|
||||
written = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//make sure to send incomplete packets too
|
||||
if(current != null){
|
||||
SyncPacket packet = new SyncPacket();
|
||||
packet.data = current.array();
|
||||
Net.send(packet, SendMode.udp);
|
||||
}
|
||||
}
|
||||
|
||||
packet.enemyStart = index;
|
||||
|
||||
for(Enemy enemy : Vars.control.enemyGroup.all()){
|
||||
float[] out = enemy.getInterpolator().type.write(enemy);
|
||||
packet.data[index] = out;
|
||||
packet.ids[index] = enemy.id;
|
||||
|
||||
index ++;
|
||||
}
|
||||
|
||||
Net.send(packet, SendMode.udp);
|
||||
}
|
||||
|
||||
if(Timers.get("serverItemSync", itemSyncTime)){
|
||||
|
|
|
|||
|
|
@ -100,15 +100,8 @@ public class Renderer extends RendererModule{
|
|||
clearScreen();
|
||||
}else{
|
||||
boolean smoothcam = Settings.getBool("smoothcam");
|
||||
|
||||
//TODO identify the source of this bug
|
||||
if(control.core == null){
|
||||
// ui.showError("$text.error.crashmessage");
|
||||
// GameState.set(State.menu);
|
||||
// return;
|
||||
}
|
||||
|
||||
if(control.core.block() == ProductionBlocks.core){
|
||||
if(control.core == null || control.core.block() == ProductionBlocks.core){
|
||||
if(!smoothcam){
|
||||
setCamera(player.x, player.y);
|
||||
}else{
|
||||
|
|
|
|||
|
|
@ -2,20 +2,20 @@ package io.anuke.mindustry.entities;
|
|||
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.graphics.Fx;
|
||||
import io.anuke.mindustry.net.Syncable;
|
||||
import io.anuke.mindustry.resource.Mech;
|
||||
import io.anuke.mindustry.resource.Weapon;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.Blocks;
|
||||
import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.entities.DestructibleEntity;
|
||||
import io.anuke.ucore.entities.SolidEntity;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class Player extends DestructibleEntity implements Syncable{
|
||||
public class Player extends SyncEntity{
|
||||
static final float speed = 1.1f;
|
||||
static final float dashSpeed = 1.8f;
|
||||
|
||||
|
|
@ -33,7 +33,6 @@ public class Player extends DestructibleEntity implements Syncable{
|
|||
|
||||
public transient int clientid;
|
||||
public transient boolean isLocal = false;
|
||||
public transient Interpolator<Player> inter = new Interpolator<>(SyncType.player);
|
||||
|
||||
public Player(){
|
||||
hitbox.setSize(5);
|
||||
|
|
@ -43,11 +42,6 @@ public class Player extends DestructibleEntity implements Syncable{
|
|||
heal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interpolator<Player> getInterpolator() {
|
||||
return inter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage(int amount){
|
||||
if(!Vars.debug && !isAndroid)
|
||||
|
|
@ -117,7 +111,7 @@ public class Player extends DestructibleEntity implements Syncable{
|
|||
@Override
|
||||
public void update(){
|
||||
if(!isLocal || isAndroid || Vars.ui.chatfrag.chatOpen()){
|
||||
if(!isDead() && !isLocal) inter.update(this);
|
||||
if(!isDead() && !isLocal) interpolate();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -186,4 +180,49 @@ public class Player extends DestructibleEntity implements Syncable{
|
|||
public String toString() {
|
||||
return "Player{" + id + ", android=" + isAndroid + ", local=" + isLocal + ", " + x + ", " + y + "}\n";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuffer data) {
|
||||
data.putFloat(x);
|
||||
data.putFloat(y);
|
||||
data.putFloat(angle);
|
||||
data.putShort((short)health);
|
||||
data.put((byte)(dashing ? 1 : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ByteBuffer data) {
|
||||
float x = data.getFloat();
|
||||
float y = data.getFloat();
|
||||
float angle = data.getFloat();
|
||||
short health = data.getShort();
|
||||
byte dashing = data.get();
|
||||
|
||||
interpolator.target.set(x, y);
|
||||
interpolator.targetrot = angle;
|
||||
this.health = health;
|
||||
this.dashing = dashing == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate() {
|
||||
Interpolator i = interpolator;
|
||||
if(i.target.dst(x, y) > 16 && !isAndroid){
|
||||
set(i.target.x, i.target.y);
|
||||
}
|
||||
|
||||
if(isAndroid && i.target.dst(x, y) > 2f && Timers.get(this, "dashfx", 2)){
|
||||
Angles.translation(angle + 180, 3f);
|
||||
Effects.effect(Fx.dashsmoke, x + Angles.x(), y + Angles.y());
|
||||
}
|
||||
|
||||
if(dashing && Timers.get(this, "dashfx", 3)){
|
||||
Angles.translation(angle + 180, 3f);
|
||||
Effects.effect(Fx.dashsmoke, x + Angles.x(), y + Angles.y());
|
||||
}
|
||||
|
||||
x = Mathf.lerpDelta(x, i.target.x, 0.4f);
|
||||
y = Mathf.lerpDelta(y, i.target.y, 0.4f);
|
||||
angle = Mathf.lerpAngDelta(angle, i.targetrot, 0.6f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
46
core/src/io/anuke/mindustry/entities/SyncEntity.java
Normal file
46
core/src/io/anuke/mindustry/entities/SyncEntity.java
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package io.anuke.mindustry.entities;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.ObjectIntMap;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.ucore.entities.DestructibleEntity;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public abstract class SyncEntity extends DestructibleEntity{
|
||||
private static ObjectIntMap<Class<? extends SyncEntity>> writeSizes = new ObjectIntMap<>();
|
||||
|
||||
public transient Interpolator interpolator = new Interpolator();
|
||||
|
||||
static{
|
||||
setWriteSize(Enemy.class, 4 + 4 + 2 + 2);
|
||||
setWriteSize(Player.class, 4 + 4 + 4 + 2 + 1);
|
||||
}
|
||||
|
||||
public abstract void write(ByteBuffer data);
|
||||
|
||||
public abstract void read(ByteBuffer data);
|
||||
|
||||
public abstract void interpolate();
|
||||
|
||||
public int getWriteSize(){
|
||||
return getWriteSize(getClass());
|
||||
}
|
||||
|
||||
public static int getWriteSize(Class<? extends SyncEntity> type){
|
||||
int i = writeSizes.get(type, -1);
|
||||
if(i == -1) throw new RuntimeException("Write size for class \"" + type + "\" is not defined!");
|
||||
return i;
|
||||
}
|
||||
|
||||
protected static void setWriteSize(Class<? extends SyncEntity> type, int size){
|
||||
writeSizes.put(type, size);
|
||||
}
|
||||
|
||||
public class Interpolator {
|
||||
public Vector2 target = new Vector2();
|
||||
public Vector2 delta = new Vector2();
|
||||
public Vector2 last = new Vector2();
|
||||
public float targetrot;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,17 +4,17 @@ import com.badlogic.gdx.math.Vector2;
|
|||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.entities.Bullet;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.SyncEntity;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.Syncable;
|
||||
import io.anuke.ucore.entities.DestructibleEntity;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.entities.SolidEntity;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Timer;
|
||||
|
||||
public class Enemy extends DestructibleEntity implements Syncable{
|
||||
protected Interpolator<Enemy> inter = new Interpolator<>(SyncType.enemy);
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class Enemy extends SyncEntity {
|
||||
public final EnemyType type;
|
||||
|
||||
public Timer timer = new Timer(5);
|
||||
|
|
@ -92,8 +92,36 @@ public class Enemy extends DestructibleEntity implements Syncable{
|
|||
}
|
||||
|
||||
@Override
|
||||
public Interpolator<Enemy> getInterpolator() {
|
||||
return inter;
|
||||
public void write(ByteBuffer data) {
|
||||
data.putFloat(x);
|
||||
data.putFloat(y);
|
||||
data.putShort((short)(angle*2));
|
||||
data.putShort((short)health);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ByteBuffer data) {
|
||||
|
||||
float x = data.getFloat();
|
||||
float y = data.getFloat();
|
||||
short angle = data.getShort();
|
||||
short health = data.getShort();
|
||||
|
||||
interpolator.target.set(x, y);
|
||||
interpolator.targetrot = angle/2f;
|
||||
this.health = health;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate() {
|
||||
Interpolator i = interpolator;
|
||||
if(i.target.dst(x, y) > 16){
|
||||
set(i.target.x, i.target.y);
|
||||
}
|
||||
|
||||
x = Mathf.lerpDelta(x, i.target.x, 0.4f);
|
||||
y = Mathf.lerpDelta(y, i.target.y, 0.4f);
|
||||
angle = Mathf.lerpAngDelta(angle, i.targetrot, 0.6f);
|
||||
}
|
||||
|
||||
public void shoot(BulletType bullet){
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ public class EnemyType {
|
|||
float range = this.range + enemy.tier * 5;
|
||||
|
||||
if(Net.client() && Net.active()){
|
||||
enemy.inter.update(enemy); //TODO? better structure for interpolation
|
||||
enemy.interpolate(); //TODO? better structure for interpolation
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,7 @@ public class Packets {
|
|||
}
|
||||
|
||||
public static class SyncPacket{
|
||||
public int[] ids;
|
||||
public float[][] data;
|
||||
public short enemyStart;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
public static class BlockSyncPacket extends Streamable{
|
||||
|
|
@ -48,7 +46,7 @@ public class Packets {
|
|||
}
|
||||
|
||||
public static class PositionPacket{
|
||||
public float[] data;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
public static class EffectPacket{
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
package io.anuke.mindustry.net;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.graphics.Fx;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
//TODO clean up this mess
|
||||
public interface Syncable {
|
||||
|
||||
public Interpolator<?> getInterpolator();
|
||||
|
||||
public abstract class SyncType<T extends Entity>{
|
||||
public abstract float[] write(T entity);
|
||||
public abstract void read(T entity, float[] data);
|
||||
public abstract void update(T entity, Interpolator interpolator);
|
||||
|
||||
//TODO write dashing state so particles appear
|
||||
public static final SyncType<Player> player = new SyncType<Player>() {
|
||||
@Override
|
||||
public float[] write(Player entity) {
|
||||
return new float[]{entity.x, entity.y, entity.angle, entity.health, entity.dashing ? 1f : -1f};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Player entity, float[] data) {
|
||||
entity.getInterpolator().target.set(data[0], data[1]);
|
||||
entity.getInterpolator().targetrot = data[2];
|
||||
entity.health = (int)data[3];
|
||||
entity.dashing = data[4] > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Player entity, Interpolator interpolator) {
|
||||
Interpolator i = entity.getInterpolator();
|
||||
if(i.target.dst(entity.x, entity.y) > 16 && !entity.isAndroid){
|
||||
entity.set(i.target.x, i.target.y);
|
||||
}
|
||||
|
||||
if(entity.isAndroid && i.target.dst(entity.x, entity.y) > 2f && Timers.get(entity, "dashfx", 2)){
|
||||
Angles.translation(entity.angle + 180, 3f);
|
||||
Effects.effect(Fx.dashsmoke, entity.x + Angles.x(), entity.y + Angles.y());
|
||||
}
|
||||
|
||||
if(entity.dashing && Timers.get(entity, "dashfx", 3)){
|
||||
Angles.translation(entity.angle + 180, 3f);
|
||||
Effects.effect(Fx.dashsmoke, entity.x + Angles.x(), entity.y + Angles.y());
|
||||
}
|
||||
|
||||
entity.x = Mathf.lerpDelta(entity.x, i.target.x, 0.4f);
|
||||
entity.y = Mathf.lerpDelta(entity.y, i.target.y, 0.4f);
|
||||
entity.angle = Mathf.lerpAngDelta(entity.angle, i.targetrot, 0.6f);
|
||||
}
|
||||
};
|
||||
|
||||
public static final SyncType<Enemy> enemy = new SyncType<Enemy>() {
|
||||
@Override
|
||||
public float[] write(Enemy entity) {
|
||||
return new float[]{entity.x, entity.y, entity.angle, entity.health};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Enemy entity, float[] data) {
|
||||
entity.getInterpolator().target.set(data[0], data[1]);
|
||||
entity.getInterpolator().targetrot = data[2];
|
||||
entity.health = (int)data[3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Enemy entity, Interpolator interpolator) {
|
||||
Interpolator i = entity.getInterpolator();
|
||||
if(i.target.dst(entity.x, entity.y) > 16){
|
||||
entity.set(i.target.x, i.target.y);
|
||||
}
|
||||
|
||||
entity.x = Mathf.lerpDelta(entity.x, i.target.x, 0.4f);
|
||||
entity.y = Mathf.lerpDelta(entity.y, i.target.y, 0.4f);
|
||||
entity.angle = Mathf.lerpAngDelta(entity.angle, i.targetrot, 0.6f);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class Interpolator<T extends Entity> {
|
||||
public SyncType<T> type;
|
||||
public Vector2 target = new Vector2();
|
||||
public Vector2 last = new Vector2();
|
||||
public float targetrot;
|
||||
|
||||
public Interpolator(SyncType<T> type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void update(T entity){
|
||||
this.type.update(entity, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package io.anuke.mindustry.world;
|
|||
import com.badlogic.gdx.utils.IntMap;
|
||||
import com.badlogic.gdx.utils.ObjectIntMap;
|
||||
import io.anuke.mindustry.world.blocks.*;
|
||||
import io.anuke.ucore.UCore;
|
||||
|
||||
public class BlockLoader {
|
||||
static final ObjectIntMap<String> defaultMap = map(
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public class KryoClient implements ClientProvider{
|
|||
}
|
||||
};
|
||||
|
||||
client = new Client(8192, 2048*2);
|
||||
client = new Client(8192, 2048);
|
||||
client.setDiscoveryHandler(handler);
|
||||
|
||||
Listener listener = new Listener(){
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import java.net.InetAddress;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
public class KryoRegistrator {
|
||||
public static boolean fakeLag = true;
|
||||
public static boolean fakeLag = false;
|
||||
public static final int fakeLagAmount = 500;
|
||||
|
||||
public static void register(Kryo kryo){
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public class KryoServer implements ServerProvider {
|
|||
IntArray connections = new IntArray();
|
||||
|
||||
public KryoServer(){
|
||||
server = new Server(4096*2, 2048*2); //TODO tweak
|
||||
server = new Server(4096*2, 2048); //TODO tweak
|
||||
server.setDiscoveryHandler((datagramChannel, fromAddress) -> {
|
||||
ByteBuffer buffer = KryoRegistrator.writeServerData();
|
||||
UCore.log("Replying to discover request with buffer of size " + buffer.capacity());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue