Non-blocking connect / Localized connect error messages

This commit is contained in:
Anuken
2018-10-28 23:47:28 -04:00
parent e21d17a482
commit 108e5a2f5e
5 changed files with 92 additions and 78 deletions

View File

@@ -77,7 +77,6 @@ text.unlocked = New Block Unlocked\!
text.unlocked.plural = New Blocks Unlocked\! text.unlocked.plural = New Blocks Unlocked\!
text.players = {0} players online text.players = {0} players online
text.players.single = {0} player online text.players.single = {0} player online
text.server.mismatch = Packet error\: possible client/server version mismatch.\nMake sure you and the host have the\nlatest version of Mindustry\!
text.server.closing = [accent]Closing server... text.server.closing = [accent]Closing server...
text.server.kicked.kick = You have been kicked from the server\! text.server.kicked.kick = You have been kicked from the server\!
text.server.kicked.serverClose = Server closed. text.server.kicked.serverClose = Server closed.
@@ -137,7 +136,6 @@ text.disconnect = Disconnected.
text.disconnect.data = Failed to load world data\! text.disconnect.data = Failed to load world data\!
text.connecting = [accent]Connecting... text.connecting = [accent]Connecting...
text.connecting.data = [accent]Loading world data... text.connecting.data = [accent]Loading world data...
text.connectfail = [crimson]Failed to connect to server\: [orange]{0}
text.server.port = Port\: text.server.port = Port\:
text.server.addressinuse = Address already in use\! text.server.addressinuse = Address already in use\!
text.server.invalidport = Invalid port number\! text.server.invalidport = Invalid port number\!
@@ -262,6 +260,14 @@ text.tutorial = Tutorial
text.editor = Editor text.editor = Editor
text.mapeditor = Map Editor text.mapeditor = Map Editor
text.donate = Donate text.donate = Donate
text.connectfail = [crimson]Failed to connect to server\:\n\n[accent]{0}
text.error.unreachable = Server unreachable.
text.error.invalidaddress = Invalid address.
text.error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct!
text.error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry!
text.error.any = Unkown network error.
text.settings.language = Language text.settings.language = Language
text.settings.reset = Reset to Defaults text.settings.reset = Reset to Defaults
text.settings.rebind = Rebind text.settings.rebind = Rebind

View File

@@ -269,10 +269,9 @@ public class Drone extends FlyingUnit implements BuilderTrait{
} }
private void notifyPlaced(BuildEntity entity, boolean isBreaking){ private void notifyPlaced(BuildEntity entity, boolean isBreaking){
float timeToBuild = entity.buildCost;
float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0); float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0);
if(!state.is(build) && dist / type.maxVelocity < timeToBuild * 0.9f){ if(!state.is(build) && dist / type.maxVelocity < entity.buildCost * 0.9f){
target = entity; target = entity;
this.isBreaking = isBreaking; this.isBreaking = isBreaking;
setState(build); setState(build);

View File

@@ -17,13 +17,14 @@ import io.anuke.mindustry.net.Streamable.StreamBuilder;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.function.BiConsumer; import io.anuke.ucore.function.BiConsumer;
import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Pooling; import io.anuke.ucore.util.Pooling;
import io.anuke.ucore.util.Threads;
import java.io.IOException; import java.io.IOException;
import static io.anuke.mindustry.Vars.headless; import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.ui;
public class Net{ public class Net{
private static boolean server; private static boolean server;
@@ -46,15 +47,41 @@ public class Net{
return serverProvider != null; return serverProvider != null;
} }
/** /**Display a network error. Call on the graphics thread.*/
* Display a network error. public static void showError(Throwable e){
*/
public static void showError(String text){
if(!headless){ if(!headless){
ui.showError(text); Threads.assertGraphics();
}else{
Log.err(text); Throwable t = e;
while(t.getCause() != null){
t = t.getCause();
}
String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase();
String type = error.getClass().toString().toLowerCase();
if(error.equals("mismatch")){
error = Bundles.get("text.error.mismatch");
}else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address"))){
error = Bundles.get("text.error.invalidaddress");
}else if(error.contains("connection refused") || error.contains("route to host") || type.contains("unknownhost")){
error = Bundles.get("text.error.unreachable");
}else if(type.contains("timeout")){
error = Bundles.get("text.error.timeout");
}else if(!error.isEmpty()){
error = Bundles.get("text.error.any");
}
ui.showText("", Bundles.format("text.connectfail", error));
ui.loadfrag.hide();
if(Net.client()){
netClient.disconnectQuietly();
}
} }
Log.err(e);
} }
/** /**
@@ -77,14 +104,18 @@ public class Net{
/** /**
* Connect to an address. * Connect to an address.
*/ */
public static void connect(String ip, int port) throws IOException{ public static void connect(String ip, int port, Runnable success){
lastIP = ip + ":" + port; try{
if(!active){ lastIP = ip + ":" + port;
clientProvider.connect(ip, port); if(!active){
active = true; clientProvider.connect(ip, port, success);
server = false; active = true;
}else{ server = false;
throw new IOException("Already connected!"); }else{
throw new IOException("Already connected!");
}
}catch(IOException e){
showError(e);
} }
} }
@@ -346,7 +377,7 @@ public class Net{
/**Client implementation.*/ /**Client implementation.*/
public interface ClientProvider{ public interface ClientProvider{
/**Connect to a server.*/ /**Connect to a server.*/
void connect(String ip, int port) throws IOException; void connect(String ip, int port, Runnable success) throws IOException;
/**Send an object to the server.*/ /**Send an object to the server.*/
void send(Object object, SendMode mode); void send(Object object, SendMode mode);

View File

@@ -18,7 +18,6 @@ import io.anuke.ucore.scene.ui.layout.Cell;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.scene.utils.UIUtils; import io.anuke.ucore.scene.utils.UIUtils;
import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Strings; import io.anuke.ucore.util.Strings;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -300,34 +299,11 @@ public class JoinDialog extends FloatingDialog{
}); });
Timers.runTask(2f, () -> { Timers.runTask(2f, () -> {
try{ Vars.netClient.beginConnecting();
Vars.netClient.beginConnecting(); Net.connect(ip, port, () -> {
Net.connect(ip, port);
hide(); hide();
add.hide(); add.hide();
}catch(Exception e){ });
Throwable t = e;
while(t.getCause() != null){
t = t.getCause();
}
//TODO localize
String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase();
if(error.contains("connection refused")){
error = "connection refused";
}else if(error.contains("port out of range")){
error = "invalid port!";
}else if(error.contains("invalid argument")){
error = "invalid IP or port!";
}else if(t.getClass().toString().toLowerCase().contains("sockettimeout")){
error = "timed out!\nmake sure the host has port forwarding set up,\nand that the address is correct!";
}else{
error = Strings.parseException(e, false);
}
ui.showError(Bundles.format("text.connectfail", error));
ui.loadfrag.hide();
Log.err(e);
}
}); });
} }

