aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java1
-rw-r--r--wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/DungeonsGuideReloadListener.java24
-rwxr-xr-xwrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java34
-rw-r--r--wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java2
-rw-r--r--wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java128
-rw-r--r--wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java58
6 files changed, 241 insertions, 6 deletions
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
index 28ce3735..b0b29e89 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
@@ -46,6 +46,7 @@ import kr.syeyoung.dungeonsguide.roomedit.EditingContext;
import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonRoomEdit;
import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor;
import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessor;
+import kr.syeyoung.dungeonsguide.stomp.StompPayload;
import kr.syeyoung.dungeonsguide.utils.AhUtils;
import kr.syeyoung.dungeonsguide.utils.MapUtils;
import kr.syeyoung.dungeonsguide.utils.ShortUtils;
diff --git a/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/DungeonsGuideReloadListener.java b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/DungeonsGuideReloadListener.java
new file mode 100644
index 00000000..7252a9db
--- /dev/null
+++ b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/DungeonsGuideReloadListener.java
@@ -0,0 +1,24 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.launcher;
+
+public interface DungeonsGuideReloadListener {
+ public void unloadReference();
+ public void onLoad(DGInterface dgInterface);
+}
diff --git a/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
index f7db1b44..bb3e5909 100755
--- a/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
+++ b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
@@ -26,6 +26,8 @@ import kr.syeyoung.dungeonsguide.launcher.exceptions.PrivacyPolicyRequiredExcept
import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.TokenExpiredException;
import kr.syeyoung.dungeonsguide.launcher.loader.IDGLoader;
+import kr.syeyoung.dungeonsguide.launcher.loader.JarLoader;
+import kr.syeyoung.dungeonsguide.launcher.loader.LocalLoader;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.gui.GuiScreen;
@@ -44,6 +46,9 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.io.*;
import java.security.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
@Mod(modid = Main.MOD_ID, version = Main.VERSION)
public class Main
@@ -60,6 +65,14 @@ public class Main
private Authenticator authenticator = new Authenticator();
private ModDownloader modDownloader = new ModDownloader(authenticator);
+ private List<DungeonsGuideReloadListener> listeners = new ArrayList<>();
+
+ public void addDGReloadListener(DungeonsGuideReloadListener dungeonsGuideReloadListener) {
+ listeners.add(Objects.requireNonNull(dungeonsGuideReloadListener));
+ }
+ public void removeDGReloadListener(DungeonsGuideReloadListener dungeonsGuideReloadListener) {
+ listeners.remove(dungeonsGuideReloadListener);
+ }
private IDGLoader currentLoader;
@@ -86,18 +99,25 @@ public class Main
throw new UnsupportedOperationException("Current version is not unloadable");
}
dgInterface = null;
+ for (DungeonsGuideReloadListener listener : listeners) {
+ listener.unloadReference();
+ }
if (currentLoader != null) {
currentLoader.unloadJar();
}
currentLoader = null;
}
- public void load(IDGLoader newLoader) {
+ public void load(IDGLoader newLoader) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
if (dgInterface != null) throw new IllegalStateException("DG is loaded");
newLoader.loadJar(authenticator);
dgInterface = newLoader.getInstance();
currentLoader = newLoader;
dgInterface.init(configDir);
+
+ for (DungeonsGuideReloadListener listener : listeners) {
+ listener.onLoad(dgInterface);
+ }
}
public void reload(IDGLoader newLoader) {
@@ -113,10 +133,12 @@ public class Main
}
public void tryOpenError() {
+ Minecraft.getMinecraft().displayGuiScreen(obtainErrorGUI());
}
public GuiScreen obtainErrorGUI() {
// when gets called init and stuff remove thing
+ return null;
}
@SubscribeEvent(priority = EventPriority.LOWEST)
@@ -144,12 +166,13 @@ public class Main
if ("local".equals(loader) ||
(loader.equals("auto") && this.getClass().getResourceAsStream("/kr/syeyoung/dungeonsguide/DungeonsGuide.class") == null)) {
-
- } else if ("jar".equals("loader") ||
- (loader.equals("auto") && this.getClass().getResourceAsStream("/mod.jar") == null)) {
-
+ return new LocalLoader();
+ } else if ("jar".equals(loader) ||
+ (loader.equals("auto") && this.getClass().getResourceAsStream("/mod.jar") == null)) {
+ return new JarLoader();
} else if (loader.equals("auto") ){
// remote load
+ throw new UnsupportedOperationException(""); // yet
} else {
throw new NoSuitableLoaderFoundException(System.getProperty("dg.loader"), configuration.get("loader", "modsource", "auto").getString());
}
@@ -231,6 +254,7 @@ public class Main
public void setLastError(Throwable t) {
lastError = t;
+ tryOpenError();
}
public static Main getMain() {
diff --git a/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java
index 607fc668..ceff437e 100644
--- a/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java
+++ b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java
@@ -24,7 +24,7 @@ import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
import net.minecraftforge.common.config.Configuration;
public interface IDGLoader {
- void loadJar(Authenticator authenticator);
+ void loadJar(Authenticator authenticator) throws InstantiationException, IllegalAccessException, ClassNotFoundException;
DGInterface getInstance();
void unloadJar() throws ReferenceLeakedException;
diff --git a/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java
new file mode 100644
index 00000000..2012412a
--- /dev/null
+++ b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java
@@ -0,0 +1,128 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.launcher.loader;
+
+import kr.syeyoung.dungeonsguide.launcher.DGInterface;
+import kr.syeyoung.dungeonsguide.launcher.Main;
+import kr.syeyoung.dungeonsguide.launcher.authentication.Authenticator;
+import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class JarLoader implements IDGLoader {
+ private DGInterface dgInterface;
+ private ReferenceQueue<ClassLoader> refQueue = new ReferenceQueue<>();
+ private PhantomReference<ClassLoader> phantomReference;
+
+ private boolean loaded;
+
+ public static class JarClassLoader extends URLClassLoader {
+ public JarClassLoader(URL[] urls, ClassLoader parent) {
+ super(urls, parent);
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+
+ synchronized (getClassLoadingLock(name)) {
+ // First, check if the class has already been loaded
+ Class<?> c = findLoadedClass(name);
+ if (c == null) {
+ long t0 = System.nanoTime();
+
+ if (c == null) {
+ // If still not found, then invoke findClass in order
+ // to find the class.
+ long t1 = System.nanoTime();
+ c = findClass(name);
+
+ // this is the defining class loader; record the stats
+ sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
+ sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
+ sun.misc.PerfCounter.getFindClasses().increment();
+ }
+ try {
+ if (getParent() != null && c == null) {
+ c = getParent().loadClass(name);
+ }
+ } catch (ClassNotFoundException e) {
+ // ClassNotFoundException thrown if class not found
+ // from the non-null parent class loader
+ }
+ }
+ if (resolve) {
+ resolveClass(c);
+ }
+ return c;
+ }
+ }
+
+ public Class<?> loadClassResolve(String name, boolean resolve) throws ClassNotFoundException {
+ return this.loadClass(name, resolve);
+ }
+ }
+
+ @Override
+ public void loadJar(Authenticator authenticator) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ if (dgInterface != null) throw new IllegalStateException("Already loaded");
+
+ JarClassLoader classLoader = new JarClassLoader(new URL[] {
+ Main.class.getResource("/mod.jar")
+ }, this.getClass().getClassLoader());
+
+ dgInterface = (DGInterface) classLoader.loadClassResolve("kr.syeyoung.dungeonsguide.DungeonsGuide", true).newInstance();
+ phantomReference = new PhantomReference<>(classLoader, refQueue);
+ }
+
+ @Override
+ public DGInterface getInstance() {
+ return dgInterface;
+ }
+
+ @Override
+ public void unloadJar() throws ReferenceLeakedException {
+ dgInterface.unload();
+ dgInterface = null;
+ System.gc();// pls do
+ Reference<? extends ClassLoader> t = refQueue.poll();
+ if (t == null) throw new ReferenceLeakedException(); // Why do you have to be that strict? Well, to tell them to actually listen on DungeonsGuideReloadListener. If it starts causing issues then I will remove check cus it's not really loaded (classes are loaded by child classloader)
+ t.clear();
+ phantomReference = null;
+ }
+
+ @Override
+ public boolean isUnloadable() {
+ return true;
+ }
+
+ @Override
+ public boolean isLoaded() {
+ return dgInterface != null;
+ }
+
+ @Override
+ public String strategyName() {
+ return "jar";
+ }
+}
diff --git a/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java
new file mode 100644
index 00000000..67c43ad5
--- /dev/null
+++ b/wrapper/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java
@@ -0,0 +1,58 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.launcher.loader;
+
+import kr.syeyoung.dungeonsguide.launcher.DGInterface;
+import kr.syeyoung.dungeonsguide.launcher.authentication.Authenticator;
+import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
+
+public class LocalLoader implements IDGLoader {
+ private DGInterface dgInterface;
+
+ @Override
+ public void loadJar(Authenticator authenticator) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ if (dgInterface != null) throw new IllegalStateException("Already loaded");
+ dgInterface = (DGInterface) Class.forName("kr.syeyoung.dungeonsguide.DungeonsGuide").newInstance();
+ }
+
+ @Override
+ public DGInterface getInstance() {
+ return dgInterface;
+ }
+
+ @Override
+ public void unloadJar() throws ReferenceLeakedException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isUnloadable() {
+ return false;
+ }
+
+ @Override
+ public boolean isLoaded() {
+ return dgInterface != null;
+ }
+
+ @Override
+ public String strategyName() {
+ return "local";
+ }
+}