Many editor improvements, lang bugfixes, Syncable entity change

This commit is contained in:
Anuken
2018-01-30 19:57:08 -05:00
parent 4b830a8cf2
commit 9a5ac76850
16 changed files with 206 additions and 317 deletions

View File

@ -22,7 +22,7 @@ allprojects {
appName = "Mindustry"
gdxVersion = '1.9.8'
aiVersion = '1.8.1'
uCoreVersion = '82c0091'
uCoreVersion = 'fe2f2dd'
}
repositories {

View File

@ -3,6 +3,8 @@
<source path="io/anuke/mindustry" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Tile" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.Maps" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.Player" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.types.Enemy" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Map" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.EnemySpawn" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.SaveFileVersion" />

View File

@ -9,18 +9,13 @@ 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;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.SendMode;
import io.anuke.mindustry.net.NetworkIO;
import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.resource.Upgrade;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.BaseBulletType;
import io.anuke.ucore.entities.Entities;
@ -131,6 +126,7 @@ public class NetClient extends Module {
if (id != player.id) {
EntityRequestPacket req = new EntityRequestPacket();
req.id = id;
req.group = groupid;
Net.send(req, SendMode.udp);
}
data.position(data.position() + SyncEntity.getWriteSize((Class<? extends SyncEntity>) group.getType()));
@ -157,25 +153,18 @@ public class NetClient extends Module {
ui.hudfrag.updateItems();
});
Net.handleClient(EnemySpawnPacket.class, spawn -> {
Net.handleClient(EntitySpawnPacket.class, packet -> {
EntityGroup group = packet.group;
//duplicates.
if (enemyGroup.getByID(spawn.id) != null ||
recieved.contains(spawn.id) || dead.contains(spawn.id)) return;
if (group.getByID(packet.entity.id) != null ||
recieved.contains(packet.entity.id) || dead.contains(packet.entity.id)) return;
recieved.add(spawn.id);
recieved.add(packet.entity.id);
Enemy enemy = new Enemy(EnemyType.getByID(spawn.type));
enemy.interpolator.target.set(spawn.x, spawn.y);
enemy.set(spawn.x, spawn.y);
enemy.tier = spawn.tier;
enemy.lane = spawn.lane;
enemy.id = spawn.id;
enemy.health = spawn.health;
enemy.add();
packet.entity.add();
Effects.effect(Fx.spawn, enemy);
Log.info("Recieved enemy {0}", spawn.id);
Log.info("Recieved entity {0}", packet.entity.id);
});
Net.handleClient(EnemyDeathPacket.class, spawn -> {
@ -252,31 +241,6 @@ public class NetClient extends Module {
Platform.instance.updateRPC();
});
Net.handleClient(PlayerSpawnPacket.class, packet -> {
//duplicates.
if (enemyGroup.getByID(packet.id) != null ||
recieved.contains(packet.id)) return;
recieved.add(packet.id);
Player player = new Player();
player.x = packet.x;
player.y = packet.y;
player.isAndroid = packet.android;
player.name = packet.name;
player.id = packet.id;
player.weaponLeft = (Weapon) Upgrade.getByID(packet.weaponleft);
player.weaponRight = (Weapon) Upgrade.getByID(packet.weaponright);
player.interpolator.last.set(player.x, player.y);
player.interpolator.target.set(player.x, player.y);
player.add();
Log.info("Recieved player {0}", packet.id);
Platform.instance.updateRPC();
});
Net.handleClient(KickPacket.class, packet -> {
kicked = true;
Net.disconnect();

View File

@ -1,11 +1,9 @@
package io.anuke.mindustry.core;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.*;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.SendMode;
@ -20,7 +18,6 @@ import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Mathf;
@ -95,18 +92,18 @@ public class NetServer extends Module{
if (player == null) return;
player.add();
netCommon.sendMessage("[accent]" + Bundles.format("text.server.connected", player.name));
netCommon.sendMessage("[accent]" + player.name + " has connected.");
});
Net.handleServer(Disconnect.class, (id, packet) -> {
Player player = connections.get(packet.id);
if (player == null) {
Gdx.app.error("Mindustry", "Unknown client has disconnected (ID=" + id + ")");
Log.err("Unknown client has disconnected (ID={0})", id);
return;
}
netCommon.sendMessage("[accent]" + Bundles.format("text.server.disconnected", player.name));
netCommon.sendMessage("[accent]" + player.name + " has disconnected.");
player.remove();
DisconnectPacket dc = new DisconnectPacket();
@ -171,29 +168,12 @@ public class NetServer extends Module{
Net.handleServer(EntityRequestPacket.class, (cid, packet) -> {
int id = packet.id;
int dest = cid;
if (playerGroup.getByID(id) != null) {
Player player = playerGroup.getByID(id);
PlayerSpawnPacket p = new PlayerSpawnPacket();
p.x = player.x;
p.y = player.y;
p.id = player.id;
p.name = player.name;
p.weaponleft = player.weaponLeft.id;
p.weaponright = player.weaponRight.id;
p.android = player.isAndroid;
EntityGroup group = Entities.getGroup(packet.group);
if(group.getByID(id) != null){
EntitySpawnPacket p = new EntitySpawnPacket();
p.entity = (SyncEntity)group.getByID(id);
Net.sendTo(dest, p, SendMode.tcp);
} else if (enemyGroup.getByID(id) != null) {
Enemy enemy = enemyGroup.getByID(id);
EnemySpawnPacket e = new EnemySpawnPacket();
e.x = enemy.x;
e.y = enemy.y;
e.id = enemy.id;
e.tier = (byte) enemy.tier;
e.lane = (byte) enemy.lane;
e.type = enemy.type.id;
e.health = (short) enemy.health;
Net.sendTo(dest, e, SendMode.tcp);
return;
}
});

View File

@ -7,6 +7,7 @@ import io.anuke.mindustry.graphics.Shaders;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.resource.Mech;
import io.anuke.mindustry.resource.Upgrade;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Blocks;
@ -66,33 +67,29 @@ public class Player extends SyncEntity{
@Override
public void onDeath(){
if(!isLocal) return;
if(isLocal){
remove();
if(Net.active()){
NetEvents.handlePlayerDeath();
}
Effects.effect(Fx.explosion, this);
Effects.shake(4f, 5f, this);
Effects.sound("die", this);
remove();
if(Net.active()){
NetEvents.handlePlayerDeath();
}
//TODO respawning doesn't work properly for multiplayer at all
if(isLocal) {
control.setRespawnTime(respawnduration);
ui.hudfrag.fadeRespawn(true);
}
Effects.effect(Fx.explosion, this);
Effects.shake(4f, 5f, this);
Effects.sound("die", this);
control.setRespawnTime(respawnduration);
ui.hudfrag.fadeRespawn(true);
}
/**called when a remote player death event is recieved*/
public void doRespawn(){
dead = true;
Effects.effect(Fx.explosion, this);
Effects.shake(4f, 5f, this);
Effects.sound("die", this);
set(-9999, -9999);
Timers.run(respawnduration, () -> {
Timers.run(respawnduration + 5f, () -> {
heal();
set(world.getSpawnX(), world.getSpawnY());
});
@ -104,7 +101,7 @@ public class Player extends SyncEntity{
angle = Mathf.lerpAngDelta(angle, targetAngle, 0.2f);
}
if((debug && (!showPlayer || !showUI)) || (isAndroid && isLocal) ) return;
if((debug && (!showPlayer || !showUI)) || (isAndroid && isLocal) || dead) return;
boolean snap = snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate") && isLocal;
String part = isAndroid ? "ship" : "mech";
@ -140,7 +137,7 @@ public class Player extends SyncEntity{
@Override
public void update(){
if(!isLocal || isAndroid || ui.chatfrag.chatOpen()){
if(!isDead() && !isLocal) interpolate();
if(!isLocal) interpolate();
return;
}
@ -214,6 +211,30 @@ public class Player extends SyncEntity{
return "Player{" + id + ", android=" + isAndroid + ", local=" + isLocal + ", " + x + ", " + y + "}\n";
}
@Override
public void writeSpawn(ByteBuffer buffer) {
buffer.put((byte)name.getBytes().length);
buffer.put(name.getBytes());
buffer.put(weaponLeft.id);
buffer.put(weaponRight.id);
buffer.put(isAndroid ? 1 : (byte)0);
buffer.putFloat(x);
buffer.putFloat(y);
}
@Override
public void readSpawn(ByteBuffer buffer) {
byte nlength = buffer.get();
byte[] n = new byte[nlength];
buffer.get(n);
name = new String(n);
weaponLeft = (Weapon) Upgrade.getByID(buffer.get());
weaponRight = (Weapon) Upgrade.getByID(buffer.get());
isAndroid = buffer.get() == 1;
x = buffer.getFloat();
y = buffer.getFloat();
}
@Override
public void write(ByteBuffer data) {
data.putFloat(x);

View File

@ -17,10 +17,11 @@ public abstract class SyncEntity extends DestructibleEntity{
setWriteSize(Player.class, 4 + 4 + 4 + 2 + 1);
}
public abstract void writeSpawn(ByteBuffer data);
public abstract void readSpawn(ByteBuffer data);
public abstract void write(ByteBuffer data);
public abstract void read(ByteBuffer data);
public abstract void interpolate();
public int getWriteSize(){

View File

@ -17,7 +17,7 @@ import java.nio.ByteBuffer;
import static io.anuke.mindustry.Vars.enemyGroup;
public class Enemy extends SyncEntity {
public final EnemyType type;
public EnemyType type;
public Timer timer = new Timer(5);
public float idletime = 0f;
@ -38,6 +38,9 @@ public class Enemy extends SyncEntity {
this.type = type;
}
/**internal constructor used for deserialization, DO NOT USE*/
public Enemy(){}
@Override
public void update(){
type.update(this);
@ -93,6 +96,26 @@ public class Enemy extends SyncEntity {
return add(enemyGroup);
}
@Override
public void writeSpawn(ByteBuffer buffer) {
buffer.put(type.id);
buffer.put((byte)lane);
buffer.put((byte)tier);
buffer.putFloat(x);
buffer.putFloat(y);
buffer.putShort((short)health);
}
@Override
public void readSpawn(ByteBuffer buffer) {
type = EnemyType.getByID(buffer.get());
lane = buffer.get();
tier = buffer.get();
x = buffer.getFloat();
y = buffer.getFloat();
health = buffer.getShort();
}
@Override
public void write(ByteBuffer data) {
data.putFloat(x);

View File

@ -11,6 +11,7 @@ import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.util.Log;
public class MapEditor{
public static final int[] validMapSizes = {128, 256, 512};
@ -103,6 +104,7 @@ public class MapEditor{
}
public void setDrawBlock(Block block){
Log.info("Setting draw block {0}", block);
this.drawBlock = block;
pixmap.setColor(ColorMapper.getColor(block));
}

View File

@ -1,5 +1,6 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
@ -13,9 +14,12 @@ import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.SpecialBlocks;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.builders.build;
import io.anuke.ucore.scene.builders.imagebutton;
import io.anuke.ucore.scene.builders.label;
@ -37,6 +41,7 @@ public class MapEditorDialog extends Dialog{
private MapLoadDialog loadDialog;
private MapSaveDialog saveDialog;
private MapResizeDialog resizeDialog;
private ScrollPane pane;
private FileChooser openFile, saveFile;
private boolean saved = false;
@ -138,6 +143,17 @@ public class MapEditorDialog extends Dialog{
build.begin(this);
build();
build.end();
tapped(() -> {
Element e = getScene().hit(Graphics.mouse().x, Graphics.mouse().y, true);
if(e == null || !e.isDescendantOf(pane)) getScene().setScrollFocus(null);
});
update(() -> {
if(getScene().getKeyboardFocus() == this){
doInput();
}
});
shown(() -> {
saved = true;
@ -146,9 +162,7 @@ public class MapEditorDialog extends Dialog{
Core.scene.setScrollFocus(view);
view.clearStack();
Timers.runTask(3f, () -> {
Platform.instance.updateRPC();
});
Timers.runTask(10f, Platform.instance::updateRPC);
});
hidden(() -> Platform.instance.updateRPC());
@ -173,6 +187,10 @@ public class MapEditorDialog extends Dialog{
i++;
}
}
public boolean hasPane(){
return getScene().getScrollFocus() == pane;
}
public void build(){
@ -247,18 +265,20 @@ public class MapEditorDialog extends Dialog{
ImageButton undo = tools.addImageButton("icon-undo", 16*2f, () -> view.undo()).get();
ImageButton redo = tools.addImageButton("icon-redo", 16*2f, () -> view.redo()).get();
tools.addImageButton("icon-grid", "toggle", 16*2f, () -> view.setGrid(!view.isGrid())).get();
ImageButton grid = tools.addImageButton("icon-grid", "toggle", 16*2f, () -> view.setGrid(!view.isGrid())).get();
undo.setDisabled(() -> !view.getStack().canUndo());
redo.setDisabled(() -> !view.getStack().canRedo());
undo.update(() -> undo.getImage().setColor(undo.isDisabled() ? Color.GRAY : Color.WHITE));
redo.update(() -> redo.getImage().setColor(redo.isDisabled() ? Color.GRAY : Color.WHITE));
grid.update(() -> grid.setChecked(view.isGrid()));
for(EditorTool tool : EditorTool.values()){
ImageButton button = new ImageButton("icon-" + tool.name(), "toggle");
button.clicked(() -> view.setTool(tool));
button.resizeImage(16*2f);
button.update(() -> button.setChecked(view.getTool() == tool));
group.add(button);
if (tool == EditorTool.pencil)
button.setChecked(true);
@ -283,9 +303,8 @@ public class MapEditorDialog extends Dialog{
row();
new table("button"){{
get().addCheck("$text.oregen", b -> {
editor.getMap().oreGen = b;
}).update(c -> c.setChecked(editor.getMap().oreGen)).padTop(3).padBottom(3);
get().addCheck("$text.oregen", b -> editor.getMap().oreGen = b)
.update(c -> c.setChecked(editor.getMap().oreGen)).padTop(3).padBottom(3);
}}.growX().padBottom(-6).end();
row();
@ -297,6 +316,36 @@ public class MapEditorDialog extends Dialog{
}}.right().growY().end();
}}.grow().end();
}
private void doInput(){
//tool select
for(int i = 0; i < EditorTool.values().length; i ++){
int code = i == 0 ? 5 : i;
if(Inputs.keyTap("weapon_" + code)){
view.setTool(EditorTool.values()[i]);
break;
}
}
//ctrl keys (undo, redo, save)
if(Inputs.keyDown(Keys.CONTROL_LEFT)){
if(Inputs.keyTap(Keys.Z)){
view.undo();
}
if(Inputs.keyTap(Keys.Y)){
view.redo();
}
if(Inputs.keyTap(Keys.S)){
saveDialog.save();
}
if(Inputs.keyTap(Keys.G)){
view.setGrid(!view.isGrid());
}
}
}
private boolean verifySize(Pixmap pix){
boolean w = false, h = false;
@ -344,7 +393,7 @@ public class MapEditorDialog extends Dialog{
private void addBlockSelection(Table table){
Table content = new Table();
ScrollPane pane = new ScrollPane(content, "volume");
pane = new ScrollPane(content, "volume");
pane.setScrollingDisabled(true, false);
pane.setFadeScrollBars(false);
pane.setOverscroll(true, false);

View File

@ -1,6 +1,5 @@
package io.anuke.mindustry.mapeditor;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Map;
@ -8,12 +7,16 @@ import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.TextField;
import static io.anuke.mindustry.Vars.*;
public class MapSaveDialog extends FloatingDialog{
private TextField field;
private Consumer<String> listener;
public MapSaveDialog(Consumer<String> cons){
super("$text.editor.savemap");
field = new TextField();
listener = cons;
Platform.instance.addDialog(field);
@ -48,11 +51,18 @@ public class MapSaveDialog extends FloatingDialog{
button.setDisabled(this::invalid);
buttons().add(button);
}
public void save(){
if(!invalid()){
listener.accept(field.getText());
}else{
ui.showError("$text.editor.failoverwrite");
}
}
public void setFieldText(String text){
field.setText(text);
}
private boolean invalid(){
if(field.getText().isEmpty()){

View File

@ -11,13 +11,12 @@ import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
import com.badlogic.gdx.utils.Array;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.ui.GridImage;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.scene.Element;
@ -28,6 +27,8 @@ import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Tmp;
import static io.anuke.mindustry.Vars.ui;
public class MapView extends Element implements GestureListener{
private MapEditor editor;
private EditorTool tool = EditorTool.pencil;
@ -49,6 +50,10 @@ public class MapView extends Element implements GestureListener{
this.tool = tool;
}
public EditorTool getTool() {
return tool;
}
public void clearStack(){
stack.clear();
current = null;
@ -85,7 +90,6 @@ public class MapView extends Element implements GestureListener{
stack.redo();
editor.updateTexture();
}
}
public MapView(MapEditor editor){
@ -171,19 +175,20 @@ public class MapView extends Element implements GestureListener{
@Override
public void act(float delta){
super.act(delta);
float size = Math.min(width, height);
offsetx = Mathf.clamp(offsetx, -size, size);
offsety = Mathf.clamp(offsety, -size, size);
if(tool != EditorTool.zoom) return;
float ax = Inputs.getAxis("move_x");
float ay = Inputs.getAxis("move_y");
offsetx -= ax * 15f / zoom;
offsety -= ay * 15f / zoom;
if(ui.editor.hasPane()) return;
zoom += Inputs.scroll()/10f * zoom;
clampZoom();
}
private void clampZoom(){
zoom = Mathf.clamp(zoom, 0.4f, 6f);
zoom = Mathf.clamp(zoom, 0.4f, 8f);
}
private GridPoint2 project(float x, float y){

View File

@ -1,9 +1,13 @@
package io.anuke.mindustry.net;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import com.badlogic.gdx.utils.reflect.ReflectionException;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.net.Packet.ImportantPacket;
import io.anuke.mindustry.resource.Item;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup;
import java.nio.ByteBuffer;
@ -241,66 +245,29 @@ public class Packets {
}
}
public static class EnemySpawnPacket implements Packet{
public byte type, lane, tier;
public float x, y;
public short health;
public int id;
public static class EntitySpawnPacket implements Packet{
public SyncEntity entity;
public EntityGroup<?> group;
@Override
public void write(ByteBuffer buffer) {
buffer.put(type);
buffer.put(lane);
buffer.put(tier);
buffer.putFloat(x);
buffer.putFloat(y);
buffer.putShort(health);
buffer.putInt(id);
public void write(ByteBuffer buffer){
buffer.put((byte)entity.getGroup().getID());
buffer.putInt(entity.id);
entity.writeSpawn(buffer);
}
@Override
public void read(ByteBuffer buffer) {
type = buffer.get();
lane = buffer.get();
tier = buffer.get();
x = buffer.getFloat();
y = buffer.getFloat();
health = buffer.getShort();
id = buffer.getInt();
}
}
public static class PlayerSpawnPacket implements Packet{
public byte weaponleft, weaponright;
public boolean android;
public String name;
public float x, y;
public int id;
@Override
public void write(ByteBuffer buffer) {
buffer.put((byte)name.getBytes().length);
buffer.put(name.getBytes());
buffer.put(weaponleft);
buffer.put(weaponright);
buffer.put(android ? 1 : (byte)0);
buffer.putFloat(x);
buffer.putFloat(y);
buffer.putInt(id);
}
@Override
public void read(ByteBuffer buffer) {
byte nlength = buffer.get();
byte[] n = new byte[nlength];
buffer.get(n);
name = new String(n);
weaponleft = buffer.get();
weaponright = buffer.get();
android = buffer.get() == 1;
x = buffer.getFloat();
y = buffer.getFloat();
id = buffer.getInt();
byte groupid = buffer.get();
int id = buffer.getInt();
group = Entities.getGroup(groupid);
try {
entity = (SyncEntity) ClassReflection.newInstance(group.getType());
entity.id = id;
entity.readSpawn(buffer);
}catch (ReflectionException e){
throw new RuntimeException(e);
}
}
}
@ -467,15 +434,18 @@ public class Packets {
public static class EntityRequestPacket implements Packet{
public int id;
public byte group;
@Override
public void write(ByteBuffer buffer) {
buffer.putInt(id);
buffer.put(group);
}
@Override
public void read(ByteBuffer buffer) {
id = buffer.getInt();
group = buffer.get();
}
}

View File

@ -18,8 +18,6 @@ public class Registrator {
BreakPacket.class,
StateSyncPacket.class,
BlockSyncPacket.class,
EnemySpawnPacket.class,
PlayerSpawnPacket.class,
BulletPacket.class,
EnemyDeathPacket.class,
BlockUpdatePacket.class,
@ -38,7 +36,8 @@ public class Registrator {
FriendlyFireChangePacket.class,
PlayerDeathPacket.class,
CustomMapPacket.class,
MapAckPacket.class
MapAckPacket.class,
EntitySpawnPacket.class,
};
private static ObjectIntMap<Class<?>> ids = new ObjectIntMap<>();

View File

@ -281,4 +281,9 @@ public class Block{
public static Block getByID(int id){
return blocks.get(id);
}
@Override
public String toString(){
return name;
}
}

View File

@ -1,140 +0,0 @@
package io.anuke.kryonet;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Base64Coder;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.net.Host;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.ClientProvider;
import io.anuke.mindustry.net.Net.SendMode;
import io.anuke.mindustry.net.Packet;
import io.anuke.mindustry.net.Packets.Connect;
import io.anuke.mindustry.net.Packets.Disconnect;
import io.anuke.mindustry.net.Registrator;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.util.Log;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
public class JavaWebsocketClient implements ClientProvider {
WebSocketClient socket;
ByteBuffer buffer = ByteBuffer.allocate(1024);
boolean debug = false;
@Override
public void connect(String ip, int port) throws IOException {
try {
URI i = new URI("ws://" + ip + ":" + Vars.webPort);
Log.info("Connecting: {0}", i);
socket = new WebSocketClient(i, new Draft_6455(), null, 5000) {
Thread thread;
@Override
public void connect() {
if(thread != null )
throw new IllegalStateException( "WebSocketClient objects are not reuseable" );
thread = new Thread(this);
thread.setDaemon(true);
thread.start();
}
@Override
public void onOpen(ServerHandshake handshakedata) {
Log.info("Connected!");
Connect connect = new Connect();
Net.handleClientReceived(connect);
}
@Override
public void onMessage(String message) {
try {
byte[] bytes = Base64Coder.decode(message);
ByteBuffer buffer = ByteBuffer.wrap(bytes);
byte id = buffer.get();
if (id == -2) {
//this is a framework message... do nothing yet?
} else {
Class<?> type = Registrator.getByID(id);
Packet packet = (Packet) ClassReflection.newInstance(type);
packet.read(buffer);
Net.handleClientReceived(packet);
}
} catch (Exception e) {
e.printStackTrace();
//throw new RuntimeException(e);
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
Disconnect disconnect = new Disconnect();
Net.handleClientReceived(disconnect);
}
@Override
public void onError(Exception ex) {
onClose(0, null, true);
ex.printStackTrace();
}
};
socket.connect();
}catch (URISyntaxException e){
throw new IOException(e);
}
}
@Override
public void send(Object object, SendMode mode) {
if(!(object instanceof Packet)) throw new RuntimeException("All sent objects must be packets!");
Packet p = (Packet)object;
buffer.position(0);
buffer.put(Registrator.getID(object.getClass()));
p.write(buffer);
int pos = buffer.position();
buffer.position(0);
byte[] out = new byte[pos];
buffer.get(out);
String string = new String(Base64Coder.encode(out));
socket.send(string);
}
@Override
public void updatePing() {
}
@Override
public int getPing() {
return 0;
}
@Override
public void disconnect() {
socket.close();
}
@Override
public void discover(Consumer<Array<Host>> callback){
callback.accept(new Array<>());
}
@Override
public void pingHost(String address, int port, Consumer<Host> valid, Consumer<IOException> failed) {
failed.accept(new IOException());
}
@Override
public void dispose() {
if(socket != null) socket.close();
for(Thread thread : Thread.getAllStackTraces().keySet()){
if(thread.getName().equals("WebsocketWriteThread")) thread.interrupt();
}
}
}

View File

@ -135,7 +135,7 @@ public class KryoServer implements ServerProvider {
serverThread = new Thread(() -> {
try{
server.run();
}catch (Exception e){
}catch (Throwable e){
if(!(e instanceof ClosedSelectorException)) handleException(e);
}
}, "Kryonet Server");
@ -273,7 +273,7 @@ public class KryoServer implements ServerProvider {
Log.info("Disposed server.");
}
private void handleException(Exception e){
private void handleException(Throwable e){
Gdx.app.postRunnable(() -> { throw new RuntimeException(e);});
}
@ -435,9 +435,7 @@ public class KryoServer implements ServerProvider {
}
@Override
public void onStart() {
Log.info("Web server started.");
}
public void onStart() {}
}
}