View File

@@ -3,7 +3,6 @@ package io.anuke.kryonet;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.esotericsoftware.kryonet.*; import com.esotericsoftware.kryonet.*;
import com.esotericsoftware.minlog.Log;
import io.anuke.mindustry.net.Host; import io.anuke.mindustry.net.Host;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.ClientProvider; import io.anuke.mindustry.net.Net.ClientProvider;
@@ -13,12 +12,14 @@ import io.anuke.mindustry.net.Packets.Connect;
import io.anuke.mindustry.net.Packets.Disconnect; import io.anuke.mindustry.net.Packets.Disconnect;
import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.util.Pooling; import io.anuke.ucore.util.Pooling;
import io.anuke.ucore.util.Strings;
import net.jpountz.lz4.LZ4Factory; import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor; import net.jpountz.lz4.LZ4FastDecompressor;
import java.io.IOException; import java.io.IOException;
import java.net.*; import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.ClosedSelectorException; import java.nio.channels.ClosedSelectorException;
@@ -75,10 +76,12 @@ public class KryoClient implements ClientProvider{
@Override @Override
public void disconnected (Connection connection) { public void disconnected (Connection connection) {
Disconnect c = new Disconnect(); if(connection.getLastProtocolError() != null){
netClient.setQuiet();
}
Disconnect c = new Disconnect();
threads.runDelay(() -> Net.handleClientReceived(c)); threads.runDelay(() -> Net.handleClientReceived(c));
if(connection.getLastProtocolError() != null) Log.error("\n\n\n\nProtocol error: " + connection.getLastProtocolError() + "\n\n\n\n");
} }
@Override @Override
@@ -89,13 +92,7 @@ public class KryoClient implements ClientProvider{
try{ try{
Net.handleClientReceived(object); Net.handleClientReceived(object);
}catch (Exception e){ }catch (Exception e){
e.printStackTrace(); handleException(e);
if(e instanceof KryoNetException && e.getMessage() != null && e.getMessage().toLowerCase().contains("incorrect")) {
Net.showError("$text.server.mismatch");
netClient.disconnectQuietly();
}else{
throw new RuntimeException(e);
}
} }
}); });
@@ -128,21 +125,28 @@ public class KryoClient implements ClientProvider{
} }
@Override @Override
public void connect(String ip, int port) throws IOException { public void connect(String ip, int port, Runnable success){
//just in case runAsync(() -> {
client.stop();
Thread updateThread = new Thread(() -> {
try{ try{
client.run(); //just in case
}catch (Exception e){ client.stop();
if(!(e instanceof ClosedSelectorException)) handleException(e);
}
}, "Kryonet Client");
updateThread.setDaemon(true);
updateThread.start();
client.connect(5000, ip, port, port); Thread updateThread = new Thread(() -> {
try{
client.run();
}catch(Exception e){
if(!(e instanceof ClosedSelectorException)) handleException(e);
}
}, "Kryonet Client");
updateThread.setDaemon(true);
updateThread.start();
client.connect(5000, ip, port, port);
success.run();
}catch(Exception e){
handleException(e);
}
});
} }
@Override @Override
@@ -222,12 +226,10 @@ public class KryoClient implements ClientProvider{
} }
private void handleException(Exception e){ private void handleException(Exception e){
e.printStackTrace();
if(e instanceof KryoNetException){ if(e instanceof KryoNetException){
Gdx.app.postRunnable(() -> Net.showError("$text.server.mismatch")); Gdx.app.postRunnable(() -> Net.showError(new IOException("mismatch")));
}else{ }else{
Net.showError(Strings.parseException(e, true)); Gdx.app.postRunnable(() -> Net.showError(e));
disconnect();
} }
} }