Inter server teleporting is there, albeit slightly borked
This commit is contained in:
parent
b53f66b6ac
commit
093f45463a
@ -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 {
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
src/main/java/net/md_5/bungee/EntityMap.java
Normal file
61
src/main/java/net/md_5/bungee/EntityMap.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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 {
|
||||||
if (downBridge != null) {
|
server.disconnect("Quitting");
|
||||||
downBridge.interrupt();
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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();
|
||||||
server.out.write(packet);
|
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);
|
||||||
|
}
|
||||||
} 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();
|
||||||
out.write(packet);
|
boolean sendPacket = true;
|
||||||
out.flush();
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
} 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));
|
||||||
}
|
}
|
||||||
|
24
src/main/java/net/md_5/bungee/command/CommandList.java
Normal file
24
src/main/java/net/md_5/bungee/command/CommandList.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
30
src/main/java/net/md_5/bungee/command/CommandServer.java
Normal file
30
src/main/java/net/md_5/bungee/command/CommandServer.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user