More multiplayer setup, possible android support

This commit is contained in:
Anuken
2017-12-31 22:06:18 -05:00
parent 701c7f6e78
commit 62ae6dc159
13 changed files with 354 additions and 206 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -221,9 +221,8 @@ public class Control extends Module{
wavetime = waveSpacing(); wavetime = waveSpacing();
Entities.clear(); Entities.clear();
enemies = 0; enemies = 0;
if(!android) player.add();
player.add();
player.heal(); player.heal();
clearItems(); clearItems();

View File

@@ -100,8 +100,12 @@ public class NetClient extends Module {
entity = Vars.control.playerGroup.getByID(id); entity = Vars.control.playerGroup.getByID(id);
} }
Syncable sync = ((Syncable)entity);
if(sync == null) continue;
//augh //augh
((Interpolator)((Syncable)entity).getInterpolator()).type.read(entity, packet.data[i]); ((Interpolator)sync.getInterpolator()).type.read(entity, packet.data[i]);
} }
} }
}); });
@@ -151,8 +155,10 @@ public class NetClient extends Module {
}); });
Net.handle(EnemyDeathPacket.class, spawn -> { Net.handle(EnemyDeathPacket.class, spawn -> {
Enemy enemy = Vars.control.enemyGroup.getByID(spawn.id); Gdx.app.postRunnable(() -> {
if(enemy != null) enemy.onDeath(); Enemy enemy = Vars.control.enemyGroup.getByID(spawn.id);
if (enemy != null) enemy.onDeath();
});
}); });
Net.handle(PathPacket.class, packet -> { Net.handle(PathPacket.class, packet -> {
@@ -170,6 +176,24 @@ public class NetClient extends Module {
Entity owner = Vars.control.enemyGroup.getByID(packet.owner); Entity owner = Vars.control.enemyGroup.getByID(packet.owner);
Bullet bullet = new Bullet(type, owner, packet.x, packet.y, packet.angle).add(); Bullet bullet = new Bullet(type, owner, packet.x, packet.y, packet.angle).add();
}); });
Net.handle(BlockDestroyPacket.class, packet -> {
Tile tile = Vars.world.tile(packet.position % Vars.world.width(), packet.position / Vars.world.width());
if(tile.entity != null){
tile.entity.onDeath(true);
}
});
Net.handle(BlockUpdatePacket.class, packet -> {
Tile tile = Vars.world.tile(packet.position % Vars.world.width(), packet.position / Vars.world.width());
if(tile.entity != null){
tile.entity.health = packet.health;
}
});
Net.handle(BlockSyncPacket.class, packet -> {
//TODO implementation, load data...
});
} }
public void update(){ public void update(){

View File

@@ -2,11 +2,13 @@ package io.anuke.mindustry.core;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntMap;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.io.NetworkIO; import io.anuke.mindustry.io.NetworkIO;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
@@ -22,10 +24,12 @@ import io.anuke.ucore.core.Effects.Effect;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.modules.Module; import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.Mathf;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
public class NetServer extends Module{ public class NetServer extends Module{
@@ -66,7 +70,6 @@ public class NetServer extends Module{
UCore.log("Sending entities: " + Arrays.toString(dp.players)); UCore.log("Sending entities: " + Arrays.toString(dp.players));
//TODO send pathfind positions //TODO send pathfind positions
//TODO new denser format
//TODO save enemy nodes //TODO save enemy nodes
Net.sendTo(packet.id, dp, SendMode.tcp); Net.sendTo(packet.id, dp, SendMode.tcp);
@@ -166,6 +169,19 @@ public class NetServer extends Module{
Net.send(packet, SendMode.tcp); Net.send(packet, SendMode.tcp);
} }
public void handleBlockDestroyed(TileEntity entity){
BlockDestroyPacket packet = new BlockDestroyPacket();
packet.position = entity.tile.packedPosition();
Net.send(packet, SendMode.tcp);
}
public void handleBlockDamaged(TileEntity entity){
BlockUpdatePacket packet = new BlockUpdatePacket();
packet.health = entity.health;
packet.position = entity.tile.packedPosition();
Net.send(packet, SendMode.udp);
}
public void update(){ public void update(){
if(!Net.server()) return; if(!Net.server()) return;
@@ -220,18 +236,59 @@ public class NetServer extends Module{
if(Timers.get("serverBlockSync", blockSyncTime)){ if(Timers.get("serverBlockSync", blockSyncTime)){
BlockSyncPacket packet = new BlockSyncPacket(); BlockSyncPacket packet = new BlockSyncPacket();
//TODO IntArray connections = Net.getConnections();
for(int i = 0; i < connections.size; i ++){
int id = connections.get(i);
Player player = this.connections.get(i);
int x = Mathf.scl2(player.x, Vars.tilesize);
int y = Mathf.scl2(player.y, Vars.tilesize);
}
//TODO sync to each player entity
} }
} }
public void sendBlockSync(int client){ public void sendBlockSync(int client, int x, int y, int viewx, int viewy){
BlockSyncPacket packet = new BlockSyncPacket(); BlockSyncPacket packet = new BlockSyncPacket();
ByteArrayOutputStream bs = new ByteArrayOutputStream(); ByteArrayOutputStream bs = new ByteArrayOutputStream();
DataOutputStream stream = new DataOutputStream(bs);
//TODO try {
DataOutputStream stream = new DataOutputStream(bs);
for (int rx = -viewx / 2; rx <= viewx / 2; rx++) {
for (int ry = -viewy / 2; ry <= viewy / 2; ry++) {
Tile tile = Vars.world.tile(x + rx, y + ry);
if (tile == null || tile.entity == null) continue;
stream.writeInt(tile.packedPosition());
byte times = 0;
for(; times < tile.entity.timer.getTimes().length; times ++){
if(tile.entity.timer.getTimes()[times] > 0){
break;
}
}
stream.writeByte(times);
for(int i = 0; i < times; i ++){
stream.writeFloat(tile.entity.timer.getTimes()[times]);
}
tile.entity.write(stream);
}
}
}catch (IOException e){
throw new RuntimeException(e);
}
//TODO finish
packet.stream = new ByteArrayInputStream(bs.toByteArray()); packet.stream = new ByteArrayInputStream(bs.toByteArray());
Net.sendStream(client, packet);
} }
} }

View File

@@ -79,20 +79,22 @@ public class Player extends DestructibleEntity implements Syncable{
@Override @Override
public void draw(){ public void draw(){
if(Vars.debug && (!Vars.showPlayer || !Vars.showUI)) return; if((Vars.debug && (!Vars.showPlayer || !Vars.showUI)) || (Vars.android && isLocal)) return;
String part = Vars.android ? "ship" : "mech";
if(Vars.snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){ if(Vars.snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){
Draw.rect("mech-"+mech.name(), (int)x, (int)y, angle-90); Draw.rect(part+"-"+mech.name(), (int)x, (int)y, angle-90);
}else{ }else{
Draw.rect("mech-"+mech.name(), x, y, angle-90); Draw.rect(part+"-"+mech.name(), x, y, angle-90);
} }
} }
@Override @Override
public void update(){ public void update(){
if(!isLocal){ if(!isLocal || android){
if(!isDead()) inter.update(this); if(!isDead() && !isLocal) inter.update(this);
return; return;
} }

View File

@@ -1,12 +1,9 @@
package io.anuke.mindustry.entities; package io.anuke.mindustry.entities;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
@@ -18,6 +15,10 @@ import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Timer; import io.anuke.ucore.util.Timer;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class TileEntity extends Entity{ public class TileEntity extends Entity{
public Tile tile; public Tile tile;
public int[] items = new int[Item.getAllItems().size]; public int[] items = new int[Item.getAllItems().size];
@@ -54,19 +55,28 @@ public class TileEntity extends Entity{
} }
public void onDeath(){ public void onDeath(){
onDeath(false);
if(tile.block() == ProductionBlocks.core){ }
Vars.control.coreDestroyed();
public void onDeath(boolean force){
if(Net.active() && Net.server()){
Vars.netServer.handleBlockDestroyed(this);
} }
if(!dead) { if(!Net.active() || Net.server() || force){
dead = true; if(tile.block() == ProductionBlocks.core){
Block block = tile.block(); Vars.control.coreDestroyed();
}
block.onDestroyed(tile); if(!dead) {
dead = true;
Block block = tile.block();
Vars.world.removeBlock(tile); block.onDestroyed(tile);
remove();
Vars.world.removeBlock(tile);
remove();
}
} }
} }
@@ -80,6 +90,10 @@ public class TileEntity extends Entity{
int amount = tile.block().handleDamage(tile, damage); int amount = tile.block().handleDamage(tile, damage);
health -= amount; health -= amount;
if(health <= 0) onDeath(); if(health <= 0) onDeath();
if(Net.active() && Net.server()){
Vars.netServer.handleBlockDamaged(this);
}
} }
public boolean collide(Bullet other){ public boolean collide(Bullet other){

View File

@@ -1,15 +1,15 @@
package io.anuke.mindustry.input; package io.anuke.mindustry.input;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.input.GestureDetector.GestureAdapter; import com.badlogic.gdx.input.GestureDetector.GestureAdapter;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Inputs; import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
public class GestureHandler extends GestureAdapter{ public class GestureHandler extends GestureAdapter{
AndroidInput input; AndroidInput input;
@@ -49,8 +49,10 @@ public class GestureHandler extends GestureAdapter{
if(!Vars.control.showCursor() && !(player.recipe != null && Vars.control.hasItems(player.recipe.requirements) && player.placeMode.lockCamera) && if(!Vars.control.showCursor() && !(player.recipe != null && Vars.control.hasItems(player.recipe.requirements) && player.placeMode.lockCamera) &&
!(player.recipe == null && player.breakMode.lockCamera)){ !(player.recipe == null && player.breakMode.lockCamera)){
player.x -= deltaX*Core.camera.zoom/Core.cameraScale; float dx = deltaX*Core.camera.zoom/Core.cameraScale, dy = deltaY*Core.camera.zoom/Core.cameraScale;
player.y += deltaY*Core.camera.zoom/Core.cameraScale; player.x -= dx;
player.y += dy;
player.angle = Mathf.lerpAngDelta(player.angle, Mathf.atan2(dx, dy), 0.5f);
}else if(player.placeMode.lockCamera && (player.placeMode.pan && player.recipe != null)){ }else if(player.placeMode.lockCamera && (player.placeMode.pan && player.recipe != null)){
input.mousex += deltaX; input.mousex += deltaX;
input.mousey += deltaY; input.mousey += deltaY;

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.net; package io.anuke.mindustry.net;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.net.Streamable.StreamBegin; import io.anuke.mindustry.net.Streamable.StreamBegin;
@@ -48,6 +49,11 @@ public class Net{
server = false; server = false;
active = false; active = false;
} }
/**Returns a list of all connections IDs.*/
public static IntArray getConnections(){
return serverProvider.getConnections();
}
/**Send an object to all connected clients, or to the server if this is a client.*/ /**Send an object to all connected clients, or to the server if this is a client.*/
public static void send(Object object, SendMode mode){ public static void send(Object object, SendMode mode){
@@ -182,6 +188,8 @@ public class Net{
public void sendExcept(int id, Object object, SendMode mode); public void sendExcept(int id, Object object, SendMode mode);
/**Close the server connection.*/ /**Close the server connection.*/
public void close(); public void close();
/**Return all connected users.*/
public IntArray getConnections();
/**Register classes to be sent.*/ /**Register classes to be sent.*/
public void register(Class<?>... types); public void register(Class<?>... types);
} }

View File

@@ -96,6 +96,6 @@ public class Packets {
} }
public static class BlockUpdatePacket{ public static class BlockUpdatePacket{
public int health; public int health, position;
} }
} }

View File

@@ -29,6 +29,8 @@ public class Registrator {
PathPacket.class, PathPacket.class,
BulletPacket.class, BulletPacket.class,
EnemyDeathPacket.class, EnemyDeathPacket.class,
BlockUpdatePacket.class,
BlockDestroyPacket.class,
Class.class, Class.class,
byte[].class, byte[].class,

View File

@@ -1,9 +1,14 @@
package io.anuke.mindustry.net; package io.anuke.mindustry.net;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.enemies.Enemy; 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.entities.Entity;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
//TODO clean up this giant mess //TODO clean up this giant mess
@@ -36,6 +41,11 @@ public interface Syncable {
entity.set(i.target.x, i.target.y); entity.set(i.target.x, i.target.y);
} }
if(Vars.android && i.target.dst(entity.x, entity.y) > 2f && 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.x = Mathf.lerpDelta(entity.x, i.target.x, 0.4f);
entity.y = Mathf.lerpDelta(entity.y, i.target.y, 0.4f); entity.y = Mathf.lerpDelta(entity.y, i.target.y, 0.4f);
entity.angle = Mathf.lerpAngDelta(entity.angle, i.targetrot, 0.6f); entity.angle = Mathf.lerpAngDelta(entity.angle, i.targetrot, 0.6f);

View File

@@ -1,8 +1,10 @@
package io.anuke.mindustry.desktop; package io.anuke.mindustry.desktop;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.IntArray;
import com.esotericsoftware.kryonet.*; import com.esotericsoftware.kryonet.*;
import com.esotericsoftware.kryonet.util.InputStreamSender; import com.esotericsoftware.kryonet.util.InputStreamSender;
import com.esotericsoftware.minlog.Log; import com.esotericsoftware.minlog.Log;
@@ -98,7 +100,14 @@ public class DesktopLauncher {
@Override @Override
public void received (Connection connection, Object object) { public void received (Connection connection, Object object) {
if(object instanceof FrameworkMessage) return; if(object instanceof FrameworkMessage) return;
Net.handleClientReceived(object);
try{
Net.handleClientReceived(object);
}catch (Exception e){
Gdx.app.exit();
throw new RuntimeException(e);
}
} }
}); });
@@ -144,6 +153,7 @@ public class DesktopLauncher {
Net.setServerProvider(new ServerProvider() { Net.setServerProvider(new ServerProvider() {
Server server; Server server;
IntArray connections = new IntArray();
{ {
server = new Server(); server = new Server();
@@ -157,6 +167,7 @@ public class DesktopLauncher {
c.id = connection.getID(); c.id = connection.getID();
c.addressTCP = connection.getRemoteAddressTCP().toString(); c.addressTCP = connection.getRemoteAddressTCP().toString();
Net.handleServerReceived(c, c.id); Net.handleServerReceived(c, c.id);
connections.add(c.id);
} }
@Override @Override
@@ -164,18 +175,30 @@ public class DesktopLauncher {
Disconnect c = new Disconnect(); Disconnect c = new Disconnect();
c.id = connection.getID(); c.id = connection.getID();
Net.handleServerReceived(c, c.id); Net.handleServerReceived(c, c.id);
connections.removeValue(c.id);
} }
@Override @Override
public void received (Connection connection, Object object) { public void received (Connection connection, Object object) {
if(object instanceof FrameworkMessage) return; if(object instanceof FrameworkMessage) return;
Net.handleServerReceived(object, connection.getID());
try{
Net.handleServerReceived(object, connection.getID());
}catch (Exception e){
Gdx.app.exit();
throw new RuntimeException(e);
}
} }
}); });
register(Registrator.getClasses()); register(Registrator.getClasses());
} }
@Override
public IntArray getConnections() {
return connections;
}
@Override @Override
public void host(int port) throws IOException { public void host(int port) throws IOException {
server.bind(port, port); server.bind(port, port);