Update #0 - First Release

This commit is contained in:
LAX1DUDE
2022-12-25 01:12:28 -08:00
commit e7179fad45
2154 changed files with 256324 additions and 0 deletions

View File

@ -0,0 +1,61 @@
package net.lax1dude.eaglercraft.v1_8.socket;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.minecraft.client.multiplayer.ServerAddress;
import net.minecraft.client.multiplayer.ServerData;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class AddressResolver {
public static String resolveURI(ServerData input) {
return resolveURI(input.serverIP);
}
public static String resolveURI(String input) {
String lc = input.toLowerCase();
if(!lc.startsWith("ws://") && !lc.startsWith("wss://")) {
if(EagRuntime.requireSSL()) {
input = "wss://" + input;
}else {
input = "ws://" + input;
}
}
return input;
}
public static ServerAddress resolveAddressFromURI(String input) {
String uri = resolveURI(input);
String lc = input.toLowerCase();
if(lc.startsWith("ws://")) {
input = input.substring(5);
}else if(lc.startsWith("wss://")) {
input = input.substring(6);
}
int port = EagRuntime.requireSSL() ? 443: 80;
int i = input.indexOf('/');
if(i != -1) {
input = input.substring(0, i);
}
i = input.lastIndexOf(':');
if(i != -1) {
try {
port = Integer.parseInt(input.substring(i + 1));
}catch(Throwable t) {
}
}
return new ServerAddress(uri, port);
}
}

View File

@ -0,0 +1,24 @@
package net.lax1dude.eaglercraft.v1_8.socket;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class CompressionNotSupportedException extends UnsupportedOperationException {
public CompressionNotSupportedException() {
super("Compression is not supported by Eaglercraft, set " +
"'network-compression-threshold=-1' in server.properties to " +
"allow Eaglercraft connections to this server");
}
}

View File

