Automatically queue packets to send when a player connects, and change the API regarding this. Please don't use the Server methods anymore, instead use ServerInfo.

CC: @TheDgtl
This commit is contained in:
md_5 2013-01-31 20:51:59 +11:00
parent 0721e3cc75
commit ecf5b4dc30
7 changed files with 128 additions and 32 deletions

View File

@ -2,6 +2,7 @@ package net.md_5.bungee.api;
import net.md_5.bungee.api.plugin.PluginManager; import net.md_5.bungee.api.plugin.PluginManager;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.net.InetSocketAddress;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -75,7 +76,11 @@ public abstract class ProxyServer
* *
* @param name the name to lookup * @param name the name to lookup
* @return the associated server * @return the associated server
* @deprecated in most cases the {@link #getServerInfo(java.lang.String)}
* method should be used, as it will return a server even when no players
* are online.
*/ */
@Deprecated
public abstract Server getServer(String name); public abstract Server getServer(String name);
/** /**
@ -196,4 +201,14 @@ public abstract class ProxyServer
* @return the Minecraft protocol version * @return the Minecraft protocol version
*/ */
public abstract byte getProtocolVersion(); public abstract byte getProtocolVersion();
/**
* Factory method to construct an implementation specific server info
* instance.
*
* @param name name of the server
* @param address connectable Minecraft address + port of the server
* @return the constructed instance
*/
public abstract ServerInfo constructServerInfo(String name, InetSocketAddress address);
} }

View File

@ -7,6 +7,8 @@ import java.util.Collections;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.Synchronized; import lombok.Synchronized;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
/** /**
@ -14,7 +16,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
*/ */
@Data @Data
@AllArgsConstructor @AllArgsConstructor
public class ServerInfo public abstract class ServerInfo
{ {
/** /**
@ -62,4 +64,19 @@ public class ServerInfo
{ {
return Collections.unmodifiableCollection(players); return Collections.unmodifiableCollection(players);
} }
/**
* Send data by any available means to this server.
*
* @param channel the channel to send this data via
* @param data the data to send
*/
public abstract void sendData(String channel, byte[] data);
/**
* Asynchronously gets the current player count on this server.
*
* @param callback the callback to call when the count has been retrieved.
*/
public abstract void ping(Callback<ServerPing> callback);
} }

View File

@ -1,8 +1,8 @@
package net.md_5.bungee.api.connection; package net.md_5.bungee.api.connection;
import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.config.ServerInfo;
/** /**
* Represents a destination which this proxy might connect to. * Represents a destination which this proxy might connect to.
@ -29,6 +29,9 @@ public interface Server extends Connection
* Asynchronously gets the current player count on this server. * Asynchronously gets the current player count on this server.
* *
* @param callback the callback to call when the count has been retrieved. * @param callback the callback to call when the count has been retrieved.
* @deprecated use the corresponding method in {@link ServerInfo} for
* clarity
*/ */
@Deprecated
public abstract void ping(Callback<ServerPing> callback); public abstract void ping(Callback<ServerPing> callback);
} }

View File

@ -5,6 +5,7 @@ import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -339,4 +340,10 @@ public class BungeeCord extends ProxyServer
{ {
return GAME_VERSION; return GAME_VERSION;
} }
@Override
public ServerInfo constructServerInfo(String name, InetSocketAddress address)
{
return new BungeeServerInfo(name, address);
}
} }

View File

@ -0,0 +1,76 @@
package net.md_5.bungee;
import java.io.DataOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import lombok.Getter;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.packet.DefinedPacket;
import net.md_5.bungee.packet.PacketFAPluginMessage;
import net.md_5.bungee.packet.PacketFFKick;
import net.md_5.bungee.packet.PacketInputStream;
public class BungeeServerInfo extends ServerInfo
{
@Getter
private final Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>();
public BungeeServerInfo(String name, InetSocketAddress address)
{
super(name, address);
}
@Override
public void sendData(String channel, byte[] data)
{
Server server = ProxyServer.getInstance().getServer(getName());
if (server != null)
{
server.sendData(channel, data);
} else
{
packetQueue.add(new PacketFAPluginMessage(channel, data));
}
}
@Override
public void ping(final Callback<ServerPing> callback)
{
new Thread()
{
@Override
public void run()
{
try
{
Socket socket = new Socket();
socket.connect(getAddress());
try (DataOutputStream out = new DataOutputStream(socket.getOutputStream()))
{
out.write(0xFE);
out.write(0x01);
}
try (PacketInputStream in = new PacketInputStream(socket.getInputStream()))
{
PacketFFKick response = new PacketFFKick(in.readPacket());
String[] split = response.message.split("\00");
ServerPing ping = new ServerPing(Byte.parseByte(split[1]), split[2], split[3], Integer.parseInt(split[4]), Integer.parseInt(split[5]));
callback.done(ping, null);
}
} catch (Throwable t)
{
callback.done(null, t);
}
}
}.start();
}
}

View File

@ -95,6 +95,12 @@ public class ServerConnection extends GenericConnection implements Server
out.write(BungeeCord.getInstance().registerChannels().getPacket()); out.write(BungeeCord.getInstance().registerChannels().getPacket());
Queue<DefinedPacket> packetQueue = ((BungeeServerInfo) info).getPacketQueue();
while (!packetQueue.isEmpty())
{
out.write(packetQueue.poll().getPacket());
}
return server; return server;
} catch (KickException ex) } catch (KickException ex)
{ {
@ -122,35 +128,7 @@ public class ServerConnection extends GenericConnection implements Server
@Override @Override
public void ping(final Callback<ServerPing> callback) public void ping(final Callback<ServerPing> callback)
{ {
new Thread() getInfo().ping(callback);
{
@Override
public void run()
{
try
{
Socket socket = new Socket();
socket.connect(getAddress());
try (DataOutputStream out = new DataOutputStream(socket.getOutputStream()))
{
out.write(0xFE);
out.write(0x01);
}
try (PacketInputStream in = new PacketInputStream(socket.getInputStream()))
{
PacketFFKick response = new PacketFFKick(in.readPacket());
String[] split = response.message.split("\00");
ServerPing ping = new ServerPing(Byte.parseByte(split[1]), split[2], split[3], Integer.parseInt(split[4]), Integer.parseInt(split[5]));
callback.done(ping, null);
}
} catch (Throwable t)
{
callback.done(null, t);
}
}
}.start();
} }
@Override @Override

View File

@ -151,7 +151,7 @@ public class YamlConfig implements ConfigurationAdapter
String name = entry.getKey(); String name = entry.getKey();
String addr = get("address", "localhost:25565", val); String addr = get("address", "localhost:25565", val);
InetSocketAddress address = Util.getAddr(addr); InetSocketAddress address = Util.getAddr(addr);
ServerInfo info = new ServerInfo(name, address); ServerInfo info = ProxyServer.getInstance().constructServerInfo(name, address);
ret.put(name, info); ret.put(name, info);
} }