mirror of
https://github.com/ayunami2000/ayungee.git
synced 2024-12-30 02:14:11 -08:00
make it actually connect servers now :D
crazy right??!?!?!???!
This commit is contained in:
parent
75423d4ea5
commit
9c9d3c28eb
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
|||
web
|
||||
target/*
|
||||
!target/ayungee-1.0-SNAPSHOT-jar-with-dependencies.jar
|
||||
test
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
lightweight bungeecord alternative for eaglercraft servers running protocolsupport
|
||||
|
||||
Thanks to LAX1DUDE for very small snippets of EaglerBungee used in this project (specifically for the server icon)
|
||||
Thanks to LAX1DUDE and md-5 for very small snippets of EaglerBungee used in this project (specifically for the server icon, skins, & entity remapping)
|
||||
|
||||
**TODO: skins & capes**
|
||||
**TODO: ability for plugins to change a player's server & built-in auth system**
|
||||
|
||||
|
||||
|
||||
**if you have questions about the license, please, reach out to me. i just put the license i put on most of my projects on this, but if you have a problem with it, let me know.
|
||||
|
|
|
@ -16,10 +16,17 @@ public class Client {
|
|||
|
||||
public String username;
|
||||
|
||||
public int server = 0;
|
||||
|
||||
public byte[] handshake = null;
|
||||
|
||||
public int clientEntityId;
|
||||
public int serverEntityId;
|
||||
|
||||
public void setSocket(Socket sock) throws IOException {
|
||||
socket = sock;
|
||||
socketOut = sock.getOutputStream();
|
||||
socketIn = socket.getInputStream();
|
||||
socketIn = sock.getInputStream();
|
||||
}
|
||||
|
||||
public Client(String uname) {
|
||||
|
|
81
src/main/java/me/ayunami2000/ayungee/EntityMap.java
Normal file
81
src/main/java/me/ayunami2000/ayungee/EntityMap.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
package me.ayunami2000.ayungee;
|
||||
|
||||
// https://github.com/LAX1DUDE/eaglercraft/blob/a8d5c856de28ba2a263abc055d7b26d50dc2bf7e/eaglercraftbungee/src/main/java/net/md_5/bungee/EntityMap.java
|
||||
|
||||
public class EntityMap {
|
||||
public static final int[][] entityIds;
|
||||
|
||||
public static void rewrite(final byte[] packet, final int oldId, final int newId) {
|
||||
final int packetId = packet[0] & 0xFF;
|
||||
if (packetId == 29) {
|
||||
for (int pos = 2; pos < (short) ((packet[1] << 8) + packet[2] & 0xff); pos += 4) {
|
||||
final int readId = readInt(packet, pos);
|
||||
if (readId == oldId) {
|
||||
setInt(packet, pos, newId);
|
||||
} else if (readId == newId) {
|
||||
setInt(packet, pos, oldId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final int[] idArray = EntityMap.entityIds[packetId];
|
||||
if (idArray != null) {
|
||||
for (final int pos2 : idArray) {
|
||||
final int readId2 = readInt(packet, pos2);
|
||||
if (readId2 == oldId) {
|
||||
setInt(packet, pos2, newId);
|
||||
} else if (readId2 == newId) {
|
||||
setInt(packet, pos2, oldId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (packetId == 23) {
|
||||
final int type = packet[5] & 0xFF;
|
||||
if (type == 60 || type == 90) {
|
||||
final int index20 = readInt(packet, 20);
|
||||
if (packet.length > 24 && index20 == oldId) {
|
||||
setInt(packet, 20, newId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setInt(final byte[] buf, final int pos, final int i) {
|
||||
buf[pos] = (byte) (i >> 24);
|
||||
buf[pos + 1] = (byte) (i >> 16);
|
||||
buf[pos + 2] = (byte) (i >> 8);
|
||||
buf[pos + 3] = (byte) i;
|
||||
}
|
||||
|
||||
public static int readInt(final byte[] buf, final int pos) {
|
||||
return (buf[pos] & 0xFF) << 24 | (buf[pos + 1] & 0xFF) << 16 | (buf[pos + 2] & 0xFF) << 8 | (buf[pos + 3] & 0xFF);
|
||||
}
|
||||
|
||||
static {
|
||||
(entityIds = new int[256][])[5] = new int[] { 1 };
|
||||
EntityMap.entityIds[7] = new int[] { 1, 5 };
|
||||
EntityMap.entityIds[17] = new int[] { 1 };
|
||||
EntityMap.entityIds[18] = new int[] { 1 };
|
||||
EntityMap.entityIds[19] = new int[] { 1 };
|
||||
EntityMap.entityIds[20] = new int[] { 1 };
|
||||
EntityMap.entityIds[22] = new int[] { 1, 5 };
|
||||
EntityMap.entityIds[23] = new int[] { 1 };
|
||||
EntityMap.entityIds[24] = new int[] { 1 };
|
||||
EntityMap.entityIds[25] = new int[] { 1 };
|
||||
EntityMap.entityIds[26] = new int[] { 1 };
|
||||
EntityMap.entityIds[28] = new int[] { 1 };
|
||||
EntityMap.entityIds[30] = new int[] { 1 };
|
||||
EntityMap.entityIds[31] = new int[] { 1 };
|
||||
EntityMap.entityIds[32] = new int[] { 1 };
|
||||
EntityMap.entityIds[33] = new int[] { 1 };
|
||||
EntityMap.entityIds[34] = new int[] { 1 };
|
||||
EntityMap.entityIds[35] = new int[] { 1 };
|
||||
EntityMap.entityIds[38] = new int[] { 1 };
|
||||
EntityMap.entityIds[39] = new int[] { 1, 5 };
|
||||
EntityMap.entityIds[40] = new int[] { 1 };
|
||||
EntityMap.entityIds[41] = new int[] { 1 };
|
||||
EntityMap.entityIds[42] = new int[] { 1 };
|
||||
EntityMap.entityIds[55] = new int[] { 1 };
|
||||
EntityMap.entityIds[71] = new int[] { 1 };
|
||||
}
|
||||
}
|
|
@ -7,9 +7,7 @@ import org.yaml.snakeyaml.Yaml;
|
|||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
@ -19,8 +17,7 @@ import java.util.regex.Pattern;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public static String hostname = "localhost";
|
||||
public static int port = 25569;
|
||||
public static List<ServerItem> servers = new ArrayList<>();
|
||||
public static int webPort = 25565;
|
||||
|
||||
public static String motdJson = "";
|
||||
|
@ -28,8 +25,6 @@ public class Main {
|
|||
|
||||
public static boolean forwarded = false;
|
||||
|
||||
public static boolean eaglerPackets = false;
|
||||
|
||||
public static WebSocketServer webSocketServer = null;
|
||||
|
||||
public static Map<WebSocket, Client> clients = new HashMap<>();
|
||||
|
@ -107,12 +102,19 @@ public class Main {
|
|||
}).start();
|
||||
}
|
||||
|
||||
servers.add(new ServerItem("localhost", 25569));
|
||||
|
||||
List<String> stringServers = (List<String>) config.getOrDefault("servers", new ArrayList<>());
|
||||
|
||||
if (!stringServers.isEmpty()) {
|
||||
servers.clear();
|
||||
for (String serverEntry : stringServers) {
|
||||
servers.add(new ServerItem(serverEntry));
|
||||
}
|
||||
}
|
||||
|
||||
hostname = (String) config.getOrDefault("hostname", "localhost");
|
||||
port = (int) config.getOrDefault("port", 25569);
|
||||
webPort = (int) config.getOrDefault("web_port", 25565);
|
||||
forwarded = (boolean) config.getOrDefault("forwarded", false);
|
||||
eaglerPackets = (boolean) config.getOrDefault("eag_packets", false);
|
||||
|
||||
List<String> defaultMotd = new ArrayList<>();
|
||||
|
||||
|
@ -168,7 +170,7 @@ public class Main {
|
|||
switch (pieces[0]) {
|
||||
case "help":
|
||||
case "?":
|
||||
System.out.println("help ; unban <ip> ; banip <ip> ; ban <username> ; stop");
|
||||
System.out.println("help ; unban <ip> ; banip <ip> ; ban <username> ; send <username> <serverid> ; stop");
|
||||
break;
|
||||
case "unban":
|
||||
case "pardon":
|
||||
|
@ -229,6 +231,24 @@ public class Main {
|
|||
System.out.println("IP " + pieces[1] + " is already banned!");
|
||||
}
|
||||
break;
|
||||
case "send":
|
||||
case "server":
|
||||
if (pieces.length == 1 || pieces.length == 2) {
|
||||
System.out.println("Usage: " + pieces[0] + " <username> <serverindex>");
|
||||
break;
|
||||
}
|
||||
Client targetUser = clients.values().stream().filter(client -> client.username.equals(pieces[1])).findFirst().orElse(clients.values().stream().filter(client -> client.username.equalsIgnoreCase(pieces[1])).findFirst().orElse(null));
|
||||
if (targetUser == null) {
|
||||
System.out.println("Unable to find any user with that username!");
|
||||
break;
|
||||
}
|
||||
try {
|
||||
int destServer = Integer.parseInt(pieces[2]);
|
||||
targetUser.server = Math.max(0, Math.min(servers.size() - 1, destServer));
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("That is not a valid number!");
|
||||
}
|
||||
break;
|
||||
case "stop":
|
||||
case "end":
|
||||
case "exit":
|
||||
|
|
17
src/main/java/me/ayunami2000/ayungee/ServerItem.java
Normal file
17
src/main/java/me/ayunami2000/ayungee/ServerItem.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
package me.ayunami2000.ayungee;
|
||||
|
||||
public class ServerItem {
|
||||
public String host;
|
||||
public int port = 25565;
|
||||
|
||||
public ServerItem(String h, int p) {
|
||||
host = h;
|
||||
port = p;
|
||||
}
|
||||
|
||||
public ServerItem(String hp) {
|
||||
String[] pieces = hp.split(":");
|
||||
if (pieces.length > 1) port = Integer.parseInt(pieces[1]);
|
||||
host = pieces[0];
|
||||
}
|
||||
}
|
115
src/main/java/me/ayunami2000/ayungee/Skins.java
Normal file
115
src/main/java/me/ayunami2000/ayungee/Skins.java
Normal file
|
@ -0,0 +1,115 @@
|
|||
package me.ayunami2000.ayungee;
|
||||
|
||||
import org.java_websocket.WebSocket;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Skins {
|
||||
private static final HashMap<String,byte[]> skinCollection = new HashMap();
|
||||
private static final HashMap<String,byte[]> capeCollection = new HashMap();
|
||||
private static final HashMap<String,Long> lastSkinLayerUpdate = new HashMap();
|
||||
|
||||
private static final int[] SKIN_DATA_SIZE = new int[] { 64*32*4, 64*64*4, -9, -9, 1, 64*64*4, -9 }; // 128 pixel skins crash clients
|
||||
private static final int[] CAPE_DATA_SIZE = new int[] { 32*32*4, -9, 1 };
|
||||
|
||||
public static boolean setSkin(String user, WebSocket conn, byte[] initMsg) {
|
||||
if(initMsg.length >= 3) {
|
||||
try {
|
||||
ByteBuffer bb = ByteBuffer.wrap(initMsg);
|
||||
bb.get();
|
||||
int tagLen = bb.getShort();
|
||||
if (!(tagLen >= 0 && tagLen < initMsg.length - 1)) return false;
|
||||
StringBuilder tagBuilder = new StringBuilder();
|
||||
for (int i = 0; i < tagLen; i++) tagBuilder.append(bb.getChar());
|
||||
//int dataLen = bb.getShort();
|
||||
int dataLen = bb.remaining() - 2;
|
||||
String tag = tagBuilder.toString();
|
||||
int offset = 3 + tagLen * 2 + 2;
|
||||
byte[] msg = new byte[dataLen];
|
||||
System.arraycopy(initMsg, offset, msg, 0, dataLen);
|
||||
if("EAG|MySkin".equals(tag)) {
|
||||
if(!skinCollection.containsKey(user)) {
|
||||
int t = (int)msg[0] & 0xFF;
|
||||
if(t >= 0 && t < SKIN_DATA_SIZE.length && msg.length == (SKIN_DATA_SIZE[t] + 1)) {
|
||||
skinCollection.put(user, msg);
|
||||
}
|
||||
}
|
||||
}else if("EAG|MyCape".equals(tag)) {
|
||||
if(!capeCollection.containsKey(user)) {
|
||||
int t = (int)msg[0] & 0xFF;
|
||||
if(t >= 0 && t < CAPE_DATA_SIZE.length && msg.length == (CAPE_DATA_SIZE[t] + 2)) {
|
||||
capeCollection.put(user, msg);
|
||||
}
|
||||
}
|
||||
}else if("EAG|FetchSkin".equals(tag)) {
|
||||
if(msg.length > 2) {
|
||||
String fetch = new String(msg, 2, msg.length - 2, StandardCharsets.UTF_8);
|
||||
byte[] data;
|
||||
if((data = skinCollection.get(fetch)) != null) {
|
||||
byte[] conc = new byte[data.length + 2];
|
||||
conc[0] = msg[0]; conc[1] = msg[1]; //synchronization cookie
|
||||
System.arraycopy(data, 0, conc, 2, data.length);
|
||||
if((data = capeCollection.get(fetch)) != null) {
|
||||
byte[] conc2 = new byte[conc.length + data.length];
|
||||
System.arraycopy(conc, 0, conc2, 0, conc.length);
|
||||
System.arraycopy(data, 0, conc2, conc.length, data.length);
|
||||
conc = conc2;
|
||||
}
|
||||
byte[] packetPrefix = new byte[] { (byte) 250, 0, 12, 0, 69, 0, 65, 0, 71, 0, 124, 0, 85, 0, 115, 0, 101, 0, 114, 0, 83, 0, 107, 0, 105, 0, 110, (byte) ((conc.length >>> 8) & 0xFF), (byte) (conc.length & 0xFF) };
|
||||
byte[] fullPacket = new byte[packetPrefix.length + conc.length];
|
||||
System.arraycopy(packetPrefix, 0, fullPacket, 0, packetPrefix.length);
|
||||
System.arraycopy(conc, 0, fullPacket, packetPrefix.length, conc.length);
|
||||
conn.send(fullPacket);
|
||||
}
|
||||
}
|
||||
}else if("EAG|SkinLayers".equals(tag)) {
|
||||
long millis = System.currentTimeMillis();
|
||||
Long lsu = lastSkinLayerUpdate.get(user);
|
||||
if(lsu != null && millis - lsu.longValue() < 700l) { // DoS protection
|
||||
return false;
|
||||
}
|
||||
lastSkinLayerUpdate.put(user, millis);
|
||||
byte[] data;
|
||||
if((data = capeCollection.get(user)) != null) {
|
||||
data[1] = msg[0];
|
||||
}else {
|
||||
data = new byte[] { (byte)2, msg[0], (byte)0 };
|
||||
capeCollection.put(user, data);
|
||||
}
|
||||
ByteArrayOutputStream bao = new ByteArrayOutputStream();
|
||||
DataOutputStream dd = new DataOutputStream(bao);
|
||||
dd.write(msg[0]);
|
||||
dd.writeUTF(user);
|
||||
byte[] bpacket = bao.toByteArray();
|
||||
byte[] packetPrefix = new byte[] { (byte) 250, 0, 14, 0, 69, 0, 65, 0, 71, 0, 124, 0, 83, 0, 107, 0, 105, 0, 110, 0, 76, 0, 97, 0, 121, 0, 101, 0, 114, 0, 115, (byte) ((bpacket.length >>> 8) & 0xFF), (byte) (bpacket.length & 0xFF) };
|
||||
int off = bpacket.length == 0 ? 2 : 0;
|
||||
byte[] fullPacket = new byte[(packetPrefix.length - off) + bpacket.length];
|
||||
System.arraycopy(packetPrefix, 0, fullPacket, 0, packetPrefix.length - off);
|
||||
if (bpacket.length != 0) System.arraycopy(bpacket, 0, fullPacket, packetPrefix.length, bpacket.length);
|
||||
for (WebSocket pl : Main.clients.keySet()) {
|
||||
if (pl.equals(conn)) continue;
|
||||
if (pl.isOpen()) pl.send(fullPacket);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
// hacker
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void removeSkin(String username) {
|
||||
skinCollection.remove(username);
|
||||
capeCollection.remove(username);
|
||||
lastSkinLayerUpdate.remove(username);
|
||||
}
|
||||
}
|
|
@ -63,6 +63,7 @@ public class WebSocketProxy extends WebSocketServer {
|
|||
Client selfClient = Main.clients.remove(conn);
|
||||
if (selfClient != null) {
|
||||
System.out.println("Player " + selfClient.username + " (" + Main.getIp(conn) + ") left!");
|
||||
Skins.removeSkin(selfClient.username);
|
||||
if (selfClient.socket.isClosed()) {
|
||||
try {
|
||||
selfClient.socket.close();
|
||||
|
@ -88,7 +89,7 @@ public class WebSocketProxy extends WebSocketServer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(WebSocket conn, ByteBuffer message) {
|
||||
public void onMessage(WebSocket conn, ByteBuffer message) { // todo: make use of the fact that it's already a bytebuffer dumbass
|
||||
if (Main.bans.contains(Main.getIp(conn))) {
|
||||
conn.close();
|
||||
return;
|
||||
|
@ -97,60 +98,132 @@ public class WebSocketProxy extends WebSocketServer {
|
|||
byte[] msg = message.array();
|
||||
if (!Main.clients.containsKey(conn)) {
|
||||
if (msg.length > 3 && msg[1] == (byte) 69) {
|
||||
if (msg[3] < 3 || msg[3] > 16) {
|
||||
// todo: it uses shorts dumbass, get with the system
|
||||
short unameLen = (short) ((msg[2] << 8) + msg[3] & 0xff);
|
||||
if (unameLen < 3 || unameLen > 16) {
|
||||
conn.close();
|
||||
return;
|
||||
}
|
||||
byte[] uname = new byte[msg[3]];
|
||||
if (msg.length < 5 + msg[3] * 2) {
|
||||
conn.close();
|
||||
return;
|
||||
}
|
||||
byte[] uname = new byte[unameLen];
|
||||
for (int i = 0; i < uname.length; i++) uname[i] = msg[5 + i * 2];
|
||||
String username = new String(uname);
|
||||
Main.clients.put(conn, new Client(username));
|
||||
Client selfClient = new Client(username);
|
||||
Main.clients.put(conn, selfClient);
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Socket selfSocket = new Socket(Main.hostname, Main.port);
|
||||
Client selfClient = Main.clients.get(conn);
|
||||
selfClient.setSocket(selfSocket);
|
||||
while (selfClient.msgCache.size() > 0) selfClient.socketOut.write(selfClient.msgCache.remove(0));
|
||||
while (conn.isOpen() && !selfSocket.isInputShutdown()) {
|
||||
byte[] data = new byte[maxBuffSize];
|
||||
int read = selfClient.socketIn.read(data, 0, maxBuffSize);
|
||||
if (read == maxBuffSize) {
|
||||
boolean firstTime = true;
|
||||
while (conn.isOpen()) {
|
||||
int currServer = selfClient.server;
|
||||
ServerItem chosenServer = Main.servers.get(currServer);
|
||||
Socket selfSocket = new Socket(chosenServer.host, chosenServer.port);
|
||||
selfClient.setSocket(selfSocket);
|
||||
if (!firstTime) sendToServer(selfClient.handshake, selfClient);
|
||||
while (selfClient.msgCache.size() > 0) sendToServer(selfClient.msgCache.remove(0), selfClient);
|
||||
while (conn.isOpen() && !selfSocket.isInputShutdown() && selfClient.server == currServer) {
|
||||
byte[] dataa = new byte[maxBuffSize];
|
||||
int read = selfClient.socketIn.read(dataa, 0, maxBuffSize);
|
||||
byte[] data;
|
||||
if (read == maxBuffSize) {
|
||||
data = dataa;
|
||||
} else if (read > 0) {
|
||||
data = new byte[read];
|
||||
System.arraycopy(dataa, 0, data, 0, read);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (firstTime && data[0] == 1) selfClient.clientEntityId = selfClient.serverEntityId = EntityMap.readInt(data, 1);
|
||||
if (!firstTime && data[0] == 1) {
|
||||
selfClient.serverEntityId = EntityMap.readInt(data, 1);
|
||||
// assume server is giving valid data; we don't have to validate it because it isn't a potentially malicious client
|
||||
byte[] worldByte = new byte[data[6] * 2 + 2];
|
||||
System.arraycopy(data, 5, worldByte, 0, worldByte.length);
|
||||
byte gamemode = data[worldByte.length + 5];
|
||||
byte dimension = data[worldByte.length + 6];
|
||||
byte difficulty = data[worldByte.length + 7];
|
||||
Arrays.fill(data, (byte) 0);
|
||||
data[0] = 9;
|
||||
EntityMap.setInt(data, 1, dimension);
|
||||
data[5] = difficulty;
|
||||
data[6] = gamemode;
|
||||
data[7] = (byte)(256 & 0xff);
|
||||
data[8] = (byte)((256 >> 8) & 0xff);
|
||||
System.arraycopy(worldByte, 0, data, 9, worldByte.length);
|
||||
read = 9 + worldByte.length;
|
||||
byte[] trimData = new byte[read];
|
||||
System.arraycopy(data, 0, trimData, 0, read);
|
||||
data = trimData;
|
||||
if (conn.isOpen()) conn.send(new byte[] { 9, 0, 0, 0, 1, 0, 0, 1, 0, 0, 7, 0, 100, 0, 101, 0, 102, 0, 97, 0, 117, 0, 108, 0, 116 });
|
||||
if (conn.isOpen()) conn.send(new byte[] { 9, 0, 0, 0, -1, 0, 0, 1, 0, 0, 7, 0, 100, 0, 101, 0, 102, 0, 97, 0, 117, 0, 108, 0, 116 });
|
||||
}
|
||||
EntityMap.rewrite(data, selfClient.serverEntityId, selfClient.clientEntityId);
|
||||
if (conn.isOpen()) conn.send(data);
|
||||
} else if (read > 0) {
|
||||
byte[] trueData = new byte[read];
|
||||
System.arraycopy(data, 0, trueData, 0, read);
|
||||
if (conn.isOpen()) conn.send(trueData);
|
||||
}
|
||||
if (conn.isOpen() && selfClient.server == currServer) conn.close();
|
||||
if (!selfSocket.isClosed()) selfSocket.close();
|
||||
selfClient.socketOut = null;
|
||||
firstTime = false;
|
||||
}
|
||||
if (conn.isOpen()) conn.close();
|
||||
if (!selfSocket.isClosed()) selfSocket.close();
|
||||
} catch (IOException ex) {
|
||||
conn.close();
|
||||
}
|
||||
}).start();
|
||||
msg[1] = (byte) 61;
|
||||
selfClient.handshake = msg;
|
||||
System.out.println("Player " + username + " (" + Main.getIp(conn) + ") joined!");
|
||||
} else {
|
||||
conn.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
byte[] packet = message.array();
|
||||
if (!Main.eaglerPackets && packet.length >= 11 && packet[0] == -6 && packet[2] >= 4 && packet[4] == 69 && packet[6] == 65 && packet[8] == 71 && packet[10] == 124) return; // EAG|
|
||||
Client currClient = Main.clients.get(conn);
|
||||
if (currClient.socketOut == null) {
|
||||
currClient.msgCache.add(packet);
|
||||
} else if (!currClient.socket.isOutputShutdown()) {
|
||||
if (msg.length >= 3 && msg[0] == 3) {
|
||||
int msgLen = (short) ((msg[1] << 8) + msg[2] & 0xff);
|
||||
if (msgLen != 0) {
|
||||
if (msg.length >= 3 + msgLen * 2) {
|
||||
byte[] chatBytes = new byte[msgLen];
|
||||
for (int i = 0; i < chatBytes.length; i++) chatBytes[i] = msg[4 + i * 2];
|
||||
String chatMsg = new String(chatBytes);
|
||||
if (chatMsg.toLowerCase().startsWith("/server")) {
|
||||
String msgArgs = chatMsg.substring(7 + (chatMsg.contains(" ") ? 1 : 0));
|
||||
if (msgArgs.isEmpty()) {
|
||||
//usage msg
|
||||
conn.send(new byte[] { 3, 0, 25, 0, (byte) 167, 0, 57, 0, 85, 0, 115, 0, 97, 0, 103, 0, 101, 0, 58, 0, 32, 0, 47, 0, 115, 0, 101, 0, 114, 0, 118, 0, 101, 0, 114, 0, 32, 0, 60, 0, 110, 0, 117, 0, 109, 0, 98, 0, 101, 0, 114, 0, 62 });
|
||||
} else {
|
||||
try {
|
||||
int destServer = Integer.parseInt(msgArgs);
|
||||
currClient.server = Math.max(0, Math.min(Main.servers.size() - 1, destServer));
|
||||
} catch (NumberFormatException e) {
|
||||
//not a number
|
||||
conn.send(new byte[] { 3, 0, 29, 0, (byte) 167, 0, 57, 0, 84, 0, 104, 0, 97, 0, 116, 0, 32, 0, 105, 0, 115, 0, 32, 0, 110, 0, 111, 0, 116, 0, 32, 0, 97, 0, 32, 0, 118, 0, 97, 0, 108, 0, 105, 0, 100, 0, 32, 0, 110, 0, 117, 0, 109, 0, 98, 0, 101, 0, 114, 0, 33 });
|
||||
}
|
||||
}
|
||||
return; // don't send to underlying server
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (msg.length > 0 && msg[0] == (byte) 250) {
|
||||
if (Skins.setSkin(currClient.username, conn, msg)) return;
|
||||
}
|
||||
if (currClient.socketOut == null || currClient.socket.isOutputShutdown()) {
|
||||
currClient.msgCache.add(msg);
|
||||
} else {
|
||||
try {
|
||||
currClient.socketOut.write(packet);
|
||||
sendToServer(msg, currClient);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToServer(byte[] orig, Client client) throws IOException {
|
||||
byte[] data = orig.clone();
|
||||
EntityMap.rewrite(data, client.clientEntityId, client.serverEntityId);
|
||||
client.socketOut.write(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(WebSocket conn, Exception ex) {
|
||||
//
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
# mc server ip
|
||||
hostname: localhost
|
||||
# mc server port
|
||||
port: 25569
|
||||
# mc servers in network. first one is default/hub
|
||||
servers:
|
||||
- localhost:25569
|
||||
# ayungee port
|
||||
web_port: 25565
|
||||
# if this is behind a reverse proxy, such as caddy or nginx. uses X-Real-IP header.
|
||||
forwarded: false
|
||||
# forward eagler-specific packets?
|
||||
eag_packets: false
|
||||
# origin blacklist URL (leave empty to disable syncing)
|
||||
origin_blacklist: "https://g.eags.us/eaglercraft/origin_blacklist.txt"
|
||||
# whitelisted origins -- if specified, only allows the listed origins to connect
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user