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" appName = "Mindustry"
gdxVersion = '1.9.8' gdxVersion = '1.9.8'
aiVersion = '1.8.1' aiVersion = '1.8.1'
uCoreVersion = '82c0091' uCoreVersion = 'fe2f2dd'
} }
repositories { repositories {

View File

@ -3,6 +3,8 @@
<source path="io/anuke/mindustry" /> <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.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.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.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.game.EnemySpawn" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.SaveFileVersion" /> <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.Player;
import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.entities.enemies.Enemy; 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.io.Platform;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Net.SendMode;
import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.NetworkIO;
import io.anuke.mindustry.net.Packets.*; 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.Map;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.BaseBulletType; import io.anuke.ucore.entities.BaseBulletType;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
@ -131,6 +126,7 @@ public class NetClient extends Module {
if (id != player.id) { if (id != player.id) {
EntityRequestPacket req = new EntityRequestPacket(); EntityRequestPacket req = new EntityRequestPacket();
req.id = id; req.id = id;
req.group = groupid;
Net.send(req, SendMode.udp); Net.send(req, SendMode.udp);
} }
data.position(data.position() + SyncEntity.getWriteSize((Class<? extends SyncEntity>) group.getType())); data.position(data.position() + SyncEntity.getWriteSize((Class<? extends SyncEntity>) group.getType()));
@ -157,25 +153,18 @@ public class NetClient extends Module {
ui.hudfrag.updateItems(); ui.hudfrag.updateItems();
}); });
Net.handleClient(EnemySpawnPacket.class, spawn -> { Net.handleClient(EntitySpawnPacket.class, packet -> {
EntityGroup group = packet.group;
//duplicates. //duplicates.
if (enemyGroup.getByID(spawn.id) != null || if (group.getByID(packet.entity.id) != null ||
recieved.contains(spawn.id) || dead.contains(spawn.id)) return; 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)); packet.entity.add();
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();
Effects.effect(Fx.spawn, enemy); Log.info("Recieved entity {0}", packet.entity.id);
Log.info("Recieved enemy {0}", spawn.id);
}); });
Net.handleClient(EnemyDeathPacket.class, spawn -> { Net.handleClient(EnemyDeathPacket.class, spawn -> {
@ -252,31 +241,6 @@ public class NetClient extends Module {
Platform.instance.updateRPC(); 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 -> { Net.handleClient(KickPacket.class, packet -> {
kicked = true; kicked = true;
Net.disconnect(); Net.disconnect();

View File

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

View File

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

View File

@ -17,10 +17,11 @@ public abstract class SyncEntity extends DestructibleEntity{
setWriteSize(Player.class, 4 + 4 + 4 + 2 + 1); 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 write(ByteBuffer data);
public abstract void read(ByteBuffer data); public abstract void read(ByteBuffer data);
public abstract void interpolate(); public abstract void interpolate();
public int getWriteSize(){ public int getWriteSize(){

View File

@ -17,7 +17,7 @@ import java.nio.ByteBuffer;
import static io.anuke.mindustry.Vars.enemyGroup; import static io.anuke.mindustry.Vars.enemyGroup;
public class Enemy extends SyncEntity { public class Enemy extends SyncEntity {
public final EnemyType type; public EnemyType type;
public Timer timer = new Timer(5); public Timer timer = new Timer(5);
public float idletime = 0f; public float idletime = 0f;
@ -38,6 +38,9 @@ public class Enemy extends SyncEntity {
this.type = type; this.type = type;
} }
/**internal constructor used for deserialization, DO NOT USE*/
public Enemy(){}
@Override @Override
public void update(){ public void update(){
type.update(this); type.update(this);
@ -93,6 +96,26 @@ public class Enemy extends SyncEntity {
return add(enemyGroup); 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 @Override
public void write(ByteBuffer data) { public void write(ByteBuffer data) {
data.putFloat(x); 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.Map;
import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.graphics.Pixmaps; import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.util.Log;
public class MapEditor{ public class MapEditor{
public static final int[] validMapSizes = {128, 256, 512}; public static final int[] validMapSizes = {128, 256, 512};
@ -103,6 +104,7 @@ public class MapEditor{
} }
public void setDrawBlock(Block block){ public void setDrawBlock(Block block){
Log.info("Setting draw block {0}", block);
this.drawBlock = block; this.drawBlock = block;
pixmap.setColor(ColorMapper.getColor(block)); pixmap.setColor(ColorMapper.getColor(block));
} }

View File

@ -1,5 +1,6 @@
package io.anuke.mindustry.mapeditor; package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap; 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.Blocks;
import io.anuke.mindustry.world.blocks.SpecialBlocks; import io.anuke.mindustry.world.blocks.SpecialBlocks;
import io.anuke.ucore.core.Core; 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.core.Timers;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Pixmaps; 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.build;
import io.anuke.ucore.scene.builders.imagebutton; import io.anuke.ucore.scene.builders.imagebutton;
import io.anuke.ucore.scene.builders.label; import io.anuke.ucore.scene.builders.label;
@ -37,6 +41,7 @@ public class MapEditorDialog extends Dialog{
private MapLoadDialog loadDialog; private MapLoadDialog loadDialog;
private MapSaveDialog saveDialog; private MapSaveDialog saveDialog;
private MapResizeDialog resizeDialog; private MapResizeDialog resizeDialog;
private ScrollPane pane;
private FileChooser openFile, saveFile; private FileChooser openFile, saveFile;
private boolean saved = false; private boolean saved = false;
@ -139,6 +144,17 @@ public class MapEditorDialog extends Dialog{
build(); build();
build.end(); 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(() -> { shown(() -> {
saved = true; saved = true;
editor.beginEdit(new Map()); editor.beginEdit(new Map());
@ -146,9 +162,7 @@ public class MapEditorDialog extends Dialog{
Core.scene.setScrollFocus(view); Core.scene.setScrollFocus(view);
view.clearStack(); view.clearStack();
Timers.runTask(3f, () -> { Timers.runTask(10f, Platform.instance::updateRPC);
Platform.instance.updateRPC();
});
}); });
hidden(() -> Platform.instance.updateRPC()); hidden(() -> Platform.instance.updateRPC());
@ -174,6 +188,10 @@ public class MapEditorDialog extends Dialog{
} }
} }
public boolean hasPane(){
return getScene().getScrollFocus() == pane;
}
public void build(){ public void build(){
new table(){{ new table(){{
@ -247,18 +265,20 @@ public class MapEditorDialog extends Dialog{
ImageButton undo = tools.addImageButton("icon-undo", 16*2f, () -> view.undo()).get(); ImageButton undo = tools.addImageButton("icon-undo", 16*2f, () -> view.undo()).get();
ImageButton redo = tools.addImageButton("icon-redo", 16*2f, () -> view.redo()).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()); undo.setDisabled(() -> !view.getStack().canUndo());
redo.setDisabled(() -> !view.getStack().canRedo()); redo.setDisabled(() -> !view.getStack().canRedo());
undo.update(() -> undo.getImage().setColor(undo.isDisabled() ? Color.GRAY : Color.WHITE)); undo.update(() -> undo.getImage().setColor(undo.isDisabled() ? Color.GRAY : Color.WHITE));
redo.update(() -> redo.getImage().setColor(redo.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()){ for(EditorTool tool : EditorTool.values()){
ImageButton button = new ImageButton("icon-" + tool.name(), "toggle"); ImageButton button = new ImageButton("icon-" + tool.name(), "toggle");
button.clicked(() -> view.setTool(tool)); button.clicked(() -> view.setTool(tool));
button.resizeImage(16*2f); button.resizeImage(16*2f);
button.update(() -> button.setChecked(view.getTool() == tool));
group.add(button); group.add(button);
if (tool == EditorTool.pencil) if (tool == EditorTool.pencil)
button.setChecked(true); button.setChecked(true);
@ -283,9 +303,8 @@ public class MapEditorDialog extends Dialog{
row(); row();
new table("button"){{ new table("button"){{
get().addCheck("$text.oregen", b -> { get().addCheck("$text.oregen", b -> editor.getMap().oreGen = b)
editor.getMap().oreGen = b; .update(c -> c.setChecked(editor.getMap().oreGen)).padTop(3).padBottom(3);
}).update(c -> c.setChecked(editor.getMap().oreGen)).padTop(3).padBottom(3);
}}.growX().padBottom(-6).end(); }}.growX().padBottom(-6).end();
row(); row();
@ -298,6 +317,36 @@ public class MapEditorDialog extends Dialog{
}}.grow().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){ private boolean verifySize(Pixmap pix){
boolean w = false, h = false; boolean w = false, h = false;
for(int i : MapEditor.validMapSizes){ for(int i : MapEditor.validMapSizes){
@ -344,7 +393,7 @@ public class MapEditorDialog extends Dialog{
private void addBlockSelection(Table table){ private void addBlockSelection(Table table){
Table content = new Table(); Table content = new Table();
ScrollPane pane = new ScrollPane(content, "volume"); pane = new ScrollPane(content, "volume");
pane.setScrollingDisabled(true, false); pane.setScrollingDisabled(true, false);
pane.setFadeScrollBars(false); pane.setFadeScrollBars(false);
pane.setOverscroll(true, false); pane.setOverscroll(true, false);

View File

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

View File

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

View File

@ -1,9 +1,13 @@
package io.anuke.mindustry.net; 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.Player;
import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.net.Packet.ImportantPacket; import io.anuke.mindustry.net.Packet.ImportantPacket;
import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Item;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -241,67 +245,30 @@ public class Packets {
} }
} }
public static class EnemySpawnPacket implements Packet{ public static class EntitySpawnPacket implements Packet{
public byte type, lane, tier; public SyncEntity entity;
public float x, y; public EntityGroup<?> group;
public short health;
public int id;
@Override @Override
public void write(ByteBuffer buffer){ public void write(ByteBuffer buffer){
buffer.put(type); buffer.put((byte)entity.getGroup().getID());
buffer.put(lane); buffer.putInt(entity.id);
buffer.put(tier); entity.writeSpawn(buffer);
buffer.putFloat(x);
buffer.putFloat(y);
buffer.putShort(health);
buffer.putInt(id);
} }
@Override @Override
public void read(ByteBuffer buffer) { public void read(ByteBuffer buffer) {
type = buffer.get(); byte groupid = buffer.get();
lane = buffer.get(); int id = buffer.getInt();
tier = buffer.get(); group = Entities.getGroup(groupid);
x = buffer.getFloat(); try {
y = buffer.getFloat(); entity = (SyncEntity) ClassReflection.newInstance(group.getType());
health = buffer.getShort(); entity.id = id;
id = buffer.getInt(); entity.readSpawn(buffer);
}catch (ReflectionException e){
throw new RuntimeException(e);
} }
} }
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();
}
} }
public static class EnemyDeathPacket implements Packet{ public static class EnemyDeathPacket implements Packet{
@ -467,15 +434,18 @@ public class Packets {
public static class EntityRequestPacket implements Packet{ public static class EntityRequestPacket implements Packet{
public int id; public int id;
public byte group;
@Override @Override
public void write(ByteBuffer buffer) { public void write(ByteBuffer buffer) {
buffer.putInt(id); buffer.putInt(id);
buffer.put(group);
} }
@Override @Override
public void read(ByteBuffer buffer) { public void read(ByteBuffer buffer) {
id = buffer.getInt(); id = buffer.getInt();
group = buffer.get();
} }
} }

View File

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

View File

@ -281,4 +281,9 @@ public class Block{
public static Block getByID(int id){ public static Block getByID(int id){
return blocks.get(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(() -> { serverThread = new Thread(() -> {
try{ try{
server.run(); server.run();
}catch (Exception e){ }catch (Throwable e){
if(!(e instanceof ClosedSelectorException)) handleException(e); if(!(e instanceof ClosedSelectorException)) handleException(e);
} }
}, "Kryonet Server"); }, "Kryonet Server");
@ -273,7 +273,7 @@ public class KryoServer implements ServerProvider {
Log.info("Disposed server."); Log.info("Disposed server.");
} }
private void handleException(Exception e){ private void handleException(Throwable e){
Gdx.app.postRunnable(() -> { throw new RuntimeException(e);}); Gdx.app.postRunnable(() -> { throw new RuntimeException(e);});
} }
@ -435,9 +435,7 @@ public class KryoServer implements ServerProvider {
} }
@Override @Override
public void onStart() { public void onStart() {}
Log.info("Web server started.");
}
} }
} }