@ -0,0 +1,387 @@
package net.lax1dude.eaglercraft.v1_8.socket;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import net.lax1dude.eaglercraft.v1_8.ArrayUtils;
import net.lax1dude.eaglercraft.v1_8.EaglerInputStream;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion;
import net.lax1dude.eaglercraft.v1_8.crypto.SHA256Digest;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformNetworking;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile;
import net.lax1dude.eaglercraft.v1_8.profile.GuiAuthenticationScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiDisconnected;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.multiplayer.GuiConnecting;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class ConnectionHandshake {
private static final long baseTimeout = 5000l;
private static final int baseVersion = 2; // ProtocolVersions.V_02
private static final Logger logger = LogManager.getLogger();
public static boolean attemptHandshake(Minecraft mc, GuiConnecting connecting, GuiScreen ret, String password, boolean allowPlaintext) {
try {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
DataOutputStream d = new DataOutputStream(bao);
d.writeByte(HandshakePacketTypes.PROTOCOL_CLIENT_VERSION);
d.writeByte(2); // legacy protocol version
d.writeShort(1); // supported eagler protocols count
d.writeShort(baseVersion); // client supports v2
d.writeShort(1); // supported game protocols count
d.writeShort(47); // client supports 1.8 protocol
String clientBrand = EaglercraftVersion.projectForkName;
d.writeByte(clientBrand.length());
d.writeBytes(clientBrand);
String clientVers = EaglercraftVersion.projectOriginVersion;
d.writeByte(clientVers.length());
d.writeBytes(clientVers);
d.writeBoolean(password != null);
String username = mc.getSession().getProfile().getName();
d.writeByte(username.length());
d.writeBytes(username);
PlatformNetworking.writePlayPacket(bao.toByteArray());
byte[] read = awaitNextPacket(baseTimeout);
if(read == null) {
logger.error("Read timed out while waiting for server protocol response!");
return false;
}
DataInputStream di = new DataInputStream(new EaglerInputStream(read));
int type = di.read();
if(type == HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH) {
StringBuilder protocols = new StringBuilder();
int c = di.readShort();
for(int i = 0; i < c; ++i) {
if(i > 0) {
protocols.append(", ");
}
protocols.append("v").append(di.readShort());
}
StringBuilder games = new StringBuilder();
c = di.readShort();
for(int i = 0; i < c; ++i) {
if(i > 0) {
games.append(", ");
}
games.append("mc").append(di.readShort());
}
logger.info("Incompatible client: v2 & mc47");
logger.info("Server supports: {}", protocols);
logger.info("Server supports: {}", games);
int msgLen = di.read();
byte[] dat = new byte[msgLen];
di.read(dat);
String msg = new String(dat, StandardCharsets.UTF_8);
mc.displayGuiScreen(new GuiDisconnected(ret, "connect.failed", new ChatComponentText(msg)));
return false;
}else if(type == HandshakePacketTypes.PROTOCOL_SERVER_VERSION) {
int serverVers = di.readShort();
if(serverVers != baseVersion) {
logger.info("Incompatible server version: {}", serverVers);
mc.displayGuiScreen(new GuiDisconnected(ret, "connect.failed", new ChatComponentText(serverVers < baseVersion ? "Outdated Server" : "Outdated Client")));
return false;
}
int gameVers = di.readShort();
if(gameVers != 47) {
logger.info("Incompatible minecraft protocol version: {}", gameVers);
mc.displayGuiScreen(new GuiDisconnected(ret, "connect.failed", new ChatComponentText("This server does not support 1.8!")));
return false;
}
logger.info("Server protocol: {}", serverVers);
int msgLen = di.read();
byte[] dat = new byte[msgLen];
di.read(dat);
String brandStr = ArrayUtils.asciiString(dat);
msgLen = di.read();
dat = new byte[msgLen];
di.read(dat);
String versionStr = ArrayUtils.asciiString(dat);
logger.info("Server version: {}", versionStr);
logger.info("Server brand: {}", brandStr);
int authType = di.read();
int saltLength = (int)di.readShort() & 0xFFFF;
byte[] salt = new byte[saltLength];
di.read(salt);
bao.reset();
d.writeByte(HandshakePacketTypes.PROTOCOL_CLIENT_REQUEST_LOGIN);
d.writeByte(username.length());
d.writeBytes(username);
String requestedServer = "default";
d.writeByte(requestedServer.length());
d.writeBytes(requestedServer);
if(authType != 0 && password != null && password.length() > 0) {
if(authType == HandshakePacketTypes.AUTH_METHOD_PLAINTEXT) {
if(allowPlaintext) {
logger.warn("Server is using insecure plaintext authentication");
d.writeByte(password.length() << 1);
d.writeChars(password);
}else {
logger.error("Plaintext authentication was attempted but no user confirmation has been given to proceed");
mc.displayGuiScreen(new GuiDisconnected(ret, "connect.failed",
new ChatComponentText(EnumChatFormatting.RED + "Plaintext authentication was attempted but no user confirmation has been given to proceed")));
return false;
}
}else if(authType == HandshakePacketTypes.AUTH_METHOD_EAGLER_SHA256) {
SHA256Digest digest = new SHA256Digest();
int passLen = password.length();
digest.update((byte)((passLen >> 8) & 0xFF));
digest.update((byte)(passLen & 0xFF));
for(int i = 0; i < passLen; ++i) {
char codePoint = password.charAt(i);
digest.update((byte)((codePoint >> 8) & 0xFF));
digest.update((byte)(codePoint & 0xFF));
}
digest.update(HandshakePacketTypes.EAGLER_SHA256_SALT_SAVE, 0, 32);
byte[] hashed = new byte[32];
digest.doFinal(hashed, 0);
digest.reset();
digest.update(hashed, 0, 32);
digest.update(salt, 0, 32);
digest.update(HandshakePacketTypes.EAGLER_SHA256_SALT_BASE, 0, 32);
digest.doFinal(hashed, 0);
digest.reset();
digest.update(hashed, 0, 32);
digest.update(salt, 32, 32);
digest.update(HandshakePacketTypes.EAGLER_SHA256_SALT_BASE, 0, 32);
digest.doFinal(hashed, 0);
d.writeByte(32);
d.write(hashed);
}else if(authType == HandshakePacketTypes.AUTH_METHOD_AUTHME_SHA256) {
SHA256Digest digest = new SHA256Digest();
byte[] passwd = password.getBytes(StandardCharsets.UTF_8);
digest.update(passwd, 0, passwd.length);
byte[] hashed = new byte[32];
digest.doFinal(hashed, 0);
byte[] toHexAndSalt = new byte[64];
for(int i = 0; i < 32; ++i) {
toHexAndSalt[i << 1] = HEX[(hashed[i] >> 4) & 0xF];
toHexAndSalt[(i << 1) + 1] = HEX[hashed[i] & 0xF];
}
digest.reset();
digest.update(toHexAndSalt, 0, 64);
digest.update(salt, 0, salt.length);
digest.doFinal(hashed, 0);
for(int i = 0; i < 32; ++i) {
toHexAndSalt[i << 1] = HEX[(hashed[i] >> 4) & 0xF];
toHexAndSalt[(i << 1) + 1] = HEX[hashed[i] & 0xF];
}
d.writeByte(64);
d.write(toHexAndSalt);
}else {
logger.error("Unsupported authentication type: {}", authType);
mc.displayGuiScreen(new GuiDisconnected(ret, "connect.failed",
new ChatComponentText(EnumChatFormatting.RED + "Unsupported authentication type: " + authType + "\n\n" + EnumChatFormatting.GRAY + "(Use a newer version of the client)")));
return false;
}
}else {
d.writeByte(0);
}
PlatformNetworking.writePlayPacket(bao.toByteArray());
read = awaitNextPacket(baseTimeout);
if(read == null) {
logger.error("Read timed out while waiting for login negotiation response!");
return false;
}
di = new DataInputStream(new EaglerInputStream(read));
type = di.read();
if(type == HandshakePacketTypes.PROTOCOL_SERVER_ALLOW_LOGIN) {
msgLen = di.read();
dat = new byte[msgLen];
di.read(dat);
String serverUsername = ArrayUtils.asciiString(dat);
Minecraft.getMinecraft().getSession().update(serverUsername, new EaglercraftUUID(di.readLong(), di.readLong()));
bao.reset();
d.writeByte(HandshakePacketTypes.PROTOCOL_CLIENT_PROFILE_DATA);
String profileDataType = "skin_v1";
d.writeByte(profileDataType.length());
d.writeBytes(profileDataType);
byte[] packetSkin = EaglerProfile.getSkinPacket();
if(packetSkin.length > 0xFFFF) {
throw new IOException("Skin packet is too long: " + packetSkin.length);
}
d.writeShort(packetSkin.length);
d.write(packetSkin);
PlatformNetworking.writePlayPacket(bao.toByteArray());
bao.reset();
d.writeByte(HandshakePacketTypes.PROTOCOL_CLIENT_FINISH_LOGIN);
PlatformNetworking.writePlayPacket(bao.toByteArray());
read = awaitNextPacket(baseTimeout);
if(read == null) {
logger.error("Read timed out while waiting for login confirmation response!");
return false;
}
di = new DataInputStream(new EaglerInputStream(read));
type = di.read();
if(type == HandshakePacketTypes.PROTOCOL_SERVER_FINISH_LOGIN) {
return true;
}else if(type == HandshakePacketTypes.PROTOCOL_SERVER_ERROR) {
showError(mc, connecting, ret, di);
return false;
}else {
return false;
}
}else if(type == HandshakePacketTypes.PROTOCOL_SERVER_DENY_LOGIN) {
msgLen = di.read();
dat = new byte[msgLen];
di.read(dat);
String errStr = new String(dat, StandardCharsets.UTF_8);
mc.displayGuiScreen(new GuiDisconnected(ret, "connect.failed", new ChatComponentText(errStr)));
return false;
}else if(type == HandshakePacketTypes.PROTOCOL_SERVER_ERROR) {
showError(mc, connecting, ret, di);
return false;
}else {
return false;
}
}else if(type == HandshakePacketTypes.PROTOCOL_SERVER_ERROR) {
showError(mc, connecting, ret, di);
return false;
}else {
return false;
}
}catch(Throwable t) {
logger.error("Exception in handshake");
logger.error(t);
return false;
}
}
private static byte[] awaitNextPacket(long timeout) {
long millis = System.currentTimeMillis();
byte[] b;
while((b = PlatformNetworking.readPlayPacket()) == null) {
if(PlatformNetworking.playConnectionState().isClosed()) {
return null;
}
try {
Thread.sleep(50l);
} catch (InterruptedException e) {
}
if(System.currentTimeMillis() - millis > timeout) {
PlatformNetworking.playDisconnect();
return null;
}
}
return b;
}
private static void showError(Minecraft mc, GuiConnecting connecting, GuiScreen scr, DataInputStream err) throws IOException {
int errorCode = err.read();
int msgLen = err.read();
byte[] dat = new byte[msgLen];
err.read(dat);
String errStr = new String(dat, StandardCharsets.UTF_8);
logger.info("Server Error Code {}: {}", errorCode, errStr);
if(errorCode == HandshakePacketTypes.SERVER_ERROR_RATELIMIT_BLOCKED) {
RateLimitTracker.registerBlock(PlatformNetworking.getCurrentURI());
mc.displayGuiScreen(GuiDisconnected.createRateLimitKick(scr));
}else if(errorCode == HandshakePacketTypes.SERVER_ERROR_RATELIMIT_LOCKED) {
RateLimitTracker.registerLockOut(PlatformNetworking.getCurrentURI());
mc.displayGuiScreen(GuiDisconnected.createRateLimitKick(scr));
}else if(errorCode == HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE) {
mc.displayGuiScreen(new GuiDisconnected(scr, "connect.failed", new ChatComponentText(errStr)));
}else if(connecting != null && errorCode == HandshakePacketTypes.SERVER_ERROR_AUTHENTICATION_REQUIRED) {
mc.displayGuiScreen(new GuiAuthenticationScreen(connecting, scr, errStr));
}else {
mc.displayGuiScreen(new GuiDisconnected(scr, "connect.failed", new ChatComponentText("Server Error Code " + errorCode + "\n" + errStr)));
}
}
public static GuiScreen displayAuthProtocolConfirm(int protocol, GuiScreen no, GuiScreen yes) {
if(protocol == HandshakePacketTypes.AUTH_METHOD_PLAINTEXT) {
return new GuiHandshakeApprove("plaintext", no, yes);
}else if(protocol != HandshakePacketTypes.AUTH_METHOD_EAGLER_SHA256 && protocol != HandshakePacketTypes.AUTH_METHOD_AUTHME_SHA256) {
return new GuiHandshakeApprove("unsupportedAuth", no);
}else {
return null;
}
}
private static final byte[] HEX = new byte[] {
(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
};
}

View File

@ -0,0 +1,180 @@
package net.lax1dude.eaglercraft.v1_8.socket;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformNetworking;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.netty.ByteBuf;
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.EnumPacketDirection;
import net.minecraft.network.INetHandler;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.IChatComponent;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglercraftNetworkManager {
private final String address;
private INetHandler nethandler = null;
private EnumConnectionState packetState = EnumConnectionState.HANDSHAKING;
private final PacketBuffer temporaryBuffer;
private int debugPacketCounter = 0;
public static final Logger logger = LogManager.getLogger("NetworkManager");
public EaglercraftNetworkManager(String address) {
this.address = address;
this.temporaryBuffer = new PacketBuffer(Unpooled.buffer(0x1FFFF));
}
public void connect() {
PlatformNetworking.startPlayConnection(address);
}
public EnumEaglerConnectionState getConnectStatus() {
return PlatformNetworking.playConnectionState();
}
public void closeChannel(IChatComponent reason) {
PlatformNetworking.playDisconnect();
if(nethandler != null) {
nethandler.onDisconnect(reason);
}
clientDisconnected = true;
}
public void setConnectionState(EnumConnectionState state) {
packetState = state;
}
public void processReceivedPackets() throws IOException {
if(nethandler == null) return;
byte[] next;
while((next = PlatformNetworking.readPlayPacket()) != null) {
++debugPacketCounter;
try {
ByteBuf nettyBuffer = Unpooled.buffer(next, next.length);
nettyBuffer.writerIndex(next.length);
PacketBuffer input = new PacketBuffer(nettyBuffer);
int pktId = input.readVarIntFromBuffer();
Packet pkt;
try {
pkt = packetState.getPacket(EnumPacketDirection.CLIENTBOUND, pktId);
}catch(IllegalAccessException | InstantiationException ex) {
throw new IOException("Recieved a packet with type " + pktId + " which is invalid!");
}
try {
pkt.readPacketData(input);
}catch(Throwable t) {
throw new IOException("Failed to read packet type '" + pkt.getClass().getSimpleName() + "'", t);
}
try {
pkt.processPacket(nethandler);
}catch(Throwable t) {
logger.error("Failed to process {}! It'll be skipped for debug purposes.", pkt.getClass().getSimpleName());
logger.error(t);
}
}catch(Throwable t) {
logger.error("Failed to process websocket frame {}! It'll be skipped for debug purposes.", debugPacketCounter);
logger.error(t);
}
}
}
public void sendPacket(Packet pkt) {
if(!isChannelOpen()) {
logger.error("Packet was sent on a closed connection: {}", pkt.getClass().getSimpleName());
return;
}
int i;
try {
i = packetState.getPacketId(EnumPacketDirection.SERVERBOUND, pkt);
}catch(Throwable t) {
logger.error("Incorrect packet for state: {}", pkt.getClass().getSimpleName());
return;
}
temporaryBuffer.clear();
temporaryBuffer.writeVarIntToBuffer(i);
try {
pkt.writePacketData(temporaryBuffer);
}catch(IOException ex) {
logger.error("Failed to write packet {}!", pkt.getClass().getSimpleName());
return;
}
int len = temporaryBuffer.writerIndex();
byte[] bytes = new byte[len];
temporaryBuffer.getBytes(0, bytes);
PlatformNetworking.writePlayPacket(bytes);
}
public void setNetHandler(INetHandler nethandler) {
this.nethandler = nethandler;
}
public boolean isLocalChannel() {
return false;
}
public boolean isChannelOpen() {
return getConnectStatus() == EnumEaglerConnectionState.CONNECTED;
}
public boolean getIsencrypted() {
return false;
}
public void setCompressionTreshold(int compressionTreshold) {
throw new CompressionNotSupportedException();
}
public boolean checkDisconnected() {
if(PlatformNetworking.playConnectionState().isClosed()) {
try {
processReceivedPackets(); // catch kick message
} catch (IOException e) {
}
doClientDisconnect(new ChatComponentTranslation("disconnect.endOfStream"));
return true;
}else {
return false;
}
}
private boolean clientDisconnected = false;
private void doClientDisconnect(IChatComponent msg) {
if(!clientDisconnected) {
clientDisconnected = true;
if(nethandler != null) {
this.nethandler.onDisconnect(msg);
}
}
}
}

View File

@ -0,0 +1,24 @@
package net.lax1dude.eaglercraft.v1_8.socket;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EncryptionNotSupportedException extends UnsupportedOperationException {
public EncryptionNotSupportedException() {
super("Encryption is not supported by Eaglercraft, set " +
"online-mode=false' in server.properties to " +
"allow Eaglercraft connections to this server");
}
}

View File

@ -0,0 +1,104 @@
package net.lax1dude.eaglercraft.v1_8.socket;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class GuiHandshakeApprove extends GuiScreen {
protected String message;
protected GuiScreen no;
protected GuiScreen yes;
protected String titleString;
protected List<String> bodyLines;
protected int bodyY;
public GuiHandshakeApprove(String message, GuiScreen no, GuiScreen yes) {
this.message = message;
this.no = no;
this.yes = yes;
}
public GuiHandshakeApprove(String message, GuiScreen back) {
this(message, back, null);
}
public void initGui() {
this.buttonList.clear();
titleString = I18n.format("handshakeApprove." + message + ".title");
bodyLines = new ArrayList();
int i = 0;
boolean wasNull = true;
while(true) {
String line = getI18nOrNull("handshakeApprove." + message + ".body." + (i++));
if(line == null) {
if(wasNull) {
break;
}else {
bodyLines.add("");
wasNull = true;
}
}else {
bodyLines.add(line);
wasNull = false;
}
}
int totalHeight = 10 + 10 + bodyLines.size() * 10 + 10 + 20;
bodyY = (height - totalHeight) / 2 - 15;
int buttonY = bodyY + totalHeight - 20;
if(yes != null) {
this.buttonList.add(new GuiButton(0, width / 2 + 3, buttonY, 100, 20, I18n.format("gui.no")));
this.buttonList.add(new GuiButton(1, width / 2 - 103, buttonY, 100, 20, I18n.format("gui.yes")));
}else {
this.buttonList.add(new GuiButton(0, width / 2 - 100, buttonY, 200, 20, I18n.format("gui.back")));
}
}
protected void actionPerformed(GuiButton parGuiButton) {
if(parGuiButton.id == 0) {
mc.displayGuiScreen(no);
}else if(parGuiButton.id == 1) {
mc.displayGuiScreen(yes);
}
}
public void drawScreen(int xx, int yy, float partialTicks) {
drawBackground(0);
drawCenteredString(fontRendererObj, titleString, width / 2, bodyY, 16777215);
for(int i = 0, l = bodyLines.size(); i < l; ++i) {
String s = bodyLines.get(i);
if(s.length() > 0) {
drawCenteredString(fontRendererObj, s, width / 2, bodyY + 20 + i * 10, 16777215);
}
}
super.drawScreen(xx, yy, partialTicks);
}
private String getI18nOrNull(String key) {
String ret = I18n.format(key);
if(key.equals(ret)) {
return null;
}else {
return ret;
}
}
}

View File

@ -0,0 +1,63 @@
package net.lax1dude.eaglercraft.v1_8.socket;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class HandshakePacketTypes {
public static final String AUTHENTICATION_REQUIRED = "Authentication Required:";
public static final int PROTOCOL_CLIENT_VERSION = 0x01;
public static final int PROTOCOL_SERVER_VERSION = 0x02;
public static final int PROTOCOL_VERSION_MISMATCH = 0x03;
public static final int PROTOCOL_CLIENT_REQUEST_LOGIN = 0x04;
public static final int PROTOCOL_SERVER_ALLOW_LOGIN = 0x05;
public static final int PROTOCOL_SERVER_DENY_LOGIN = 0x06;
public static final int PROTOCOL_CLIENT_PROFILE_DATA = 0x07;
public static final int PROTOCOL_CLIENT_FINISH_LOGIN = 0x08;
public static final int PROTOCOL_SERVER_FINISH_LOGIN = 0x09;
public static final int PROTOCOL_SERVER_ERROR = 0xFF;
public static final int STATE_OPENED = 0x00;
public static final int STATE_CLIENT_VERSION = 0x01;
public static final int STATE_CLIENT_LOGIN = 0x02;
public static final int STATE_CLIENT_COMPLETE = 0x03;
public static final int SERVER_ERROR_UNKNOWN_PACKET = 0x01;
public static final int SERVER_ERROR_INVALID_PACKET = 0x02;
public static final int SERVER_ERROR_WRONG_PACKET = 0x03;
public static final int SERVER_ERROR_EXCESSIVE_PROFILE_DATA = 0x04;
public static final int SERVER_ERROR_DUPLICATE_PROFILE_DATA = 0x05;
public static final int SERVER_ERROR_RATELIMIT_BLOCKED = 0x06;
public static final int SERVER_ERROR_RATELIMIT_LOCKED = 0x07;
public static final int SERVER_ERROR_CUSTOM_MESSAGE = 0x08;
public static final int SERVER_ERROR_AUTHENTICATION_REQUIRED = 0x09;
public static final int AUTH_METHOD_NONE = 0x0;
public static final int AUTH_METHOD_EAGLER_SHA256 = 0x01;
public static final int AUTH_METHOD_AUTHME_SHA256 = 0x02;
public static final int AUTH_METHOD_PLAINTEXT = 0xFF;
public static final byte[] EAGLER_SHA256_SALT_BASE = new byte[] { (byte) 117, (byte) 43, (byte) 1, (byte) 112,
(byte) 75, (byte) 3, (byte) 188, (byte) 61, (byte) 121, (byte) 31, (byte) 34, (byte) 181, (byte) 234,
(byte) 31, (byte) 247, (byte) 72, (byte) 12, (byte) 168, (byte) 138, (byte) 45, (byte) 143, (byte) 77,
(byte) 118, (byte) 245, (byte) 187, (byte) 242, (byte) 188, (byte) 219, (byte) 160, (byte) 235, (byte) 235,
(byte) 68 };
public static final byte[] EAGLER_SHA256_SALT_SAVE = new byte[] { (byte) 49, (byte) 25, (byte) 39, (byte) 38,
(byte) 253, (byte) 85, (byte) 70, (byte) 245, (byte) 71, (byte) 150, (byte) 253, (byte) 206, (byte) 4,
(byte) 26, (byte) 198, (byte) 249, (byte) 145, (byte) 251, (byte) 232, (byte) 174, (byte) 186, (byte) 98,
(byte) 27, (byte) 232, (byte) 55, (byte) 144, (byte) 83, (byte) 21, (byte) 36, (byte) 55, (byte) 170,
(byte) 118 };
}

View File

@ -0,0 +1,65 @@
package net.lax1dude.eaglercraft.v1_8.socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class RateLimitTracker {
private static long lastTickUpdate = 0l;
private static final Map<String, Long> blocks = new HashMap();
private static final Map<String, Long> lockout = new HashMap();
public static boolean isLockedOut(String addr) {
Long lockoutStatus = lockout.get(addr);
return lockoutStatus != null && System.currentTimeMillis() - lockoutStatus.longValue() < 300000l;
}
public static boolean isProbablyLockedOut(String addr) {
return blocks.containsKey(addr) || lockout.containsKey(addr);
}
public static void registerBlock(String addr) {
blocks.put(addr, System.currentTimeMillis());
}
public static void registerLockOut(String addr) {
long millis = System.currentTimeMillis();
blocks.put(addr, millis);
lockout.put(addr, millis);
}
public static void tick() {
long millis = System.currentTimeMillis();
if(millis - lastTickUpdate > 5000l) {
lastTickUpdate = millis;
Iterator<Long> blocksItr = blocks.values().iterator();
while(blocksItr.hasNext()) {
if(millis - blocksItr.next().longValue() > 900000l) {
blocksItr.remove();
}
}
blocksItr = lockout.values().iterator();
while(blocksItr.hasNext()) {
if(millis - blocksItr.next().longValue() > 900000l) {
blocksItr.remove();
}
}
}
}
}

View File

@ -0,0 +1,30 @@
package net.lax1dude.eaglercraft.v1_8.socket;
import net.lax1dude.eaglercraft.v1_8.internal.IServerQuery;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformNetworking;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class ServerQueryDispatch {
private static final Logger logger = LogManager.getLogger("QueryDispatch");
public static IServerQuery sendServerQuery(String uri, String accept) {
logger.info("Sending {} query to: \"{}\"", accept, uri);
return PlatformNetworking.sendServerQuery(uri, accept);
}
}