diff --git a/build.gradle b/build.gradle index a98d53020a..56ace01894 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ allprojects { appName = "Mindustry" gdxVersion = '1.9.8' aiVersion = '1.8.1' - uCoreVersion = '82c0091' + uCoreVersion = 'fe2f2dd' } repositories { diff --git a/core/src/Mindustry.gwt.xml b/core/src/Mindustry.gwt.xml index 68c562e7dd..724be5ba0b 100644 --- a/core/src/Mindustry.gwt.xml +++ b/core/src/Mindustry.gwt.xml @@ -3,6 +3,8 @@ + + diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 5a1e39f8d5..1b5b3d3e6b 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -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) 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(); diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 7cb22ce63b..0546d85e56 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -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; } }); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index bc90107ee6..328dfee9de 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -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); diff --git a/core/src/io/anuke/mindustry/entities/SyncEntity.java b/core/src/io/anuke/mindustry/entities/SyncEntity.java index 580c9c11ee..3d8bddb678 100644 --- a/core/src/io/anuke/mindustry/entities/SyncEntity.java +++ b/core/src/io/anuke/mindustry/entities/SyncEntity.java @@ -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(){ diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index 88cd9559ce..ace3028e68 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -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); diff --git a/core/src/io/anuke/mindustry/mapeditor/MapEditor.java b/core/src/io/anuke/mindustry/mapeditor/MapEditor.java index bf424a81b8..3e50e435cd 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapEditor.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapEditor.java @@ -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)); } diff --git a/core/src/io/anuke/mindustry/mapeditor/MapEditorDialog.java b/core/src/io/anuke/mindustry/mapeditor/MapEditorDialog.java index 029fc79a67..d00ef09d1c 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapEditorDialog.java @@ -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); diff --git a/core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java b/core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java index 967917e5d7..3090325975 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java @@ -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 listener; public MapSaveDialog(Consumer 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()){ diff --git a/core/src/io/anuke/mindustry/mapeditor/MapView.java b/core/src/io/anuke/mindustry/mapeditor/MapView.java index 14e065d2d0..8bb018b4e3 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapView.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapView.java @@ -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){ diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 079d34ba9e..7c5f8e7223 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -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(); } } diff --git a/core/src/io/anuke/mindustry/net/Registrator.java b/core/src/io/anuke/mindustry/net/Registrator.java index 3697588e7a..9f4d197bb1 100644 --- a/core/src/io/anuke/mindustry/net/Registrator.java +++ b/core/src/io/anuke/mindustry/net/Registrator.java @@ -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> ids = new ObjectIntMap<>(); diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index ee6d92dcbd..e1c66283ef 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -281,4 +281,9 @@ public class Block{ public static Block getByID(int id){ return blocks.get(id); } + + @Override + public String toString(){ + return name; + } } diff --git a/kryonet/src/io/anuke/kryonet/JavaWebsocketClient.java b/kryonet/src/io/anuke/kryonet/JavaWebsocketClient.java deleted file mode 100644 index cafb859967..0000000000 --- a/kryonet/src/io/anuke/kryonet/JavaWebsocketClient.java +++ /dev/null @@ -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> callback){ - callback.accept(new Array<>()); - } - - @Override - public void pingHost(String address, int port, Consumer valid, Consumer 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(); - } - } -} diff --git a/kryonet/src/io/anuke/kryonet/KryoServer.java b/kryonet/src/io/anuke/kryonet/KryoServer.java index 3592e7d1c8..e1bdfe1ab8 100644 --- a/kryonet/src/io/anuke/kryonet/KryoServer.java +++ b/kryonet/src/io/anuke/kryonet/KryoServer.java @@ -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() {} } }