mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-27 18:38:14 -05:00
Update #0 - First Release
This commit is contained in:
Binary file not shown.
BIN
gateway/PlaceholderServer/PlaceholderServer-Latest.jar
Normal file
BIN
gateway/PlaceholderServer/PlaceholderServer-Latest.jar
Normal file
Binary file not shown.
@ -0,0 +1,112 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.placeholder_server;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.java_websocket.WebSocket;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* 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 DummyConnection {
|
||||
|
||||
public final long age;
|
||||
public long sendRedirectAt = 0l;
|
||||
public final WebSocket sock;
|
||||
|
||||
private boolean hasFirstPacket = false;
|
||||
|
||||
public DummyConnection(WebSocket sock) {
|
||||
this.age = System.currentTimeMillis();
|
||||
this.sock = sock;
|
||||
}
|
||||
|
||||
public void processString(String str) {
|
||||
if(!hasFirstPacket) {
|
||||
hasFirstPacket = true;
|
||||
str = str.toLowerCase();
|
||||
if(str.startsWith("accept:")) {
|
||||
str = str.substring(7).trim();
|
||||
if(str.startsWith("motd")) {
|
||||
String subType = "motd";
|
||||
int i = str.indexOf('.');
|
||||
if(i > 0 && i != str.length() - 1) {
|
||||
subType = str.substring(i + 1);
|
||||
}
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("name", PlaceholderServerConfig.serverName);
|
||||
json.put("brand", "lax1dude");
|
||||
json.put("vers", "EaglerXPlaceholder/1.0");
|
||||
json.put("cracked", true);
|
||||
json.put("secure", false);
|
||||
json.put("time", System.currentTimeMillis());
|
||||
json.put("uuid", PlaceholderServerConfig.serverUUID);
|
||||
json.put("type", str);
|
||||
JSONObject motdData = new JSONObject();
|
||||
boolean icon = false;
|
||||
if(subType.startsWith("cache.anim")) {
|
||||
motdData.put("unsupported", true);
|
||||
}else {
|
||||
if(subType.startsWith("cache")) {
|
||||
JSONArray arr = new JSONArray();
|
||||
arr.put("animation");
|
||||
arr.put("results");
|
||||
arr.put("trending");
|
||||
arr.put("portfolio");
|
||||
motdData.put("cache", arr);
|
||||
motdData.put("ttl", 7200);
|
||||
}else {
|
||||
motdData.put("cache", true);
|
||||
}
|
||||
JSONArray motdLines = new JSONArray();
|
||||
String motd1 = PlaceholderServerConfig.motd1;
|
||||
String motd2 = PlaceholderServerConfig.motd2;
|
||||
if(motd1 != null && motd1.length() > 0) motdLines.put(motd1);
|
||||
if(motd2 != null && motd2.length() > 0) motdLines.put(motd2);
|
||||
motdData.put("motd", motdLines);
|
||||
icon = PlaceholderServerConfig.cachedIconPacket != null && !subType.startsWith("noicon")
|
||||
&& !subType.startsWith("cache.noicon");
|
||||
motdData.put("icon", icon);
|
||||
motdData.put("online", 0);
|
||||
motdData.put("max", 0);
|
||||
motdData.put("players", new JSONArray());
|
||||
}
|
||||
json.put("data", motdData);
|
||||
sock.send(json.toString());
|
||||
if(icon) {
|
||||
sock.send(PlaceholderServerConfig.cachedIconPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
sock.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void processBinary(ByteBuffer bin) {
|
||||
if(!hasFirstPacket) {
|
||||
hasFirstPacket = true;
|
||||
if(bin.remaining() > 2) {
|
||||
if(bin.get(0) == (byte)2 && bin.get(1) == (byte)69) {
|
||||
sock.send(PlaceholderServerConfig.cachedLegacyKickRedirectPacket);
|
||||
sendRedirectAt = System.currentTimeMillis();
|
||||
return;
|
||||
}else if(bin.get(0) == (byte)1) {
|
||||
sock.send(PlaceholderServerConfig.cachedKickPacket);
|
||||
}
|
||||
}
|
||||
sock.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.placeholder_server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.java_websocket.WebSocket;
|
||||
import org.java_websocket.handshake.ClientHandshake;
|
||||
import org.java_websocket.server.WebSocketServer;
|
||||
|
||||
/**
|
||||
* 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 PlaceholderServer extends WebSocketServer {
|
||||
|
||||
public static PlaceholderServer websocketServer = null;
|
||||
private boolean isOpen = false;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println();
|
||||
System.out.println("Copyright (c) 2022 lax1dude");
|
||||
System.out.println("All rights reserved.");
|
||||
System.out.println();
|
||||
System.out.println("Starting placeholder 1.8 server...");
|
||||
System.out.println();
|
||||
|
||||
PlaceholderServerConfig.load();
|
||||
|
||||
System.out.println("Starting WebSocket server...");
|
||||
System.out.println();
|
||||
websocketServer = new PlaceholderServer(new InetSocketAddress(PlaceholderServerConfig.host, PlaceholderServerConfig.port));
|
||||
websocketServer.start();
|
||||
|
||||
long redirTimeout = (PlaceholderServerConfig.redirect != null && PlaceholderServerConfig.redirect.length() > 0) ? 500l : 100l;
|
||||
while(true) {
|
||||
try {
|
||||
Thread.sleep(200l);
|
||||
long millis = System.currentTimeMillis();
|
||||
for(WebSocket ws : websocketServer.getConnections()) {
|
||||
DummyConnection conn = ws.getAttachment();
|
||||
if (conn != null && ((conn.sendRedirectAt > 0l && millis - conn.sendRedirectAt > redirTimeout)
|
||||
|| millis - conn.age > (long) PlaceholderServerConfig.clientTimeout)) {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PlaceholderServer(InetSocketAddress addr) {
|
||||
super(addr);
|
||||
setReuseAddr(true);
|
||||
setTcpNoDelay(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(WebSocket arg0, int arg1, String arg2, boolean arg3) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(WebSocket arg0, Exception arg1) {
|
||||
System.err.println();
|
||||
if(arg0 != null) {
|
||||
System.err.println("Caught WebSocket exception on " + arg0.getRemoteSocketAddress() + "!");
|
||||
arg0.close();
|
||||
}else {
|
||||
System.err.println("Caught WebSocket exception!");
|
||||
}
|
||||
arg1.printStackTrace();
|
||||
if(!isOpen) {
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(WebSocket arg0, String arg1) {
|
||||
((DummyConnection)arg0.getAttachment()).processString(arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(WebSocket arg0, ByteBuffer arg1) {
|
||||
((DummyConnection)arg0.getAttachment()).processBinary(arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(WebSocket arg0, ClientHandshake arg1) {
|
||||
arg0.setAttachment(new DummyConnection(arg0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
System.out.println();
|
||||
System.out.println("Listening on: " + getAddress());
|
||||
isOpen = true;
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
PlaceholderServer.this.stop();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, "Shutdown Thread"));
|
||||
|
||||
System.out.println("Use CTRL+C to exit");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.placeholder_server;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* 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 PlaceholderServerConfig {
|
||||
|
||||
public static final File configFile = new File("config.json");
|
||||
|
||||
public static String host = "0.0.0.0";
|
||||
public static int port = 8081;
|
||||
public static String icon = null;
|
||||
public static String serverName = "EaglercraftX 1.8 Server";
|
||||
public static String serverUUID = "";
|
||||
public static int clientTimeout = 3000;
|
||||
public static String motd1 = "Coming Soon";
|
||||
public static String motd2 = "";
|
||||
public static String kick = "This server is still under construction";
|
||||
public static String redirect = "";
|
||||
|
||||
public static byte[] cachedIconPacket = null;
|
||||
public static byte[] cachedLegacyKickRedirectPacket = null;
|
||||
public static byte[] cachedKickPacket = null;
|
||||
|
||||
public static void load() throws IOException {
|
||||
if(!configFile.exists()) {
|
||||
System.out.println("Writing new config file to: " + configFile.getName());
|
||||
int i;
|
||||
try(Reader is = new InputStreamReader(PlaceholderServerConfig.class.getResourceAsStream("/config_default.json"));
|
||||
OutputStream os = new FileOutputStream(configFile)) {
|
||||
char[] copyBuffer = new char[1024];
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while((i = is.read(copyBuffer)) != -1) {
|
||||
sb.append(copyBuffer, 0, i);
|
||||
}
|
||||
String str = sb.toString();
|
||||
str = str.replace("${random_uuid}", UUID.randomUUID().toString());
|
||||
os.write(str.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
try(InputStream is = PlaceholderServerConfig.class.getResourceAsStream("/server-icon_default.png");
|
||||
OutputStream os = new FileOutputStream(new File("server-icon.png"))) {
|
||||
byte[] copyBuffer = new byte[1024];
|
||||
while((i = is.read(copyBuffer)) != -1) {
|
||||
os.write(copyBuffer, 0, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Reading config file: " + configFile.getName());
|
||||
byte[] fileBytes = new byte[(int)configFile.length()];
|
||||
try(InputStream is = new FileInputStream(configFile)) {
|
||||
int i = 0, j;
|
||||
while(i < fileBytes.length && (j = is.read(fileBytes, i, fileBytes.length - i)) != -1) {
|
||||
i += j;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject loaded = new JSONObject(new String(fileBytes, StandardCharsets.UTF_8));
|
||||
host = loaded.getString("server_host");
|
||||
port = loaded.getInt("server_port");
|
||||
icon = loaded.getString("server_icon");
|
||||
serverName = loaded.getString("server_name");
|
||||
serverUUID = loaded.getString("server_uuid");
|
||||
clientTimeout = loaded.getInt("client_timeout");
|
||||
JSONArray motd = loaded.getJSONArray("server_motd");
|
||||
motd1 = motd.getString(0);
|
||||
if(motd.length() > 1) {
|
||||
motd2 = motd.getString(1);
|
||||
}
|
||||
kick = loaded.getString("kick_message");
|
||||
if(kick.length() > 255) {
|
||||
kick = kick.substring(0, 255);
|
||||
System.err.println("Warning: kick message was truncated to 255 characters");
|
||||
}
|
||||
redirect = loaded.optString("redirect_legacy", null);
|
||||
}catch(Throwable t) {
|
||||
throw new IOException("Could not load config file \"" + configFile.getAbsolutePath() + "\"!", t);
|
||||
}
|
||||
|
||||
cacheKickPacket();
|
||||
cacheRedirectPacket();
|
||||
|
||||
if(icon != null && icon.length() > 0) {
|
||||
cacheIconPacket();
|
||||
}
|
||||
}
|
||||
|
||||
private static void cacheKickPacket() throws IOException {
|
||||
ByteArrayOutputStream bao = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(bao);
|
||||
dos.writeByte(0xFF);
|
||||
dos.writeByte(0x08);
|
||||
dos.writeByte(kick.length());
|
||||
for(int i = 0, l = kick.length(); i < l; ++i) {
|
||||
dos.writeByte(kick.charAt(i) & 0xFF);
|
||||
}
|
||||
cachedKickPacket = bao.toByteArray();
|
||||
}
|
||||
|
||||
private static void cacheRedirectPacket() throws IOException {
|
||||
ByteArrayOutputStream bao = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(bao);
|
||||
if(redirect == null || redirect.length() == 0) {
|
||||
String message = "This is an EaglercraftX 1.8 server, it is not compatible with 1.5.2!";
|
||||
dos.writeByte(0xFF);
|
||||
dos.writeShort(message.length());
|
||||
for(int i = 0, l = message.length(), j; i < l; ++i) {
|
||||
j = message.charAt(i);
|
||||
dos.writeByte((j >> 8) & 0xFF);
|
||||
dos.writeByte(j & 0xFF);
|
||||
}
|
||||
}else {
|
||||
// Packet1Login
|
||||
dos.writeByte(0x01);
|
||||
dos.writeInt(0);
|
||||
dos.writeShort(0);
|
||||
dos.writeByte(0);
|
||||
dos.writeByte(0);
|
||||
dos.writeByte(0xFF);
|
||||
dos.writeByte(0);
|
||||
dos.writeByte(0);
|
||||
// Packet250CustomPayload
|
||||
dos.writeByte(0xFA);
|
||||
String channel = "EAG|Reconnect";
|
||||
int cl = channel.length();
|
||||
dos.writeShort(cl);
|
||||
for(int i = 0; i < cl; ++i) {
|
||||
dos.writeChar(channel.charAt(i));
|
||||
}
|
||||
byte[] redirect_ = redirect.getBytes(StandardCharsets.UTF_8);
|
||||
dos.writeShort(redirect_.length);
|
||||
dos.write(redirect_);
|
||||
}
|
||||
cachedLegacyKickRedirectPacket = bao.toByteArray();
|
||||
}
|
||||
|
||||
private static void cacheIconPacket() throws IOException {
|
||||
File f = new File(icon);
|
||||
int[] iconPixels = ServerIconLoader.createServerIcon(f);
|
||||
if(iconPixels != null) {
|
||||
cachedIconPacket = new byte[16384];
|
||||
for(int i = 0, j; i < 4096; ++i) {
|
||||
j = i << 2;
|
||||
cachedIconPacket[j] = (byte)((iconPixels[i] >> 16) & 0xFF);
|
||||
cachedIconPacket[j + 1] = (byte)((iconPixels[i] >> 8) & 0xFF);
|
||||
cachedIconPacket[j + 2] = (byte)(iconPixels[i] & 0xFF);
|
||||
cachedIconPacket[j + 3] = (byte)((iconPixels[i] >> 24) & 0xFF);
|
||||
}
|
||||
}else {
|
||||
System.err.println("Could not load server icon \"" + f.getAbsolutePath() + "\"!");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.placeholder_server;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*
|
||||
*/
|
||||
class ServerIconLoader {
|
||||
|
||||
static int[] createServerIcon(BufferedImage awtIcon) {
|
||||
BufferedImage icon = awtIcon;
|
||||
boolean gotScaled = false;
|
||||
if(icon.getWidth() != 64 || icon.getHeight() != 64) {
|
||||
icon = new BufferedImage(64, 64, awtIcon.getType());
|
||||
Graphics2D g = (Graphics2D) icon.getGraphics();
|
||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, (awtIcon.getWidth() < 64 || awtIcon.getHeight() < 64) ?
|
||||
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR : RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||
g.setBackground(new Color(0, true));
|
||||
g.clearRect(0, 0, 64, 64);
|
||||
int ow = awtIcon.getWidth();
|
||||
int oh = awtIcon.getHeight();
|
||||
int nw, nh;
|
||||
float aspectRatio = (float)oh / (float)ow;
|
||||
if(aspectRatio >= 1.0f) {
|
||||
nw = (int)(64 / aspectRatio);
|
||||
nh = 64;
|
||||
}else {
|
||||
nw = 64;
|
||||
nh = (int)(64 * aspectRatio);
|
||||
}
|
||||
g.drawImage(awtIcon, (64 - nw) / 2, (64 - nh) / 2, (64 - nw) / 2 + nw, (64 - nh) / 2 + nh, 0, 0, awtIcon.getWidth(), awtIcon.getHeight(), null);
|
||||
g.dispose();
|
||||
gotScaled = true;
|
||||
}
|
||||
int[] pxls = icon.getRGB(0, 0, 64, 64, new int[4096], 0, 64);
|
||||
if(gotScaled) {
|
||||
for(int i = 0; i < pxls.length; ++i) {
|
||||
if((pxls[i] & 0xFFFFFF) == 0) {
|
||||
pxls[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pxls;
|
||||
}
|
||||
|
||||
static int[] createServerIcon(InputStream f) {
|
||||
try {
|
||||
return createServerIcon(ImageIO.read(f));
|
||||
}catch(Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static int[] createServerIcon(File f) {
|
||||
try {
|
||||
return createServerIcon(ImageIO.read(f));
|
||||
}catch(Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"server_host": "0.0.0.0",
|
||||
"server_port": 8081,
|
||||
"server_icon": "server-icon.png",
|
||||
"server_motd": [
|
||||
"1.8 is still under construction"
|
||||
],
|
||||
"server_name": "EaglercraftX 1.8 Server",
|
||||
"server_uuid": "${random_uuid}",
|
||||
"client_timeout": 3000,
|
||||
"kick_message": "This EaglercraftX 1.8 server is still under construction!",
|
||||
"redirect_legacy": null
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 402 B |
Reference in New Issue
Block a user