diff --git a/SubServers.Web/pom.xml b/SubServers.Web/pom.xml
index 5c351648..b9ccf684 100644
--- a/SubServers.Web/pom.xml
+++ b/SubServers.Web/pom.xml
@@ -54,6 +54,24 @@
gson
2.9.1
+
+ net.ME1312.SubServers
+ SubServers.Client.Common
+ -PLACEHOLDER
+ compile
+
+
+ net.ME1312.Galaxi
+ GalaxiAPI
+ 22w24a
+ compile
+
+
+ net.ME1312.SubServers
+ SubServers.Host
+ -PLACEHOLDER
+ compile
+
@@ -73,7 +91,7 @@
maven-compiler-plugin
3.7.0
-
+
1.8
diff --git a/SubServers.Web/src/META-INF/MANIFEST.MF b/SubServers.Web/src/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..4724317e
--- /dev/null
+++ b/SubServers.Web/src/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: net.ME1312.SubServers.Web.ExternalMain
+Implementation-Title: SubServers.Web
diff --git a/SubServers.Web/src/META-INF/MANIFEST.MOD.MF b/SubServers.Web/src/META-INF/MANIFEST.MOD.MF
new file mode 100644
index 00000000..3affc2e8
--- /dev/null
+++ b/SubServers.Web/src/META-INF/MANIFEST.MOD.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Class-Path: Libraries/GalaxiEngine.jar Libraries/SubDataClient.jar
+Main-Class: net.ME1312.SubServers.Web.ExternalMain
+Implementation-Title: SubServers.Host
diff --git a/SubServers.Web/src/META-INF/services/org.slf4j.spi.SLF4JServiceProvider b/SubServers.Web/src/META-INF/services/org.slf4j.spi.SLF4JServiceProvider
new file mode 100644
index 00000000..47594d9d
--- /dev/null
+++ b/SubServers.Web/src/META-INF/services/org.slf4j.spi.SLF4JServiceProvider
@@ -0,0 +1 @@
+net.ME1312.SubServers.Web.Logging.SLF4JLoggerProvider
\ No newline at end of file
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/endpoints/StatusServlet.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Endpoints/StatusServlet.java
similarity index 93%
rename from SubServers.Web/src/net/ME1312/SubServers/Web/endpoints/StatusServlet.java
rename to SubServers.Web/src/net/ME1312/SubServers/Web/Endpoints/StatusServlet.java
index 3cbf55c2..94567aec 100644
--- a/SubServers.Web/src/net/ME1312/SubServers/Web/endpoints/StatusServlet.java
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Endpoints/StatusServlet.java
@@ -1,4 +1,4 @@
-package net.ME1312.SubServers.Web.endpoints;
+package net.ME1312.SubServers.Web.Endpoints;
import com.google.gson.Gson;
import jakarta.servlet.http.HttpServlet;
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/JettyServer.java b/SubServers.Web/src/net/ME1312/SubServers/Web/JettyServer.java
index 68b89b4b..d7344512 100644
--- a/SubServers.Web/src/net/ME1312/SubServers/Web/JettyServer.java
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/JettyServer.java
@@ -1,15 +1,108 @@
package net.ME1312.SubServers.Web;
-import net.ME1312.SubServers.Web.endpoints.StatusServlet;
+import net.ME1312.Galaxi.Engine.GalaxiEngine;
+import net.ME1312.Galaxi.Event.Engine.GalaxiReloadEvent;
+import net.ME1312.Galaxi.Library.Config.YAMLConfig;
+import net.ME1312.Galaxi.Library.Container.Pair;
+import net.ME1312.Galaxi.Library.Map.ObjectMap;
+import net.ME1312.Galaxi.Library.Util;
+import net.ME1312.Galaxi.Log.Logger;
+import net.ME1312.Galaxi.Plugin.App;
+import net.ME1312.Galaxi.Plugin.PluginInfo;
+import net.ME1312.SubData.Client.DataClient;
+import net.ME1312.SubData.Client.Encryption.AES;
+import net.ME1312.SubData.Client.Encryption.DHE;
+import net.ME1312.SubData.Client.Encryption.RSA;
+import net.ME1312.SubData.Client.Library.DisconnectReason;
+import net.ME1312.SubData.Client.SubDataClient;
+import net.ME1312.SubServers.Host.Executable.SubCreatorImpl;
+import net.ME1312.SubServers.Host.Executable.SubLoggerImpl;
+import net.ME1312.SubServers.Host.Executable.SubServerImpl;
+import net.ME1312.SubServers.Web.Library.ConfigUpdater;
+import net.ME1312.SubServers.Web.Network.SubProtocol;
+import net.ME1312.SubServers.Web.Endpoints.StatusServlet;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletHandler;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+@App(name = "SubServers.Web", version = "2.19a", authors = "ME1312", website = "https://github.com/ME1312/SubServers-2", description = "Operate subservers from web browsers")
public class JettyServer {
public Server server;
+ HashMap subdata = new HashMap();
+ Pair>> lang = null;
+ public HashMap templatesR = new HashMap();
+ public HashMap templates = new HashMap();
+ public HashMap servers = new HashMap();
+
+ public Logger log;
+ public PluginInfo info;
+ public GalaxiEngine engine;
+ public YAMLConfig config;
+ public ObjectMap host = null;
+ public SubProtocol subprotocol;
+
+ public final SubAPI api = new SubAPI(this);
+
+ private long resetDate = 0;
+ private boolean reconnect = true;
+ private boolean running = false;
+
public void start() throws Exception {
+ log = new Logger("SubServers");
+ info = PluginInfo.load(this);
+ info.setLogger(log);
+ engine = GalaxiEngine.init(info);
+
+ ConfigUpdater.updateConfig(new File(engine.getRuntimeDirectory(), "config.yml"));
+ config = new YAMLConfig(new File(engine.getRuntimeDirectory(), "config.yml"));
+
+ Util.reflect(SubLoggerImpl.class.getDeclaredField("logn"), null, config.get().getMap("Settings").getBoolean("Network-Log", true));
+ Util.reflect(SubLoggerImpl.class.getDeclaredField("logc"), null, config.get().getMap("Settings").getBoolean("Console-Log", true));
+
+ engine.getPluginManager().loadPlugins(new File(engine.getRuntimeDirectory(), "Plugins"));
+
+ running = true;
+ reload(false);
+
+ subdata.put(0, null);
+ subprotocol = SubProtocol.get();
+ subprotocol.registerCipher("DHE", DHE.get(128));
+ subprotocol.registerCipher("DHE-128", DHE.get(128));
+ subprotocol.registerCipher("DHE-192", DHE.get(192));
+ subprotocol.registerCipher("DHE-256", DHE.get(256));
+ api.name = config.get().getMap("Settings").getMap("SubData").getString("Name");
+ Logger log = new Logger("SubData");
+
+ if (config.get().getMap("Settings").getMap("SubData").getString("Password", "").length() > 0) {
+ subprotocol.registerCipher("AES", new AES(128, config.get().getMap("Settings").getMap("SubData").getString("Password")));
+ subprotocol.registerCipher("AES-128", new AES(128, config.get().getMap("Settings").getMap("SubData").getString("Password")));
+ subprotocol.registerCipher("AES-192", new AES(192, config.get().getMap("Settings").getMap("SubData").getString("Password")));
+ subprotocol.registerCipher("AES-256", new AES(256, config.get().getMap("Settings").getMap("SubData").getString("Password")));
+
+ log.info.println("AES Encryption Available");
+ }
+ if (new File(engine.getRuntimeDirectory(), "subdata.rsa.key").exists()) {
+ try {
+ subprotocol.registerCipher("RSA", new RSA(new File(engine.getRuntimeDirectory(), "subdata.rsa.key")));
+ log.info.println("RSA Encryption Available");
+ } catch (Exception e) {
+ log.error.println(e);
+ }
+ }
+
+ reconnect = true;
+ log.info.println();
+ log.info.println("Connecting to /" + config.get().getMap("Settings").getMap("SubData").getString("Address", "127.0.0.1:4391"));
+ connect(log.toPrimitive(), null);
+
server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8090);
@@ -20,4 +113,41 @@ public class JettyServer {
handler.addServletWithMapping(StatusServlet.class, "/status");
server.start();
}
+
+ public void reload(boolean notifyPlugins) throws IOException {
+ resetDate = Calendar.getInstance().getTime().getTime();
+
+ ConfigUpdater.updateConfig(new File(engine.getRuntimeDirectory(), "config.yml"));
+ config.reload();
+
+ if (notifyPlugins) {
+ engine.getPluginManager().executeEvent(new GalaxiReloadEvent(engine));
+ }
+ }
+
+ private void connect(final java.util.logging.Logger log, Pair disconnect) throws IOException {
+ final int reconnect = config.get().getMap("Settings").getMap("SubData").getInt("Reconnect", 60);
+ if (disconnect == null || (this.reconnect && reconnect > 0 && disconnect.key() != DisconnectReason.PROTOCOL_MISMATCH && disconnect.key() != DisconnectReason.ENCRYPTION_MISMATCH)) {
+ final long reset = resetDate;
+ final Timer timer = new Timer(SubAPI.getInstance().getAppInfo().getName() + "::SubData_Reconnect_Handler");
+ if (disconnect != null) log.info("Attempting reconnect in " + reconnect + " seconds");
+ timer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ try {
+ if (reset == resetDate && (subdata.getOrDefault(0, null) == null || subdata.get(0).isClosed())) {
+ SubDataClient open = subprotocol.open(InetAddress.getByName(config.get().getMap("Settings").getMap("SubData").getString("Address", "127.0.0.1:4391").split(":")[0]),
+ Integer.parseInt(config.get().getMap("Settings").getMap("SubData").getString("Address", "127.0.0.1:4391").split(":")[1]));
+
+ if (subdata.getOrDefault(0, null) != null) subdata.get(0).reconnect(open);
+ subdata.put(0, open);
+ }
+ timer.cancel();
+ } catch (IOException e) {
+ log.info("Connection was unsuccessful, retrying in " + reconnect + " seconds");
+ }
+ }
+ }, (disconnect == null)?0: TimeUnit.SECONDS.toMillis(reconnect), TimeUnit.SECONDS.toMillis(reconnect));
+ }
+ }
}
\ No newline at end of file
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Library/ConfigUpdater.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Library/ConfigUpdater.java
new file mode 100644
index 00000000..460cd398
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Library/ConfigUpdater.java
@@ -0,0 +1,83 @@
+package net.ME1312.SubServers.Web.Library;
+
+import net.ME1312.Galaxi.Library.Config.YAMLConfig;
+import net.ME1312.Galaxi.Library.Config.YAMLSection;
+import net.ME1312.Galaxi.Library.Map.ObjectMap;
+import net.ME1312.Galaxi.Library.Version.Version;
+import net.ME1312.SubServers.Web.SubAPI;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+/**
+ * SubServers Configuration Updater
+ */
+public class ConfigUpdater {
+ private static final Version UNSIGNED = new Version(new SimpleDateFormat("yy'w'ww'zz'").format(Calendar.getInstance().getTime()));
+
+ /**
+ * Update SubServers' config.yml
+ *
+ * @param file File to bring up-to-date
+ */
+ public static void updateConfig(File file) throws IOException {
+ YAMLConfig config = new YAMLConfig(file);
+ YAMLSection existing = config.get().clone();
+ YAMLSection updated = existing.clone();
+ YAMLSection rewritten = new YAMLSection();
+
+ Version was = existing.getMap("Settings", new ObjectMap<>()).getVersion("Version", new Version(0));
+ Version now = SubAPI.getInstance().getAppInfo().getBuild();
+
+ int i = 0;
+ if (now == null) now = UNSIGNED;
+ if (!existing.contains("Settings") || !existing.getMap("Settings").contains("Version")) {
+
+ i++;
+ SubAPI.getInstance().getAppInfo().getLogger().info.println("Created ./config.yml");
+ } else {
+ if (was.compareTo(new Version("19w17a")) <= 0) {
+ if (existing.getMap("Settings", new YAMLSection()).contains("Log")) {
+ updated.getMap("Settings").safeSet("Console-Log", existing.getMap("Settings").getBoolean("Log"));
+ updated.getMap("Settings").safeSet("Network-Log", existing.getMap("Settings").getBoolean("Log"));
+ }
+
+ existing = updated.clone();
+ i++;
+ } if (was.compareTo(new Version("20w24c")) <= 0) {
+ // additions only this time
+
+ i++;
+ }// if (was.compareTo(new Version("99w99a")) <= 0) {
+ // // do something
+ // i++;
+ //}
+
+ if (i > 0) SubAPI.getInstance().getAppInfo().getLogger().info.println("Updated ./config.yml (" + i + " pass" + ((i != 1)?"es":"") + ")");
+ }
+
+ if (i > 0) {
+ YAMLSection settings = new YAMLSection();
+ settings.set("Version", ((now.compareTo(was) <= 0)?was:now).toString());
+ settings.set("Console-Log", updated.getMap("Settings", new YAMLSection()).getBoolean("Console-Log", true));
+ settings.set("Network-Log", updated.getMap("Settings", new YAMLSection()).getBoolean("Network-Log", true));
+ settings.set("Web-Bind", updated.getMap("Settings", new YAMLSection()).getString("Web-Bind", "127.0.0.1"));
+ settings.set("Web-Port", updated.getMap("Settings", new YAMLSection()).getInt("Web-Port", 8090));
+
+
+ YAMLSection subdata = new YAMLSection();
+ subdata.set("Name", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getString("Name", "undefined"));
+ subdata.set("Address", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getString("Address", "127.0.0.1:4391"));
+ if (updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).contains("Password")) subdata.set("Password", updated.getMap("Settings").getMap("SubData").getString("Password"));
+ if (updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).contains("Reconnect")) subdata.set("Reconnect", updated.getMap("Settings").getMap("SubData").getInt("Reconnect"));
+ settings.set("SubData", subdata);
+
+ rewritten.set("Settings", settings);
+
+ config.set(rewritten);
+ config.save();
+ }
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLogger.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLogger.java
new file mode 100644
index 00000000..2d50974b
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLogger.java
@@ -0,0 +1,266 @@
+package net.ME1312.SubServers.Web.Logging;
+
+import net.ME1312.Galaxi.Log.Logger;
+import org.slf4j.Marker;
+
+public class SLF4JLogger implements org.slf4j.Logger{
+ private Logger logger;
+
+ public SLF4JLogger(Logger logger) {
+ this.logger = logger;
+ }
+
+ @Override
+ public String getName() {
+ return logger.getPrefix();
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return false;
+ }
+
+ @Override
+ public void trace(String s) {}
+
+ @Override
+ public void trace(String s, Object o) {}
+
+ @Override
+ public void trace(String s, Object o, Object o1) {}
+
+ @Override
+ public void trace(String s, Object... objects) {}
+
+ @Override
+ public void trace(String s, Throwable throwable) {}
+
+ @Override
+ public boolean isTraceEnabled(Marker marker) {return false;}
+
+ @Override
+ public void trace(Marker marker, String s) {}
+
+ @Override
+ public void trace(Marker marker, String s, Object o) {}
+
+ @Override
+ public void trace(Marker marker, String s, Object o, Object o1) {}
+
+ @Override
+ public void trace(Marker marker, String s, Object... objects) {}
+
+ @Override
+ public void trace(Marker marker, String s, Throwable throwable) {}
+
+ @Override
+ public boolean isDebugEnabled() {
+ return true;
+ }
+
+ @Override
+ public void debug(String s) {
+ logger.debug.println(s);
+ }
+
+ @Override
+ public void debug(String s, Object o) {
+ logger.debug.print(s);
+ logger.debug.println(o);
+ }
+
+ @Override
+ public void debug(String s, Object o, Object o1) {
+ logger.debug.print(s);
+ logger.debug.print(o);
+ logger.debug.println(o1);
+ }
+
+ @Override
+ public void debug(String s, Object... objects) {
+ logger.debug.print(s);
+ logger.debug.println(objects);
+ }
+
+ @Override
+ public void debug(String s, Throwable throwable) {
+ logger.debug.print(s);
+ logger.debug.println(throwable);
+ }
+
+ @Override
+ public boolean isDebugEnabled(Marker marker) {return false;}
+
+ @Override
+ public void debug(Marker marker, String s) {}
+
+ @Override
+ public void debug(Marker marker, String s, Object o) {}
+
+ @Override
+ public void debug(Marker marker, String s, Object o, Object o1) {}
+
+ @Override
+ public void debug(Marker marker, String s, Object... objects) {}
+
+ @Override
+ public void debug(Marker marker, String s, Throwable throwable) {}
+
+ @Override
+ public boolean isInfoEnabled() {
+ return true;
+ }
+
+ @Override
+ public void info(String s) {
+ logger.info.println(s);
+ }
+
+ @Override
+ public void info(String s, Object o) {
+ logger.info.print(s);
+ logger.info.println(o);
+ }
+
+ @Override
+ public void info(String s, Object o, Object o1) {
+ logger.info.print(s);
+ logger.info.print(s);
+ logger.info.println(o1);
+ }
+
+ @Override
+ public void info(String s, Object... objects) {
+ logger.info.print(s);
+ logger.info.println(objects);
+ }
+
+ @Override
+ public void info(String s, Throwable throwable) {
+ logger.info.print(s);
+ logger.info.println(throwable);
+ }
+
+ @Override
+ public boolean isInfoEnabled(Marker marker) {return false;}
+
+ @Override
+ public void info(Marker marker, String s) {}
+
+ @Override
+ public void info(Marker marker, String s, Object o) {}
+
+ @Override
+ public void info(Marker marker, String s, Object o, Object o1) {}
+
+ @Override
+ public void info(Marker marker, String s, Object... objects) {}
+
+ @Override
+ public void info(Marker marker, String s, Throwable throwable) {}
+
+ @Override
+ public boolean isWarnEnabled() {
+ return true;
+ }
+
+ @Override
+ public void warn(String s) {
+ logger.warn.println(s);
+ }
+
+ @Override
+ public void warn(String s, Object o) {
+ logger.warn.print(s);
+ logger.warn.println(o);
+ }
+
+ @Override
+ public void warn(String s, Object... objects) {
+ logger.warn.print(s);
+ logger.warn.println(objects);
+ }
+
+ @Override
+ public void warn(String s, Object o, Object o1) {
+ logger.warn.print(s);
+ logger.warn.println(o);
+ logger.warn.println(o1);
+ }
+
+ @Override
+ public void warn(String s, Throwable throwable) {
+ logger.warn.print(s);
+ logger.warn.println(throwable);
+ }
+
+ @Override
+ public boolean isWarnEnabled(Marker marker) {return false;}
+
+ @Override
+ public void warn(Marker marker, String s) {}
+
+ @Override
+ public void warn(Marker marker, String s, Object o) {}
+
+ @Override
+ public void warn(Marker marker, String s, Object o, Object o1) {}
+
+ @Override
+ public void warn(Marker marker, String s, Object... objects) {}
+
+ @Override
+ public void warn(Marker marker, String s, Throwable throwable) {}
+
+ @Override
+ public boolean isErrorEnabled() {
+ return true;
+ }
+
+ @Override
+ public void error(String s) {
+ logger.error.println(s);
+ }
+
+ @Override
+ public void error(String s, Object o) {
+ logger.error.print(s);
+ logger.error.println(o);
+ }
+
+ @Override
+ public void error(String s, Object o, Object o1) {
+ logger.error.print(s);
+ logger.error.print(o);
+ logger.error.println(o1);
+ }
+
+ @Override
+ public void error(String s, Object... objects) {
+ logger.error.print(s);
+ logger.error.println(objects);
+ }
+
+ @Override
+ public void error(String s, Throwable throwable) {
+ logger.error.println(s);
+ }
+
+ @Override
+ public boolean isErrorEnabled(Marker marker) {return false;}
+
+ @Override
+ public void error(Marker marker, String s) {}
+
+ @Override
+ public void error(Marker marker, String s, Object o) {}
+
+ @Override
+ public void error(Marker marker, String s, Object o, Object o1) {}
+
+ @Override
+ public void error(Marker marker, String s, Object... objects) {}
+
+ @Override
+ public void error(Marker marker, String s, Throwable throwable) {}
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerFactory.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerFactory.java
new file mode 100644
index 00000000..ef525a01
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerFactory.java
@@ -0,0 +1,10 @@
+package net.ME1312.SubServers.Web.Logging;
+
+import org.slf4j.Logger;
+
+public class SLF4JLoggerFactory implements org.slf4j.ILoggerFactory {
+ @Override
+ public Logger getLogger(String s) {
+ return new SLF4JLogger(new net.ME1312.Galaxi.Log.Logger(s));
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerProvider.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerProvider.java
new file mode 100644
index 00000000..079cb3ea
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerProvider.java
@@ -0,0 +1,34 @@
+package net.ME1312.SubServers.Web.Logging;
+
+import net.ME1312.SubServers.Web.SubAPI;
+import org.slf4j.ILoggerFactory;
+import org.slf4j.IMarkerFactory;
+import org.slf4j.spi.MDCAdapter;
+import org.slf4j.spi.SLF4JServiceProvider;
+
+public class SLF4JLoggerProvider implements SLF4JServiceProvider {
+ @Override
+ public ILoggerFactory getLoggerFactory() {
+ return new SLF4JLoggerFactory();
+ }
+
+ @Override
+ public IMarkerFactory getMarkerFactory() {
+ return null;
+ }
+
+ @Override
+ public MDCAdapter getMDCAdapter() {
+ return null;
+ }
+
+ @Override
+ public String getRequestedApiVersion() {
+ return "2.0"; //SLF4J api version
+ }
+
+ @Override
+ public void initialize() {
+
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermission.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermission.java
new file mode 100644
index 00000000..a9a438e1
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermission.java
@@ -0,0 +1,56 @@
+package net.ME1312.SubServers.Web.Network.Packet;
+
+import net.ME1312.Galaxi.Library.Map.ObjectMap;
+import net.ME1312.Galaxi.Library.Util;
+import net.ME1312.SubData.Client.Protocol.Forwardable;
+import net.ME1312.SubData.Client.Protocol.PacketObjectIn;
+import net.ME1312.SubData.Client.Protocol.PacketObjectOut;
+import net.ME1312.SubData.Client.SubDataSender;
+
+import java.util.HashMap;
+import java.util.UUID;
+import java.util.function.Consumer;
+
+/**
+ * Check Permission Packet
+ */
+public class PacketCheckPermission implements Forwardable, PacketObjectIn, PacketObjectOut {
+ static HashMap[]> callbacks = new HashMap[]>();
+ private UUID player;
+ private String permission;
+ private UUID tracker;
+
+ /**
+ * New PacketCheckPermission (In)
+ */
+ public PacketCheckPermission() {}
+
+ /**
+ * New PacketCheckPermission (Out)
+ *
+ * @param player Player to check on
+ * @param permission Permission to check
+ * @param callback Callbacks
+ */
+ @SafeVarargs
+ public PacketCheckPermission(UUID player, String permission, Consumer... callback) {
+ this.player = player;
+ this.permission = permission;
+ this.tracker = Util.getNew(callbacks.keySet(), UUID::randomUUID);
+ callbacks.put(tracker, callback);
+ }
+
+ @Override
+ public ObjectMap send(SubDataSender client) throws Throwable {
+ ObjectMap data = new ObjectMap();
+ data.set(0x0000, tracker);
+ data.set(0x0001, player);
+ data.set(0x0002, permission);
+ return data;
+ }
+
+ @Override
+ public void receive(SubDataSender client, ObjectMap data) throws Throwable {
+ client.sendPacket(new PacketCheckPermissionResponse(data.getUUID(0x0001), data.getString(0x0002), (data.contains(0x0000))?data.getUUID(0x0000):null));
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermissionResponse.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermissionResponse.java
new file mode 100644
index 00000000..1134d604
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermissionResponse.java
@@ -0,0 +1,51 @@
+package net.ME1312.SubServers.Web.Network.Packet;
+
+import net.ME1312.Galaxi.Library.Map.ObjectMap;
+import net.ME1312.SubData.Client.Protocol.Forwardable;
+import net.ME1312.SubData.Client.Protocol.PacketObjectIn;
+import net.ME1312.SubData.Client.Protocol.PacketObjectOut;
+import net.ME1312.SubData.Client.SubDataSender;
+
+import java.util.UUID;
+import java.util.function.Consumer;
+
+import static net.ME1312.SubServers.Web.Network.Packet.PacketCheckPermission.callbacks;
+
+
+/**
+ * Check Permission Response Packet
+ */
+public class PacketCheckPermissionResponse implements Forwardable, PacketObjectIn, PacketObjectOut {
+ private boolean result;
+ private UUID tracker;
+
+ /**
+ * New PacketCheckPermissionResponse (In)
+ */
+ public PacketCheckPermissionResponse() {}
+
+ /**
+ * New PacketCheckPermissionResponse (Out)
+ *
+ * @param player Player to check on
+ * @param permission Permission to check
+ * @param tracker Receiver ID
+ */
+ public PacketCheckPermissionResponse(UUID player, String permission, UUID tracker) {
+ this.result = false; // TODO
+ this.tracker = tracker;
+ }
+
+ @Override
+ public ObjectMap send(SubDataSender client) throws Throwable {
+ ObjectMap data = new ObjectMap();
+ data.set(0x0000, tracker);
+ data.set(0x0001, result);
+ return data;
+ }
+
+ @Override
+ public void receive(SubDataSender client, ObjectMap data) throws Throwable {
+ for (Consumer callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data.getBoolean(0x0001));
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketDownloadLang.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketDownloadLang.java
new file mode 100644
index 00000000..ea50f084
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketDownloadLang.java
@@ -0,0 +1,48 @@
+package net.ME1312.SubServers.Web.Network.Packet;
+
+import net.ME1312.Galaxi.Library.Container.ContainedPair;
+import net.ME1312.Galaxi.Library.Map.ObjectMap;
+import net.ME1312.Galaxi.Library.Try;
+import net.ME1312.Galaxi.Library.Util;
+import net.ME1312.SubData.Client.Protocol.PacketObjectIn;
+import net.ME1312.SubData.Client.Protocol.PacketOut;
+import net.ME1312.SubData.Client.SubDataClient;
+import net.ME1312.SubData.Client.SubDataSender;
+import net.ME1312.SubServers.Host.ExHost;
+import net.ME1312.SubServers.Web.JettyServer;
+
+import java.util.Calendar;
+import java.util.logging.Logger;
+
+/**
+ * Download Lang Packet
+ */
+public class PacketDownloadLang implements PacketObjectIn, PacketOut {
+ private JettyServer host;
+
+ /**
+ * New PacketDownloadLang (In)
+ *
+ * @param host ExHost
+ */
+ public PacketDownloadLang(JettyServer host) {
+ Util.nullpo(host);
+ this.host = host;
+ }
+
+ /**
+ * New PacketDownloadLang (Out)
+ */
+ public PacketDownloadLang() {}
+
+ @Override
+ public void receive(SubDataSender client, ObjectMap data) {
+ Logger log = Try.all.get(() -> Util.reflect(SubDataClient.class.getDeclaredField("log"), client.getConnection()));
+ try {
+ Util.reflect(JettyServer.class.getDeclaredField("lang"), host, new ContainedPair<>(Calendar.getInstance().getTime().getTime(), data.getObject(0x0001)));
+ log.info("Lang Settings Downloaded");
+ } catch (IllegalAccessException | NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketLinkExHost.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketLinkExHost.java
new file mode 100644
index 00000000..36783715
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketLinkExHost.java
@@ -0,0 +1,65 @@
+package net.ME1312.SubServers.Web.Network.Packet;
+
+import net.ME1312.Galaxi.Engine.GalaxiEngine;
+import net.ME1312.Galaxi.Library.Map.ObjectMap;
+import net.ME1312.Galaxi.Library.Try;
+import net.ME1312.Galaxi.Library.Util;
+import net.ME1312.SubData.Client.Library.DebugUtil;
+import net.ME1312.SubData.Client.Protocol.Initial.InitialPacket;
+import net.ME1312.SubData.Client.Protocol.PacketObjectIn;
+import net.ME1312.SubData.Client.Protocol.PacketObjectOut;
+import net.ME1312.SubData.Client.SubDataClient;
+import net.ME1312.SubData.Client.SubDataSender;
+import net.ME1312.SubServers.Host.ExHost;
+import net.ME1312.SubServers.Web.JettyServer;
+
+import java.util.logging.Logger;
+
+/**
+ * Link Host Packet
+ */
+public class PacketLinkExHost implements InitialPacket, PacketObjectIn, PacketObjectOut {
+ private JettyServer host;
+ private int channel;
+
+ /**
+ * New PacketLinkHost (In)
+ *
+ * @param host SubServers.Host
+ */
+ public PacketLinkExHost(JettyServer host) {
+ Util.nullpo(host);
+ this.host = host;
+ }
+
+ /**
+ * New PacketLinkHost (Out)
+ *
+ * @param host SubServers.Host
+ */
+ public PacketLinkExHost(JettyServer host, int channel) {
+ Util.nullpo(host);
+ this.host = host;
+ this.channel = channel;
+ }
+
+ @Override
+ public ObjectMap send(SubDataSender client) {
+ ObjectMap data = new ObjectMap();
+ data.set(0x0000, host.api.getName());
+ data.set(0x0001, channel);
+ return data;
+ }
+
+ @Override
+ public void receive(SubDataSender client, ObjectMap data) throws Throwable {
+ Logger log = Try.all.get(() -> Util.reflect(SubDataClient.class.getDeclaredField("log"), client.getConnection()));
+ if (data.getInt(0x0001) == 0) {
+ setReady(client.getConnection());
+ } else {
+ log.severe("Could not link name with host" + ((data.contains(0x0002))?": "+data.getString(0x0002):'.'));
+ DebugUtil.logException(new IllegalStateException(), log);
+ GalaxiEngine.getInstance().stop();
+ }
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExLogMessage.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExLogMessage.java
new file mode 100644
index 00000000..336dae9c
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExLogMessage.java
@@ -0,0 +1,41 @@
+package net.ME1312.SubServers.Web.Network.Packet;
+
+import net.ME1312.Galaxi.Library.Map.ObjectMap;
+import net.ME1312.SubData.Client.Protocol.PacketObjectOut;
+import net.ME1312.SubData.Client.SubDataSender;
+
+import java.util.UUID;
+
+/**
+ * Message Log External Host Packet
+ */
+public class PacketOutExLogMessage implements PacketObjectOut {
+ private UUID address;
+ private Byte level;
+ private String line;
+
+ /**
+ * New PacketInExLogMessage (Out)
+ */
+ public PacketOutExLogMessage(UUID address, byte level, String line) {
+ this.address = address;
+ this.level = level;
+ this.line = line;
+ }
+
+ /**
+ * New PacketInExLogMessage (Reset)
+ */
+ public PacketOutExLogMessage(UUID address) {
+ this.address = address;
+ }
+
+ @Override
+ public ObjectMap send(SubDataSender client) throws Exception {
+ ObjectMap data = new ObjectMap();
+ data.set(0x0000, address);
+ if (level != null) data.set(0x0001, level);
+ if (line != null) data.set(0x0002, line);
+ return data;
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExRequestQueue.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExRequestQueue.java
new file mode 100644
index 00000000..7ee3f91f
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExRequestQueue.java
@@ -0,0 +1,15 @@
+package net.ME1312.SubServers.Web.Network.Packet;
+
+import net.ME1312.SubData.Client.Protocol.PacketOut;
+
+/**
+ * Queue Request Packet
+ */
+public class PacketOutExRequestQueue implements PacketOut {
+
+ /**
+ * New PacketOutExRequestQueue
+ */
+ public PacketOutExRequestQueue() {}
+
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/SubProtocol.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/SubProtocol.java
new file mode 100644
index 00000000..5c3d68aa
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/SubProtocol.java
@@ -0,0 +1,151 @@
+package net.ME1312.SubServers.Web.Network;
+
+import net.ME1312.Galaxi.Library.Container.Pair;
+import net.ME1312.Galaxi.Library.Map.ObjectMap;
+import net.ME1312.Galaxi.Library.Try;
+import net.ME1312.Galaxi.Library.Util;
+import net.ME1312.Galaxi.Library.Version.Version;
+import net.ME1312.SubData.Client.SubDataClient;
+import net.ME1312.SubData.Client.SubDataProtocol;
+import net.ME1312.SubServers.Client.Common.Network.Packet.*;
+import net.ME1312.SubServers.Host.Event.SubNetworkConnectEvent;
+import net.ME1312.SubServers.Host.Event.SubNetworkDisconnectEvent;
+import net.ME1312.SubServers.Web.Network.Packet.*;
+import net.ME1312.SubServers.Web.SubAPI;
+import net.ME1312.SubServers.Web.JettyServer;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.function.Consumer;
+import java.util.logging.Logger;
+
+/**
+ * SubServers Protocol Class
+ */
+public class SubProtocol extends SubDataProtocol {
+ private static SubProtocol instance;
+
+ @SuppressWarnings("deprecation")
+ protected SubProtocol() {
+ JettyServer host = SubAPI.getInstance().getInternals();
+
+ setName("SubServers 2");
+ addVersion(new Version("2.18a+"));
+
+ // 00-0F: Object Link Packets
+ registerPacket(0x0001, PacketLinkExHost.class);
+
+ registerPacket(0x0001, new PacketLinkExHost(host));
+
+
+ // 10-2F: Download Packets
+ registerPacket(0x0010, PacketDownloadLang.class);
+ registerPacket(0x0011, PacketDownloadPlatformInfo.class);
+ registerPacket(0x0012, PacketDownloadProxyInfo.class);
+ registerPacket(0x0013, PacketDownloadHostInfo.class);
+ registerPacket(0x0014, PacketDownloadGroupInfo.class);
+ registerPacket(0x0015, PacketDownloadServerInfo.class);
+ registerPacket(0x0016, PacketDownloadPlayerInfo.class);
+ registerPacket(0x0017, PacketCheckPermission.class);
+ registerPacket(0x0017, PacketCheckPermissionResponse.class);
+
+ registerPacket(0x0010, new PacketDownloadLang(host));
+ registerPacket(0x0011, new PacketDownloadPlatformInfo());
+ registerPacket(0x0012, new PacketDownloadProxyInfo());
+ registerPacket(0x0013, new PacketDownloadHostInfo());
+ registerPacket(0x0014, new PacketDownloadGroupInfo());
+ registerPacket(0x0015, new PacketDownloadServerInfo());
+ registerPacket(0x0016, new PacketDownloadPlayerInfo());
+ registerPacket(0x0017, new PacketCheckPermission());
+ registerPacket(0x0018, new PacketCheckPermissionResponse());
+
+
+ // 30-4F: Control Packets
+ registerPacket(0x0030, PacketCreateServer.class);
+ registerPacket(0x0031, PacketAddServer.class);
+ registerPacket(0x0032, PacketStartServer.class);
+ registerPacket(0x0033, PacketUpdateServer.class);
+ registerPacket(0x0034, PacketEditServer.class);
+ registerPacket(0x0035, PacketRestartServer.class);
+ registerPacket(0x0036, PacketCommandServer.class);
+ registerPacket(0x0037, PacketStopServer.class);
+ registerPacket(0x0038, PacketRemoveServer.class);
+ registerPacket(0x0039, PacketDeleteServer.class);
+ registerPacket(0x003B, PacketTransferPlayer.class);
+ registerPacket(0x003C, PacketDisconnectPlayer.class);
+ registerPacket(0x003D, PacketMessagePlayer.class);
+
+ registerPacket(0x0030, new PacketCreateServer());
+ registerPacket(0x0031, new PacketAddServer());
+ registerPacket(0x0032, new PacketStartServer());
+ registerPacket(0x0033, new PacketUpdateServer());
+ registerPacket(0x0034, new PacketEditServer());
+ registerPacket(0x0035, new PacketRestartServer());
+ registerPacket(0x0036, new PacketCommandServer());
+ registerPacket(0x0037, new PacketStopServer());
+ registerPacket(0x0038, new PacketRemoveServer());
+ registerPacket(0x0039, new PacketDeleteServer());
+ registerPacket(0x003B, new PacketTransferPlayer());
+ registerPacket(0x003C, new PacketDisconnectPlayer());
+ registerPacket(0x003D, new PacketMessagePlayer());
+
+ // 50-6F: External Host Packets
+ registerPacket(0x0053, PacketOutExRequestQueue.class);
+ }
+
+ public static SubProtocol get() {
+ if (instance == null)
+ instance = new SubProtocol();
+
+ return instance;
+ }
+
+ private Logger getLogger(int channel) {
+ return new net.ME1312.Galaxi.Log.Logger("SubData" + ((channel != 0)?File.separator+"+"+channel:"")).toPrimitive();
+ }
+
+ @Override
+ protected SubDataClient sub(Consumer scheduler, Logger logger, InetAddress address, int port, ObjectMap> login) throws IOException {
+ JettyServer host = SubAPI.getInstance().getInternals();
+ HashMap map = Try.all.get(() -> Util.reflect(JettyServer.class.getDeclaredField("subdata"), host));
+
+ int channel = 1;
+ while (map.containsKey(channel)) channel++;
+ final int fc = channel;
+
+ SubDataClient subdata = super.open(scheduler, getLogger(fc), address, port, login);
+ map.put(fc, subdata);
+ subdata.on.closed(client -> map.remove(fc));
+
+ return subdata;
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public SubDataClient open(Consumer scheduler, Logger logger, InetAddress address, int port) throws IOException {
+ JettyServer host = SubAPI.getInstance().getInternals();
+ HashMap map = Try.all.get(() -> Util.reflect(JettyServer.class.getDeclaredField("subdata"), host));
+
+ SubDataClient subdata = super.open(scheduler, logger, address, port);
+ subdata.sendPacket(new PacketDownloadLang());
+ subdata.sendPacket(new PacketOutExRequestQueue());
+ subdata.on.ready(client -> host.engine.getPluginManager().executeEvent(new SubNetworkConnectEvent((SubDataClient) client)));
+ subdata.on.closed(client -> {
+ SubNetworkDisconnectEvent event = new SubNetworkDisconnectEvent(client.value(), client.key());
+ host.engine.getPluginManager().executeEvent(event);
+
+ if (Try.all.get(() -> Util.reflect(JettyServer.class.getDeclaredField("running"), host), true)) {
+ Logger log = Try.all.get(() -> Util.reflect(SubDataClient.class.getDeclaredField("log"), client.value()));
+ Try.all.run(() -> Util.reflect(JettyServer.class.getDeclaredMethod("connect", Logger.class, Pair.class), host, log, client));
+ } else map.put(0, null);
+ });
+
+ return subdata;
+ }
+
+ public SubDataClient open(InetAddress address, int port) throws IOException {
+ return open(getLogger(0), address, port);
+ }
+}
diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/SubAPI.java b/SubServers.Web/src/net/ME1312/SubServers/Web/SubAPI.java
new file mode 100644
index 00000000..3660fa58
--- /dev/null
+++ b/SubServers.Web/src/net/ME1312/SubServers/Web/SubAPI.java
@@ -0,0 +1,106 @@
+package net.ME1312.SubServers.Web;
+
+import net.ME1312.Galaxi.Library.Util;
+import net.ME1312.Galaxi.Plugin.PluginInfo;
+import net.ME1312.SubData.Client.DataClient;
+import net.ME1312.SubData.Client.DataProtocol;
+import net.ME1312.SubServers.Client.Common.ClientAPI;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * SubAPI Class
+ */
+public final class SubAPI extends ClientAPI {
+ private final JettyServer host;
+ private static SubAPI api;
+ String name;
+
+ SubAPI(JettyServer host) {
+ this.host = host;
+ api = this;
+ }
+
+ /**
+ * Gets the SubAPI Methods
+ *
+ * @return SubAPI
+ */
+ public static SubAPI getInstance() {
+ return api;
+ }
+
+ /**
+ * Gets the SubServers Internals
+ *
+ * @deprecated Use SubAPI Methods when available
+ * @return ExHost Internals
+ */
+ @Deprecated
+ public JettyServer getInternals() {
+ return host;
+ }
+
+ /**
+ * Get the Host Name
+ *
+ * @return Host Name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the SubData Network Connections
+ *
+ * @return SubData Network Connections
+ */
+ public DataClient[] getSubDataNetwork() {
+ Integer[] keys = host.subdata.keySet().toArray(new Integer[0]);
+ DataClient[] channels = new DataClient[keys.length];
+ Arrays.sort(keys);
+ for (int i = 0; i < keys.length; ++i) channels[i] = host.subdata.get(keys[i]);
+ return channels;
+ }
+
+ /**
+ * Gets the SubData Network Protocol
+ *
+ * @return SubData Network Protocol
+ */
+ public DataProtocol getSubDataProtocol() {
+ return host.subprotocol;
+ }
+
+ /**
+ * Gets the current SubServers Lang Channels
+ *
+ * @return SubServers Lang Channel list
+ */
+ public Collection getLangChannels() {
+ return host.lang.value().keySet();
+ }
+
+ /**
+ * Gets values from the SubServers Lang
+ *
+ * @param channel Lang Channel
+ * @return Lang Value
+ */
+ public Map getLang(String channel) {
+ Util.nullpo(channel);
+ return new LinkedHashMap<>(host.lang.value().get(channel.toLowerCase()));
+ }
+
+ /**
+ * Gets the SubServers App Info
+ *
+ * @return SubServers App Info
+ */
+ public PluginInfo getAppInfo() {
+ return host.info;
+ }
+}