Inter server teleporting is there, albeit slightly borked

This commit is contained in:
md_5 2012-10-05 14:49:29 +10:00
parent b53f66b6ac
commit 093f45463a
6 changed files with 203 additions and 11 deletions

View File

@ -14,7 +14,9 @@ import java.util.concurrent.Executors;
import static net.md_5.bungee.Logger.$; import static net.md_5.bungee.Logger.$;
import net.md_5.bungee.command.Command; import net.md_5.bungee.command.Command;
import net.md_5.bungee.command.CommandEnd; import net.md_5.bungee.command.CommandEnd;
import net.md_5.bungee.command.CommandList;
import net.md_5.bungee.command.CommandSender; import net.md_5.bungee.command.CommandSender;
import net.md_5.bungee.command.CommandServer;
import net.md_5.bungee.command.ConsoleCommandSender; import net.md_5.bungee.command.ConsoleCommandSender;
public class BungeeCord { public class BungeeCord {
@ -58,6 +60,8 @@ public class BungeeCord {
{ {
commandMap.put("end", new CommandEnd()); commandMap.put("end", new CommandEnd());
commandMap.put("glist", new CommandList());
commandMap.put("server", new CommandServer());
} }
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {

View File

@ -194,10 +194,11 @@ public class Configuration {
public InetSocketAddress getServer(String name) { public InetSocketAddress getServer(String name) {
String hostline = (name == null) ? defaultServerName : name; String hostline = (name == null) ? defaultServerName : name;
if (hostline != null) { String server = servers.get(hostline);
return Util.getAddr(hostline); if (server != null) {
return Util.getAddr(server);
} else { } else {
throw new IllegalArgumentException("No server by name " + name); return Util.getAddr(servers.get(defaultServerName));
} }
} }

View File

@ -0,0 +1,61 @@
package net.md_5.bungee;
public class EntityMap {
public final static int[][] entityIds = new int[256][];
static {
entityIds[0x05] = new int[]{1};
entityIds[0x07] = new int[]{1, 5};
entityIds[0x11] = new int[]{1};
entityIds[0x12] = new int[]{1};
entityIds[0x13] = new int[]{1};
entityIds[0x14] = new int[]{1};
entityIds[0x15] = new int[]{1};
entityIds[0x16] = new int[]{1, 5};
entityIds[0x17] = new int[]{1};
entityIds[0x18] = new int[]{1};
entityIds[0x19] = new int[]{1};
entityIds[0x1C] = new int[]{1};
entityIds[0x1E] = new int[]{1};
entityIds[0x1F] = new int[]{1};
entityIds[0x20] = new int[]{1};
entityIds[0x21] = new int[]{1};
entityIds[0x22] = new int[]{1};
entityIds[0x26] = new int[]{1};
entityIds[0x27] = new int[]{1, 5};
entityIds[0x28] = new int[]{1};
entityIds[0x47] = new int[]{1};
}
public static void rewrite(byte[] packet, int oldId, int newId) {
int packetId = Util.getId(packet);
if (packetId == 0x1D) { // bulk entity
for (int pos = 2; pos < packet.length; pos += 4) {
if (oldId == readInt(packet, pos)) {
setInt(packet, pos, newId);
}
}
} else {
int[] idArray = entityIds[packetId];
if (idArray != null) {
for (int pos : idArray) {
if (oldId == readInt(packet, pos)) {
setInt(packet, pos, newId);
}
}
}
}
}
private static void setInt(byte[] buf, int pos, int i) {
buf[pos] = (byte) (i >> 24);
buf[pos + 1] = (byte) (i >> 16);
buf[pos + 2] = (byte) (i >> 8);
buf[pos + 3] = (byte) i;
}
private static int readInt(byte[] buf, int pos) {
return (((buf[pos] & 0xFF) << 24) | ((buf[pos + 1] & 0xFF) << 16) | ((buf[pos + 2] & 0xFF) << 8) | buf[pos + 3] & 0xFF);
}
}

View File

@ -6,18 +6,28 @@ import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import net.md_5.bungee.command.CommandSender;
import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.DefinedPacket;
import net.md_5.bungee.packet.Packet10HeldItem;
import net.md_5.bungee.packet.Packet1Login;
import net.md_5.bungee.packet.Packet2Handshake; import net.md_5.bungee.packet.Packet2Handshake;
import net.md_5.bungee.packet.Packet3Chat; import net.md_5.bungee.packet.Packet3Chat;
import net.md_5.bungee.packet.Packet46GameState;
import net.md_5.bungee.packet.Packet9Respawn;
import net.md_5.bungee.packet.PacketFAPluginMessage;
import net.md_5.bungee.packet.PacketInputStream; import net.md_5.bungee.packet.PacketInputStream;
public class UserConnection extends GenericConnection { public class UserConnection extends GenericConnection implements CommandSender {
public final Packet2Handshake handshake; public final Packet2Handshake handshake;
public Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>(); public Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>();
private ServerConnection server; private ServerConnection server;
private UpstreamBridge upBridge; private UpstreamBridge upBridge;
private DownstreamBridge downBridge; private DownstreamBridge downBridge;
// reconnect stuff
private Packet10HeldItem heldItem;
private int clientEntityId;
private int serverEntityId;
public UserConnection(Socket socket, PacketInputStream in, OutputStream out, Packet2Handshake handshake) { public UserConnection(Socket socket, PacketInputStream in, OutputStream out, Packet2Handshake handshake) {
super(socket, in, out); super(socket, in, out);
@ -25,16 +35,37 @@ public class UserConnection extends GenericConnection {
username = handshake.username; username = handshake.username;
} }
public void connect(String server) {
InetSocketAddress addr = BungeeCord.instance.config.getServer(server);
if (addr == null) {
sendMessage(ChatColor.RED + "Specified server does not exist");
return;
}
connect(addr);
}
public void connect(InetSocketAddress serverAddr) { public void connect(InetSocketAddress serverAddr) {
try { try {
ServerConnection newServer = ServerConnection.connect(serverAddr, handshake, true); ServerConnection newServer = ServerConnection.connect(serverAddr, handshake, true);
if (downBridge != null) {
downBridge.interrupt();
}
if (server == null) { if (server == null) {
clientEntityId = newServer.loginPacket.entityId;
out.write(newServer.loginPacket.getPacket()); out.write(newServer.loginPacket.getPacket());
upBridge = new UpstreamBridge(); upBridge = new UpstreamBridge();
upBridge.start(); upBridge.start();
} else {
server.disconnect("Quitting");
out.write(new Packet9Respawn((byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT").getPacket());
out.write(new Packet9Respawn((byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT").getPacket());
out.write(new Packet46GameState((byte) 2, (byte) 0).getPacket());
Packet1Login login = newServer.loginPacket;
serverEntityId = login.entityId;
out.write(new Packet9Respawn(login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType).getPacket());
if (heldItem != null) {
newServer.out.write(heldItem.getPacket());
} }
if (downBridge != null) {
downBridge.interrupt();
} }
downBridge = new DownstreamBridge(); downBridge = new DownstreamBridge();
server = newServer; server = newServer;
@ -70,6 +101,11 @@ public class UserConnection extends GenericConnection {
} }
} }
@Override
public void sendMessage(String message) {
packetQueue.add(new Packet3Chat(message));
}
private class UpstreamBridge extends Thread { private class UpstreamBridge extends Thread {
public UpstreamBridge() { public UpstreamBridge() {
@ -81,7 +117,23 @@ public class UserConnection extends GenericConnection {
while (!interrupted()) { while (!interrupted()) {
try { try {
byte[] packet = in.readPacket(); byte[] packet = in.readPacket();
boolean sendPacket = true;
int id = Util.getId(packet);
if (id == 0x03) {
Packet3Chat chat = new Packet3Chat(packet);
String message = chat.message;
if (message.startsWith("/")) {
sendPacket = !BungeeCord.instance.dispatchCommand(message.substring(1), UserConnection.this);
}
} else if (id == 0x10) {
heldItem = new Packet10HeldItem(packet);
}
EntityMap.rewrite(packet, clientEntityId, serverEntityId);
if (sendPacket && !server.socket.isClosed()) {
server.out.write(packet); server.out.write(packet);
}
} catch (IOException ex) { } catch (IOException ex) {
destory("Reached end of stream"); destory("Reached end of stream");
} catch (Exception ex) { } catch (Exception ex) {
@ -102,10 +154,30 @@ public class UserConnection extends GenericConnection {
while (!interrupted()) { while (!interrupted()) {
try { try {
byte[] packet = server.in.readPacket(); byte[] packet = server.in.readPacket();
boolean sendPacket = true;
int id = Util.getId(packet);
if (id == 0xFA) {
PacketFAPluginMessage message = new PacketFAPluginMessage(packet);
if (message.tag.equals("RubberBand")) {
String server = new String(message.data);
connect(server);
sendPacket = false;
}
}
while (!packetQueue.isEmpty()) {
DefinedPacket p = packetQueue.poll();
if (p != null) {
out.write(p.getPacket());
}
}
EntityMap.rewrite(packet, serverEntityId, clientEntityId);
if (sendPacket) {
out.write(packet); out.write(packet);
out.flush(); }
} catch (IOException ex) { } catch (IOException ex) {
destory("Reached end of stream");
} catch (Exception ex) { } catch (Exception ex) {
destory(Util.exception(ex)); destory(Util.exception(ex));
} }

View File

@ -0,0 +1,24 @@
package net.md_5.bungee.command;
import java.util.Collection;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.ChatColor;
import net.md_5.bungee.UserConnection;
public class CommandList extends Command {
@Override
public void execute(CommandSender sender, String[] args) {
StringBuilder users = new StringBuilder();
Collection<UserConnection> connections = BungeeCord.instance.connections.values();
for (UserConnection con : connections) {
users.append(con.username);
users.append(ChatColor.RESET.toString());
users.append(", ");
}
users.setLength(users.length() - 2);
sender.sendMessage(ChatColor.BLUE + "Currently online across all servers (" + connections.size() + "): " + ChatColor.RESET + users);
}
}

View File

@ -0,0 +1,30 @@
package net.md_5.bungee.command;
import java.util.Collection;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.ChatColor;
import net.md_5.bungee.UserConnection;
public class CommandServer extends Command {
@Override
public void execute(CommandSender sender, String[] args) {
if (!(sender instanceof UserConnection)) {
return;
}
UserConnection con = (UserConnection) sender;
if (args.length <= 0) {
Collection<String> servers = BungeeCord.instance.config.servers.keySet();
StringBuilder serverList = new StringBuilder();
for (String server : servers) {
serverList.append(server);
serverList.append(", ");
}
serverList.setLength(serverList.length() - 2);
con.sendMessage(ChatColor.GOLD + "You may connect to the following servers at this time: " + serverList.toString());
} else {
String server = args[0];
con.connect(server);
}
}
}