Added server browser
This commit is contained in:
BIN
core/assets-raw/sprites/ui/icons/icon-refresh.png
Normal file
BIN
core/assets-raw/sprites/ui/icons/icon-refresh.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 245 B |
BIN
core/assets-raw/sprites/ui/icons/icon-trash-16.png
Normal file
BIN
core/assets-raw/sprites/ui/icons/icon-trash-16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 233 B |
@@ -29,7 +29,13 @@ text.host=Host
|
|||||||
text.hosting=[accent]Opening server...
|
text.hosting=[accent]Opening server...
|
||||||
text.hosts.refresh=Refresh
|
text.hosts.refresh=Refresh
|
||||||
text.hosts.discovering=Discovering LAN games
|
text.hosts.discovering=Discovering LAN games
|
||||||
text.hosts.none=[lightgray]No games found!
|
text.server.refreshing=Refreshing server
|
||||||
|
text.hosts.none=[lightgray]No LAN games found!
|
||||||
|
text.host.invalid=[scarlet]Can't connect to host.
|
||||||
|
text.server.add=Add Server
|
||||||
|
text.server.delete=Are you sure you want to delete this server?
|
||||||
|
text.server.hostname=Host: {0}
|
||||||
|
text.server.edit=Edit Server
|
||||||
text.joingame.byip=Join by IP...
|
text.joingame.byip=Join by IP...
|
||||||
text.joingame.title=Join Game
|
text.joingame.title=Join Game
|
||||||
text.joingame.ip=IP:
|
text.joingame.ip=IP:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
@@ -199,7 +199,8 @@ public class Control extends Module{
|
|||||||
Settings.defaultList(
|
Settings.defaultList(
|
||||||
"ip", "localhost",
|
"ip", "localhost",
|
||||||
"port", Vars.port+"",
|
"port", Vars.port+"",
|
||||||
"name", Vars.android ? "player" : UCore.getProperty("user.name")
|
"name", Vars.android ? "player" : UCore.getProperty("user.name"),
|
||||||
|
"servers", ""
|
||||||
);
|
);
|
||||||
|
|
||||||
Settings.loadAll("io.anuke.moment");
|
Settings.loadAll("io.anuke.moment");
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package io.anuke.mindustry.net;
|
package io.anuke.mindustry.net;
|
||||||
|
|
||||||
public class Address {
|
public class Host {
|
||||||
public final String name;
|
public final String name;
|
||||||
public final String address;
|
public final String address;
|
||||||
public final int players;
|
public final int players;
|
||||||
|
|
||||||
public Address(String name, String address, int players){
|
public Host(String name, String address, int players){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.players = players;
|
this.players = players;
|
||||||
@@ -66,9 +66,9 @@ public class Net{
|
|||||||
|
|
||||||
/**Starts discovering servers on a different thread. Does not work with GWT.
|
/**Starts discovering servers on a different thread. Does not work with GWT.
|
||||||
* Callback is run on the main libGDX thread.*/
|
* Callback is run on the main libGDX thread.*/
|
||||||
public static void discoverServers(Consumer<Array<Address>> cons){
|
public static void discoverServers(Consumer<Array<Host>> cons){
|
||||||
executor.submit(() -> {
|
executor.submit(() -> {
|
||||||
Array<Address> arr = clientProvider.discover();
|
Array<Host> arr = clientProvider.discover();
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
cons.accept(arr);
|
cons.accept(arr);
|
||||||
});
|
});
|
||||||
@@ -163,6 +163,11 @@ public class Net{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Pings a host in an new thread. If an error occured, failed() should be called with the exception. */
|
||||||
|
public static void pingHost(String address, int port, Consumer<Host> valid, Consumer<IOException> failed){
|
||||||
|
clientProvider.pingHost(address, port, valid, failed);
|
||||||
|
}
|
||||||
|
|
||||||
/**Update client ping.*/
|
/**Update client ping.*/
|
||||||
public static void updatePing(){
|
public static void updatePing(){
|
||||||
clientProvider.updatePing();
|
clientProvider.updatePing();
|
||||||
@@ -218,7 +223,9 @@ public class Net{
|
|||||||
/**Disconnect from the server.*/
|
/**Disconnect from the server.*/
|
||||||
public void disconnect();
|
public void disconnect();
|
||||||
/**Discover servers. This should block for a certain amount of time, and will most likely be run in a different thread.*/
|
/**Discover servers. This should block for a certain amount of time, and will most likely be run in a different thread.*/
|
||||||
public Array<Address> discover();
|
public Array<Host> discover();
|
||||||
|
/**Ping a host. If an error occured, failed() should be called with the exception. */
|
||||||
|
public void pingHost(String address, int port, Consumer<Host> valid, Consumer<IOException> failed);
|
||||||
/**Register classes to be sent.*/
|
/**Register classes to be sent.*/
|
||||||
public void register(Class<?>... types);
|
public void register(Class<?>... types);
|
||||||
/**Close all connections.*/
|
/**Close all connections.*/
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package io.anuke.mindustry.ui.dialogs;
|
|||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import io.anuke.mindustry.Mindustry;
|
import io.anuke.mindustry.Mindustry;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.net.Address;
|
import io.anuke.mindustry.net.Host;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
@@ -17,13 +17,19 @@ import io.anuke.ucore.util.Bundles;
|
|||||||
import io.anuke.ucore.util.Strings;
|
import io.anuke.ucore.util.Strings;
|
||||||
|
|
||||||
public class JoinDialog extends FloatingDialog {
|
public class JoinDialog extends FloatingDialog {
|
||||||
|
Array<Server> servers = new Array<>();
|
||||||
Dialog join;
|
Dialog join;
|
||||||
|
Server renaming;
|
||||||
|
Table local = new Table();
|
||||||
|
Table remote = new Table();
|
||||||
Table hosts = new Table();
|
Table hosts = new Table();
|
||||||
float w = 400;
|
float w = 500;
|
||||||
|
|
||||||
public JoinDialog(){
|
public JoinDialog(){
|
||||||
super("$text.joingame");
|
super("$text.joingame");
|
||||||
|
|
||||||
|
loadServers();
|
||||||
|
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
|
|
||||||
join = new FloatingDialog("$text.joingame.title");
|
join = new FloatingDialog("$text.joingame.title");
|
||||||
@@ -31,7 +37,7 @@ public class JoinDialog extends FloatingDialog {
|
|||||||
Mindustry.platforms.addDialog(join.content().addField(Settings.getString("ip"),text ->{
|
Mindustry.platforms.addDialog(join.content().addField(Settings.getString("ip"),text ->{
|
||||||
Settings.putString("ip", text);
|
Settings.putString("ip", text);
|
||||||
Settings.save();
|
Settings.save();
|
||||||
}).size(180f, 54f).get(), 100);
|
}).size(240f, 54f).get(), 100);
|
||||||
|
|
||||||
join.content().row();
|
join.content().row();
|
||||||
join.content().add("$text.server.port").left();
|
join.content().add("$text.server.port").left();
|
||||||
@@ -39,33 +45,123 @@ public class JoinDialog extends FloatingDialog {
|
|||||||
.addField(Settings.getString("port"), new DigitsOnlyFilter(), text ->{
|
.addField(Settings.getString("port"), new DigitsOnlyFilter(), text ->{
|
||||||
Settings.putString("port", text);
|
Settings.putString("port", text);
|
||||||
Settings.save();
|
Settings.save();
|
||||||
})
|
}).size(240f, 54f).get());
|
||||||
.size(180f, 54f).get());
|
|
||||||
join.buttons().defaults().size(140f, 60f).pad(4f);
|
join.buttons().defaults().size(140f, 60f).pad(4f);
|
||||||
join.buttons().addButton("$text.cancel", join::hide);
|
join.buttons().addButton("$text.cancel", join::hide);
|
||||||
join.buttons().addButton("$text.ok", () ->
|
join.buttons().addButton("$text.ok", () -> {
|
||||||
connect(Settings.getString("ip"), Strings.parseInt(Settings.getString("port")))
|
if(renaming == null) {
|
||||||
).disabled(b -> Settings.getString("ip").isEmpty() || Strings.parseInt(Settings.getString("port")) == Integer.MIN_VALUE || Net.active());
|
Server server = new Server(Settings.getString("ip"), Strings.parseInt(Settings.getString("port")));
|
||||||
|
servers.add(server);
|
||||||
|
saveServers();
|
||||||
|
setupRemote();
|
||||||
|
refreshRemote();
|
||||||
|
}else{
|
||||||
|
renaming.port = Strings.parseInt(Settings.getString("port"));
|
||||||
|
renaming.ip = Settings.getString("ip");
|
||||||
|
saveServers();
|
||||||
|
setupRemote();
|
||||||
|
refreshRemote();
|
||||||
|
}
|
||||||
|
join.hide();
|
||||||
|
}).disabled(b -> Settings.getString("ip").isEmpty() || Strings.parseInt(Settings.getString("port")) == Integer.MIN_VALUE || Net.active());
|
||||||
|
join.shown(() -> {
|
||||||
|
join.getTitleLabel().setText(renaming != null ? "$text.server.edit" : "$text.server.add");
|
||||||
|
});
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
shown(this::refresh);
|
shown(this::refreshLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void refresh(){
|
void setupRemote(){
|
||||||
hosts.clear();
|
remote.clear();
|
||||||
hosts.background("button");
|
for (Server server : servers) {
|
||||||
hosts.label(() -> "[accent]" + Bundles.get("text.hosts.discovering") + new String(new char[(int)(Timers.time() / 10) % 4]).replace("\0", ".")).pad(10f);
|
//why are java lambdas this bad
|
||||||
Net.discoverServers(this::addHosts);
|
TextButton[] buttons = {null};
|
||||||
|
|
||||||
|
TextButton button = buttons[0] = remote.addButton("[accent]"+server.ip + " / " + server.port, "clear", () -> {
|
||||||
|
if(!buttons[0].childrenPressed()) connect(server.ip, server.port);
|
||||||
|
}).width(w).height(120f).pad(4f).get();
|
||||||
|
|
||||||
|
button.getLabel().setWrap(true);
|
||||||
|
|
||||||
|
Table inner = new Table();
|
||||||
|
button.clearChildren();
|
||||||
|
button.add(inner).growX();
|
||||||
|
|
||||||
|
inner.add(button.getLabel()).growX();
|
||||||
|
|
||||||
|
inner.addImageButton("icon-loading", "empty", 16*2, () -> {
|
||||||
|
refreshServer(server);
|
||||||
|
}).margin(3f).padTop(6f).top().right();
|
||||||
|
|
||||||
|
inner.addImageButton("icon-pencil", "empty", 16*2, () -> {
|
||||||
|
renaming = server;
|
||||||
|
join.show();
|
||||||
|
}).margin(3f).padTop(6f).top().right();
|
||||||
|
|
||||||
|
inner.addImageButton("icon-trash-16", "empty", 16*2, () -> {
|
||||||
|
Vars.ui.showConfirm("$text.confirm", "$text.server.delete", () -> {
|
||||||
|
servers.removeValue(server, true);
|
||||||
|
saveServers();
|
||||||
|
setupRemote();
|
||||||
|
refreshRemote();
|
||||||
|
});
|
||||||
|
}).margin(3f).pad(6).top().right();
|
||||||
|
|
||||||
|
button.row();
|
||||||
|
|
||||||
|
server.content = button.table(t -> {}).grow().get();
|
||||||
|
|
||||||
|
remote.row();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void refreshRemote(){
|
||||||
|
for(Server server : servers){
|
||||||
|
refreshServer(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void refreshServer(Server server){
|
||||||
|
server.content.clear();
|
||||||
|
server.content.label(() -> Bundles.get("text.server.refreshing") + Strings.animated(4, 11, "."));
|
||||||
|
|
||||||
|
Net.pingHost(server.ip, server.port, host -> {
|
||||||
|
server.content.clear();
|
||||||
|
|
||||||
|
server.content.add("[lightgray]" + Bundles.format("text.server.hostname", host.name)).pad(4);
|
||||||
|
server.content.row();
|
||||||
|
server.content.add("[lightgray]" + (host.players != 1 ? Bundles.format("text.players", host.players) :
|
||||||
|
Bundles.format("text.players.single", host.players))).left();
|
||||||
|
|
||||||
|
}, e -> {
|
||||||
|
server.content.clear();
|
||||||
|
server.content.add("$text.host.invalid");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void refreshLocal(){
|
||||||
|
local.clear();
|
||||||
|
local.background("button");
|
||||||
|
local.label(() -> "[accent]" + Bundles.get("text.hosts.discovering") + new String(new char[(int)(Timers.time() / 10) % 4]).replace("\0", ".")).pad(10f);
|
||||||
|
Net.discoverServers(this::addLocalHosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
hosts.background("button");
|
hosts.clear();
|
||||||
|
|
||||||
|
hosts.add(remote).growX();
|
||||||
|
hosts.row();
|
||||||
|
hosts.add(local).growX();
|
||||||
|
|
||||||
ScrollPane pane = new ScrollPane(hosts, "clear");
|
ScrollPane pane = new ScrollPane(hosts, "clear");
|
||||||
pane.setFadeScrollBars(false);
|
pane.setFadeScrollBars(false);
|
||||||
pane.setScrollingDisabled(true, false);
|
pane.setScrollingDisabled(true, false);
|
||||||
|
|
||||||
|
setupRemote();
|
||||||
|
refreshRemote();
|
||||||
|
|
||||||
content().clear();
|
content().clear();
|
||||||
content().table(t -> {
|
content().table(t -> {
|
||||||
t.add("$text.name").padRight(10);
|
t.add("$text.name").padRight(10);
|
||||||
@@ -79,19 +175,22 @@ public class JoinDialog extends FloatingDialog {
|
|||||||
content().row();
|
content().row();
|
||||||
content().add(pane).width(w).pad(0);
|
content().add(pane).width(w).pad(0);
|
||||||
content().row();
|
content().row();
|
||||||
content().addButton("$text.joingame.byip", "clear", join::show).width(w).height(80f);
|
content().addButton("$text.server.add", "clear", () -> {
|
||||||
|
renaming = null;
|
||||||
|
join.show();
|
||||||
|
}).width(w).height(80f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addHosts(Array<Address> array){
|
void addLocalHosts(Array<Host> array){
|
||||||
hosts.clear();
|
local.clear();
|
||||||
|
|
||||||
if(array.size == 0){
|
if(array.size == 0){
|
||||||
hosts.add("$text.hosts.none").pad(10f);
|
local.add("$text.hosts.none").pad(10f);
|
||||||
hosts.add().growX();
|
local.add().growX();
|
||||||
hosts.addImageButton("icon-loading", 16*2f, this::refresh).pad(-10f).padLeft(0).padTop(-6).size(70f, 74f);
|
local.addImageButton("icon-loading", 16*2f, this::refreshLocal).pad(-10f).padLeft(0).padTop(-6).size(70f, 74f);
|
||||||
}else {
|
}else {
|
||||||
for (Address a : array) {
|
for (Host a : array) {
|
||||||
TextButton button = hosts.addButton("[accent]"+a.name, "clear", () -> {
|
TextButton button = local.addButton("[accent]"+a.name, "clear", () -> {
|
||||||
connect(a.address, Vars.port);
|
connect(a.address, Vars.port);
|
||||||
}).width(w).height(80f).pad(4f).get();
|
}).width(w).height(80f).pad(4f).get();
|
||||||
button.left();
|
button.left();
|
||||||
@@ -101,8 +200,8 @@ public class JoinDialog extends FloatingDialog {
|
|||||||
button.row();
|
button.row();
|
||||||
button.add("[lightgray]" + a.address + " / " + Vars.port).pad(4).left();
|
button.add("[lightgray]" + a.address + " / " + Vars.port).pad(4).left();
|
||||||
|
|
||||||
hosts.row();
|
local.row();
|
||||||
hosts.background((Drawable) null);
|
local.background((Drawable) null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,4 +239,41 @@ public class JoinDialog extends FloatingDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadServers(){
|
||||||
|
String h = Settings.getString("servers");
|
||||||
|
String[] list = h.split("\\|\\|\\|");
|
||||||
|
for(String fname : list){
|
||||||
|
if(fname.isEmpty()) continue;
|
||||||
|
String[] split = fname.split(":");
|
||||||
|
String host = split[0];
|
||||||
|
int port = Strings.parseInt(split[1]);
|
||||||
|
|
||||||
|
if(port != Integer.MIN_VALUE) servers.add(new Server(host, port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveServers(){
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
for(Server server : servers){
|
||||||
|
out.append(server.ip);
|
||||||
|
out.append(":");
|
||||||
|
out.append(server.port);
|
||||||
|
out.append("|||");
|
||||||
|
}
|
||||||
|
Settings.putString("servers", out.toString());
|
||||||
|
Settings.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Server{
|
||||||
|
public String ip;
|
||||||
|
public int port;
|
||||||
|
public Host host;
|
||||||
|
public Table content;
|
||||||
|
|
||||||
|
public Server(String ip, int port){
|
||||||
|
this.ip = ip;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import com.badlogic.gdx.utils.Array;
|
|||||||
import com.badlogic.gdx.utils.ObjectMap;
|
import com.badlogic.gdx.utils.ObjectMap;
|
||||||
import com.badlogic.gdx.utils.ObjectSet;
|
import com.badlogic.gdx.utils.ObjectSet;
|
||||||
import com.esotericsoftware.kryonet.*;
|
import com.esotericsoftware.kryonet.*;
|
||||||
|
import com.esotericsoftware.kryonet.FrameworkMessage.DiscoverHost;
|
||||||
|
import com.esotericsoftware.kryonet.serialization.Serialization;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.net.Address;
|
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;
|
||||||
import io.anuke.mindustry.net.Net.SendMode;
|
import io.anuke.mindustry.net.Net.SendMode;
|
||||||
@@ -14,21 +16,22 @@ import io.anuke.mindustry.net.Packets.Connect;
|
|||||||
import io.anuke.mindustry.net.Packets.Disconnect;
|
import io.anuke.mindustry.net.Packets.Disconnect;
|
||||||
import io.anuke.mindustry.net.Registrator;
|
import io.anuke.mindustry.net.Registrator;
|
||||||
import io.anuke.ucore.UCore;
|
import io.anuke.ucore.UCore;
|
||||||
|
import io.anuke.ucore.function.Consumer;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.DatagramPacket;
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class KryoClient implements ClientProvider{
|
public class KryoClient implements ClientProvider{
|
||||||
Client client;
|
Client client;
|
||||||
ObjectMap<InetAddress, Address> addresses = new ObjectMap<>();
|
ObjectMap<InetAddress, Host> addresses = new ObjectMap<>();
|
||||||
|
ClientDiscoveryHandler handler;
|
||||||
|
|
||||||
public KryoClient(){
|
public KryoClient(){
|
||||||
client = new Client();
|
handler = new ClientDiscoveryHandler() {
|
||||||
client.setDiscoveryHandler(new ClientDiscoveryHandler() {
|
|
||||||
@Override
|
@Override
|
||||||
public DatagramPacket onRequestNewDatagramPacket() {
|
public DatagramPacket onRequestNewDatagramPacket() {
|
||||||
return new DatagramPacket(new byte[32], 32);
|
return new DatagramPacket(new byte[32], 32);
|
||||||
@@ -37,16 +40,19 @@ public class KryoClient implements ClientProvider{
|
|||||||
@Override
|
@Override
|
||||||
public void onDiscoveredHost(DatagramPacket datagramPacket) {
|
public void onDiscoveredHost(DatagramPacket datagramPacket) {
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(datagramPacket.getData());
|
ByteBuffer buffer = ByteBuffer.wrap(datagramPacket.getData());
|
||||||
Address address = KryoRegistrator.readServerData(datagramPacket.getAddress(), buffer);
|
Host address = KryoRegistrator.readServerData(datagramPacket.getAddress(), buffer);
|
||||||
addresses.put(datagramPacket.getAddress(), address);
|
addresses.put(datagramPacket.getAddress(), address);
|
||||||
UCore.log("Host data found: " + Arrays.toString(datagramPacket.getData()));
|
UCore.log("Host data found: " + buffer.capacity() + " bytes.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinally() {
|
public void onFinally() {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
client = new Client();
|
||||||
|
client.setDiscoveryHandler(handler);
|
||||||
|
|
||||||
client.addListener(new Listener(){
|
client.addListener(new Listener(){
|
||||||
@Override
|
@Override
|
||||||
@@ -81,7 +87,8 @@ public class KryoClient implements ClientProvider{
|
|||||||
Net.handleClientReceived(object);
|
Net.handleClientReceived(object);
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
if(e instanceof KryoNetException && e.getMessage() != null && e.getMessage().toLowerCase().contains("incorrect")) {
|
if(e instanceof KryoNetException && e.getMessage() != null && e.getMessage().toLowerCase().contains("incorrect")) {
|
||||||
UCore.log("Mismatch!");
|
Gdx.app.postRunnable(() -> Vars.ui.showError("$text.server.mismatch"));
|
||||||
|
Vars.netClient.disconnectQuietly();
|
||||||
}else{
|
}else{
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
@@ -138,14 +145,56 @@ public class KryoClient implements ClientProvider{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<Address> discover(){
|
public void pingHost(String address, int port, Consumer<Host> valid, Consumer<IOException> invalid){
|
||||||
|
Thread thread = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
|
||||||
|
Serialization ser = (Serialization) UCore.getPrivate(client, "serialization");
|
||||||
|
DatagramSocket socket = new DatagramSocket();
|
||||||
|
ByteBuffer dataBuffer = ByteBuffer.allocate(64);
|
||||||
|
ser.write(dataBuffer, new DiscoverHost());
|
||||||
|
|
||||||
|
dataBuffer.flip();
|
||||||
|
byte[] data = new byte[dataBuffer.limit()];
|
||||||
|
dataBuffer.get(data);
|
||||||
|
socket.send(new DatagramPacket(data, data.length, InetAddress.getByName(address), port));
|
||||||
|
|
||||||
|
socket.setSoTimeout(2000);
|
||||||
|
|
||||||
|
addresses.clear();
|
||||||
|
|
||||||
|
DatagramPacket packet = handler.onRequestNewDatagramPacket();
|
||||||
|
|
||||||
|
socket.receive(packet);
|
||||||
|
|
||||||
|
handler.onDiscoveredHost(packet);
|
||||||
|
|
||||||
|
Host host = addresses.values().next();
|
||||||
|
|
||||||
|
if (host != null) {
|
||||||
|
Gdx.app.postRunnable(() -> valid.accept(host));
|
||||||
|
} else {
|
||||||
|
Gdx.app.postRunnable(() -> invalid.accept(new IOException("Outdated server.")));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Gdx.app.postRunnable(() -> invalid.accept(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.setDaemon(true);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Array<Host> discover(){
|
||||||
|
addresses.clear();
|
||||||
List<InetAddress> list = client.discoverHosts(Vars.port, 3000);
|
List<InetAddress> list = client.discoverHosts(Vars.port, 3000);
|
||||||
ObjectSet<String> hostnames = new ObjectSet<>();
|
ObjectSet<String> hostnames = new ObjectSet<>();
|
||||||
Array<Address> result = new Array<>();
|
Array<Host> result = new Array<>();
|
||||||
|
|
||||||
for(InetAddress a : list){
|
for(InetAddress a : list){
|
||||||
if(!hostnames.contains(a.getHostName())) {
|
if(!hostnames.contains(a.getHostName())) {
|
||||||
Address address = addresses.get(a);
|
Host address = addresses.get(a);
|
||||||
if(address != null) result.add(address);
|
if(address != null) result.add(address);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package io.anuke.kryonet;
|
|||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.net.Address;
|
import io.anuke.mindustry.net.Host;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@@ -22,7 +22,7 @@ public class KryoRegistrator {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Address readServerData(InetAddress ia, ByteBuffer buffer){
|
public static Host readServerData(InetAddress ia, ByteBuffer buffer){
|
||||||
//old version address.
|
//old version address.
|
||||||
if(buffer.capacity() == 4) return null;
|
if(buffer.capacity() == 4) return null;
|
||||||
|
|
||||||
@@ -31,6 +31,6 @@ public class KryoRegistrator {
|
|||||||
buffer.get(sname);
|
buffer.get(sname);
|
||||||
int players = buffer.getInt();
|
int players = buffer.getInt();
|
||||||
|
|
||||||
return new Address(new String(sname), ia.getHostAddress(), players);
|
return new Host(new String(sname), ia.getHostAddress(), players);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package io.anuke.kryonet;
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.utils.IntArray;
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
import com.esotericsoftware.kryonet.*;
|
import com.esotericsoftware.kryonet.Connection;
|
||||||
|
import com.esotericsoftware.kryonet.FrameworkMessage;
|
||||||
|
import com.esotericsoftware.kryonet.Listener;
|
||||||
|
import com.esotericsoftware.kryonet.Server;
|
||||||
import com.esotericsoftware.kryonet.util.InputStreamSender;
|
import com.esotericsoftware.kryonet.util.InputStreamSender;
|
||||||
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;
|
||||||
@@ -19,9 +22,7 @@ import io.anuke.ucore.UCore;
|
|||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.DatagramChannel;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class KryoServer implements ServerProvider {
|
public class KryoServer implements ServerProvider {
|
||||||
@@ -30,16 +31,12 @@ public class KryoServer implements ServerProvider {
|
|||||||
|
|
||||||
public KryoServer(){
|
public KryoServer(){
|
||||||
server = new Server(4096*2, 2048); //TODO tweak
|
server = new Server(4096*2, 2048); //TODO tweak
|
||||||
server.setDiscoveryHandler(new ServerDiscoveryHandler() {
|
server.setDiscoveryHandler((datagramChannel, fromAddress) -> {
|
||||||
|
ByteBuffer buffer = KryoRegistrator.writeServerData();
|
||||||
@Override
|
UCore.log("Replying to discover request with buffer of size " + buffer.capacity());
|
||||||
public boolean onDiscoverHost(DatagramChannel datagramChannel, InetSocketAddress fromAddress) throws IOException {
|
buffer.position(0);
|
||||||
ByteBuffer buffer = KryoRegistrator.writeServerData();
|
datagramChannel.send(buffer, fromAddress);
|
||||||
UCore.log("Replying to discover request with buffer of size " + buffer.capacity());
|
return true;
|
||||||
buffer.position(0);
|
|
||||||
datagramChannel.send(buffer, fromAddress);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
server.addListener(new Listener(){
|
server.addListener(new Listener(){
|
||||||
|
|||||||
Reference in New Issue
Block a user