diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index a84cfefbe4..8bae7eb11e 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -84,6 +84,10 @@ public class Vars{ }; /** default server port */ public static final int port = 6567; + /** multicast discovery port.*/ + public static final int multicastPort = 20151; + /** multicast group for discovery.*/ + public static final String multicastGroup = "227.2.7.7"; /** if true, UI is not drawn */ public static boolean disableUI; /** if true, game is set up in mobile mode, even on desktop. used for debugging */ diff --git a/net/src/io/anuke/mindustry/net/ArcNetClient.java b/net/src/io/anuke/mindustry/net/ArcNetClient.java index 068b47cbb6..59b0fa5385 100644 --- a/net/src/io/anuke/mindustry/net/ArcNetClient.java +++ b/net/src/io/anuke/mindustry/net/ArcNetClient.java @@ -2,59 +2,28 @@ package io.anuke.mindustry.net; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; -import io.anuke.arc.function.Consumer; +import io.anuke.arc.function.*; import io.anuke.arc.net.*; import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.net.Net.ClientProvider; -import io.anuke.mindustry.net.Net.SendMode; -import io.anuke.mindustry.net.Packets.Connect; -import io.anuke.mindustry.net.Packets.Disconnect; -import net.jpountz.lz4.LZ4Factory; -import net.jpountz.lz4.LZ4FastDecompressor; +import io.anuke.mindustry.net.Net.*; +import io.anuke.mindustry.net.Packets.*; +import net.jpountz.lz4.*; import java.io.IOException; import java.net.*; import java.nio.*; import java.nio.channels.ClosedSelectorException; -import static io.anuke.mindustry.Vars.netClient; -import static io.anuke.mindustry.Vars.port; +import static io.anuke.mindustry.Vars.*; public class ArcNetClient implements ClientProvider{ final Client client; - final Array foundAddresses = new Array<>(); - final ClientDiscoveryHandler handler; + final Supplier packetSupplier = () -> new DatagramPacket(new byte[256], 256); final LZ4FastDecompressor decompressor = LZ4Factory.fastestInstance().fastDecompressor(); - Consumer lastCallback; public ArcNetClient(){ - handler = new ClientDiscoveryHandler(){ - @Override - public DatagramPacket newDatagramPacket(){ - return new DatagramPacket(new byte[256], 256); - } - - @Override - public void discoveredHost(DatagramPacket datagramPacket){ - ByteBuffer buffer = ByteBuffer.wrap(datagramPacket.getData()); - Host host = NetworkIO.readServerData(datagramPacket.getAddress().getHostAddress(), buffer); - for(InetAddress address : foundAddresses){ - if(address.equals(datagramPacket.getAddress()) || (isLocal(address) && isLocal(datagramPacket.getAddress()))){ - return; - } - } - Core.app.post(() -> lastCallback.accept(host)); - foundAddresses.add(datagramPacket.getAddress()); - } - - @Override - public void finish(){ - - } - }; - client = new Client(8192, 4096, new PacketSerializer()); - client.setDiscoveryHandler(handler); + client.setDiscoveryPacket(packetSupplier); NetListener listener = new NetListener(){ @Override @@ -172,40 +141,43 @@ public class ArcNetClient implements ClientProvider{ @Override public void pingHost(String address, int port, Consumer valid, Consumer invalid){ runAsync(() -> { - synchronized(handler){ - try{ - DatagramSocket socket = new DatagramSocket(); - socket.send(new DatagramPacket(new byte[]{-2, 1}, 2, InetAddress.getByName(address), port)); + try{ + DatagramSocket socket = new DatagramSocket(); + socket.send(new DatagramPacket(new byte[]{-2, 1}, 2, InetAddress.getByName(address), port)); + socket.setSoTimeout(2000); - socket.setSoTimeout(2000); + DatagramPacket packet = packetSupplier.get(); + socket.receive(packet); - lastCallback = valid; + ByteBuffer buffer = ByteBuffer.wrap(packet.getData()); + Host host = NetworkIO.readServerData(packet.getAddress().getHostAddress(), buffer); - DatagramPacket packet = handler.newDatagramPacket(); - - socket.receive(packet); - - ByteBuffer buffer = ByteBuffer.wrap(packet.getData()); - Host host = NetworkIO.readServerData(packet.getAddress().getHostAddress(), buffer); - - Core.app.post(() -> valid.accept(host)); - }catch(Exception e){ - Core.app.post(() -> invalid.accept(e)); - } + Core.app.post(() -> valid.accept(host)); + }catch(Exception e){ + Core.app.post(() -> invalid.accept(e)); } }); } @Override public void discover(Consumer callback, Runnable done){ - runAsync(() -> { - synchronized(handler){ - foundAddresses.clear(); - lastCallback = callback; - client.discoverHosts(port, 3000); - Core.app.post(done); - } - }); + Array foundAddresses = new Array<>(); + client.discoverHosts(port, multicastGroup, multicastPort, 3000, packet -> { + Core.app.post(() -> { + try{ + if(foundAddresses.contains(address -> address.equals(packet.getAddress()) || (isLocal(address) && isLocal(packet.getAddress())))){ + return; + } + ByteBuffer buffer = ByteBuffer.wrap(packet.getData()); + Host host = NetworkIO.readServerData(packet.getAddress().getHostAddress(), buffer); + callback.accept(host); + foundAddresses.add(packet.getAddress()); + }catch(Exception e){ + //don't crash when there's an error pinging a a server or parsing data + e.printStackTrace(); + } + }); + }, () -> Core.app.post(done)); } @Override diff --git a/net/src/io/anuke/mindustry/net/ArcNetServer.java b/net/src/io/anuke/mindustry/net/ArcNetServer.java index 0110523061..0da624635e 100644 --- a/net/src/io/anuke/mindustry/net/ArcNetServer.java +++ b/net/src/io/anuke/mindustry/net/ArcNetServer.java @@ -19,6 +19,8 @@ import java.nio.channels.ClosedSelectorException; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; +import static io.anuke.mindustry.Vars.*; + public class ArcNetServer implements ServerProvider{ final Server server; final CopyOnWriteArrayList connections = new CopyOnWriteArrayList<>(); @@ -31,10 +33,11 @@ public class ArcNetServer implements ServerProvider{ public ArcNetServer(){ server = new Server(4096 * 2, 4096, new PacketSerializer()); - server.setDiscoveryHandler((datagramChannel, fromAddress) -> { + server.setMulticast(multicastGroup, multicastPort); + server.setDiscoveryHandler((address, handler) -> { ByteBuffer buffer = NetworkIO.writeServerData(); buffer.position(0); - datagramChannel.send(buffer, fromAddress); + handler.respond(buffer); }); NetListener listener = new NetListener(){