aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyeyoung <cyoung06@naver.com>2022-11-17 19:19:49 +0900
committersyeyoung <cyoung06@naver.com>2022-11-17 19:19:49 +0900
commit7a698d3d7e06684419c1c7a99cd59f41fee99524 (patch)
treecc4596d4176e28741542e677d1243eae44c3b0e6
parentf033c34b2e2a7824df41ea750b66b21685462279 (diff)
downloadSkyblock-Dungeons-Guide-7a698d3d7e06684419c1c7a99cd59f41fee99524.tar.gz
Skyblock-Dungeons-Guide-7a698d3d7e06684419c1c7a99cd59f41fee99524.tar.bz2
Skyblock-Dungeons-Guide-7a698d3d7e06684419c1c7a99cd59f41fee99524.zip
- Transformer to inject custom ASMEventHandler to handle classloader inconsistency issue
- Transformer to transform Event classes, because FML for some reason injects some stuff - Move all event registration into DungeonsGuide.java Signed-off-by: syeyoung <cyoung06@naver.com>
-rw-r--r--build.gradle147
-rw-r--r--loader/build.gradle3
-rwxr-xr-xloader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java73
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/coremod/DGTweaker.java29
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/coremod/EventBusTransformer.java49
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/DGAwareEventSubscriptionTransformer.java198
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/OwnerAwareASMEventHandler.java149
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiUnloadingError.java (renamed from loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiReferenceLeak.java)4
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java59
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/DGClassLoader.java5
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java7
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java2
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java53
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java5
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java24
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java4
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java1
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java8
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompClient.java2
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompManager.java2
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/BlockCache.java3
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TitleRender.java1
23 files changed, 610 insertions, 220 deletions
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index 7252969e..00000000
--- a/build.gradle
+++ /dev/null
@@ -1,147 +0,0 @@
-
-/*
- * 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/>.
- */
-
-plugins {
- id "idea"
- id "java"
- id "com.github.johnrengelman.shadow" version "7.1.2"
- id "dev.architectury.architectury-pack200" version "0.1.3"
- id "gg.essential.loom" version "0.10.0.+"
-}
-
-tasks.wrapper {
- gradleVersion = "7.4"
- // You can either download the binary-only version of Gradle (BIN) or
- // the full version (with sources and documentation) of Gradle (ALL)
- distributionType = Wrapper.DistributionType.ALL
-}
-version = "3.8.0"
-group = "kr.syeyoung.dungeonsguide"
-archivesBaseName = "dungeonsguide"
-
-java {
- toolchain.languageVersion.set(JavaLanguageVersion.of(8))
-}
-
-loom {
- launchConfigs {
- client {
- }
- }
- runs {
- "client" {
- property('devauth.enabled','true')
- client()
- }
- }
- forge {
- pack200Provider.set(new dev.architectury.pack200.java.Pack200Adapter())
- }
-}
-
-
-sourceSets.main {
- output.setResourcesDir(file("$buildDir/classes/java/main"))
-}
-
-
-repositories {
- mavenCentral()
- maven { url "https://jitpack.io" }
- maven {url "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1"}
-}
-
-configurations {
- implementation.extendsFrom shadowImpl
-}
-
-
-dependencies {
- minecraft("com.mojang:minecraft:1.8.9")
- mappings("de.oceanlabs.mcp:mcp_stable:22-1.8.9")
- forge("net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9")
-
-
- implementation 'org.jetbrains:annotations-java5:23.0.0'
- implementation 'org.java-websocket:Java-WebSocket:1.5.3'
- implementation "org.json:json:20220924"
- implementation 'com.twelvemonkeys.imageio:imageio-bmp:3.8.3'
-
- compileOnly 'org.projectlombok:lombok:1.18.24'
- annotationProcessor 'org.projectlombok:lombok:1.18.24'
-
- compileOnly files("jars/Hychat-1.12.1-BETA.jar")
-
- testCompileOnly "org.projectlombok:lombok:1.18.24"
- testAnnotationProcessor "org.projectlombok:lombok:1.18.24"
- modRuntimeOnly("me.djtheredstoner:DevAuth-forge-legacy:1.1.0")
-}
-
-tasks.withType(JavaCompile) {
- options.encoding = "UTF-8"
-}
-
-tasks.withType(Jar) {
- archivesBaseName = "dungeonsguide"
- manifest {
- attributes["FMLCorePluginContainsFMLMod"] = "true"
- attributes["ForceLoadAsMod"] = "true"
-
- // If you don't want mixins, remove these lines
-// this["TweakClass"] = "org.spongepowered.asm.launch.MixinTweaker"
-// this["MixinConfigs"] = "mixins.examplemod.json"
- }
-}
-
-
-tasks.shadowJar {
-
- archiveFileName = jar.archiveFileName
-
- relocate "org.java_websocket", "kr.syeyoung.org.java_websocket"
-
- dependencies {
- include(dependency("org.java-websocket:Java-WebSocket:1.5.3"))
- include(dependency("org.slf4j:slf4j-api:1.7.25"))
- include(dependency("org.json:json:20220924"))
- include(dependency("com.twelvemonkeys..*:.*"))
- }
-}
-
-tasks.named("remapJar") {
- archiveClassifier = "all"
- from(tasks.shadowJar)
- input = tasks.shadowJar.archiveFile
-}
-
-
-tasks.assemble.dependsOn tasks.remapJar
-
-processResources {
- inputs.property 'version', project.version
-
- // replace stuff in mcmod.info, nothing else
- from(sourceSets.main.resources.srcDirs) {
- duplicatesStrategy = 'include'
- include 'mcmod.info'
-
- // replace version and mcversion
- expand 'version': project.version
- }
-} \ No newline at end of file
diff --git a/loader/build.gradle b/loader/build.gradle
index 14bd8e7b..921d9d41 100644
--- a/loader/build.gradle
+++ b/loader/build.gradle
@@ -21,7 +21,7 @@ loom {
// probably will have to my own mixin tweaker, due to dungeonsguide's weird dynamic loading stuff
// property("mixin.debug", "true")
// property("asmhelper.verbose", "true")
-// arg("--tweakClass", "org.spongepowered.asm.launch.MixinTweaker")
+ arg("--tweakClass", "kr.syeyoung.dungeonsguide.launcher.coremod.DGTweaker")
// arg("--mixin", "mixins.examplemod.json")
}
@@ -87,6 +87,7 @@ tasks.withType(Jar) {
manifest {
attributes["FMLCorePluginContainsFMLMod"] = "true"
attributes["ForceLoadAsMod"] = "true"
+ attributes["TweakClass"] = "kr.syeyoung.dugneonsguide.launcher.coremod.DGTweaker"
// If you don't want mixins, remove these lines
// this["TweakClass"] = "org.spongepowered.asm.launch.MixinTweaker"
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
index 782c3648..1678c58f 100755
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
@@ -24,17 +24,16 @@ import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideLoadingExcepti
import kr.syeyoung.dungeonsguide.launcher.exceptions.NoSuitableLoaderFoundException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.NoVersionFoundException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
-import kr.syeyoung.dungeonsguide.launcher.exceptions.auth.PrivacyPolicyRequiredException;
import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiDisplayer;
import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiLoadingError;
-import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiPrivacyPolicy;
-import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiReferenceLeak;
+import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiUnloadingError;
import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.Notification;
import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.NotificationManager;
import kr.syeyoung.dungeonsguide.launcher.loader.IDGLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.JarLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.LocalLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.RemoteLoader;
+import lombok.Getter;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraftforge.common.MinecraftForge;
@@ -44,8 +43,9 @@ import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.ProgressManager;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
-import javax.swing.*;
import java.io.*;
import java.util.*;
@@ -75,9 +75,11 @@ public class Main
listeners.remove(dungeonsGuideReloadListener);
}
+
+ @Getter
private IDGLoader currentLoader;
- private UUID dgUnloaded = UUID.randomUUID();
+ private static final UUID dgUnloaded = UUID.randomUUID();
@EventHandler
public void initEvent(FMLInitializationEvent initializationEvent) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
@@ -121,7 +123,14 @@ public class Main
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
} catch (DungeonsGuideLoadingException e) {
e.printStackTrace();
+
+ try {
+ unload();
+ } catch (Exception e2) {
+ GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e2));
+ }
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
+
}
}
@@ -147,7 +156,7 @@ public class Main
File f = new File(configDir, "loader.cfg");
Configuration configuration = new Configuration(f);
IDGLoader idgLoader = obtainLoader(configuration);
- load(idgLoader);
+ reload(idgLoader);
} catch (NoSuitableLoaderFoundException e) {
e.printStackTrace();
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
@@ -156,7 +165,14 @@ public class Main
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
} catch (DungeonsGuideLoadingException e) {
e.printStackTrace();
+ try {
+ unload();
+ } catch (Exception e2) {
+ GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e2));
+ }
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
+ } catch (ReferenceLeakedException e) {
+ GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e));
}
})
.unremovable(true)
@@ -166,9 +182,11 @@ public class Main
if (dgInterface != null) throw new IllegalStateException("DG is loaded");
dgInterface = newLoader.loadDungeonsGuide();
currentLoader = newLoader;
-
- dgInterface.init(configDir);
-
+ try {
+ dgInterface.init(configDir);
+ } catch (Exception e) {
+ throw new DungeonsGuideLoadingException("Exception occured while calling init", e);
+ }
for (DungeonsGuideReloadListener listener : listeners) {
listener.onLoad(dgInterface);
}
@@ -183,21 +201,42 @@ public class Main
NotificationManager.INSTANCE.removeNotification(dgUnloaded);
}
- public void reload(IDGLoader newLoader) {
+
+ private volatile IDGLoader reqLoader = null;
+ public void reloadWithoutStacktraceReference(IDGLoader newLoader) {
+ reqLoader = newLoader;
+ }
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent tickEvent) {
+ if (reqLoader != null) {
+ IDGLoader loader = reqLoader;
+ reqLoader = null;
+
+ try {
+ reload(loader);
+ } catch (DungeonsGuideLoadingException e) {
+ try {
+ unload();
+ } catch (Exception e2) {
+ GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e2));
+ }
+ GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
+ } catch (ReferenceLeakedException e) {
+ GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e));
+ }
+ }
+ }
+
+ public void reload(IDGLoader newLoader) throws DungeonsGuideLoadingException, ReferenceLeakedException {
try {
unload();
load(newLoader);
- } catch (DungeonsGuideLoadingException | ReferenceLeakedException e) {
+ } catch (DungeonsGuideLoadingException | ReferenceLeakedException | UnsupportedOperationException e) {
dgInterface = null;
currentLoader = null;
e.printStackTrace();
-
- if (e instanceof DungeonsGuideLoadingException) {
- GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
- } else {
- GuiDisplayer.INSTANCE.displayGui(new GuiReferenceLeak(e));
- }
+ throw e;
}
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/coremod/DGTweaker.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/coremod/DGTweaker.java
new file mode 100644
index 00000000..cd12e47c
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/coremod/DGTweaker.java
@@ -0,0 +1,29 @@
+package kr.syeyoung.dungeonsguide.launcher.coremod;
+
+import net.minecraft.launchwrapper.ITweaker;
+import net.minecraft.launchwrapper.LaunchClassLoader;
+
+import java.io.File;
+import java.util.List;
+
+public class DGTweaker implements ITweaker {
+ @Override
+ public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
+
+ }
+
+ @Override
+ public void injectIntoClassLoader(LaunchClassLoader classLoader) {
+ classLoader.registerTransformer(EventBusTransformer.class.getName());
+ }
+
+ @Override
+ public String getLaunchTarget() {
+ return null;
+ }
+
+ @Override
+ public String[] getLaunchArguments() {
+ return new String[0];
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/coremod/EventBusTransformer.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/coremod/EventBusTransformer.java
new file mode 100644
index 00000000..bcfa0cef
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/coremod/EventBusTransformer.java
@@ -0,0 +1,49 @@
+package kr.syeyoung.dungeonsguide.launcher.coremod;
+
+import net.minecraft.launchwrapper.IClassTransformer;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.tree.*;
+
+import java.util.Iterator;
+
+public class EventBusTransformer implements IClassTransformer {
+
+ @Override
+ public byte[] transform(String name, String transformedName, byte[] basicClass) {
+ if (name.equals("net.minecraftforge.fml.common.eventhandler.EventBus")) {
+
+ String targetMethodName = "register";
+
+ ClassNode classNode = new ClassNode();
+ ClassReader classReader = new ClassReader(basicClass);
+ classReader.accept(classNode, 0);
+
+ Iterator<MethodNode> methods = classNode.methods.iterator();
+ while(methods.hasNext())
+ {
+ MethodNode m = methods.next();
+ if ((m.name.equals(targetMethodName) && m.desc.equals("(Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/reflect/Method;Lnet/minecraftforge/fml/common/ModContainer;)V")))
+ {
+ AbstractInsnNode curr = m.instructions.getFirst();
+ while ((curr = curr.getNext()) != m.instructions.getLast()) {
+ if (curr instanceof TypeInsnNode && ((TypeInsnNode) curr).desc.equals("net/minecraftforge/fml/common/eventhandler/ASMEventHandler")) {
+ ((TypeInsnNode) curr).desc = "kr/syeyoung/dungeonsguide/launcher/events/OwnerAwareASMEventHandler";
+ }
+ if (curr instanceof MethodInsnNode && ((MethodInsnNode) curr).owner.equals("net/minecraftforge/fml/common/eventhandler/ASMEventHandler")) {
+ ((MethodInsnNode) curr).owner = "kr/syeyoung/dungeonsguide/launcher/events/OwnerAwareASMEventHandler";
+ }
+ }
+
+ break;
+ }
+ }
+
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+ classNode.accept(writer);
+ return writer.toByteArray();
+ }
+
+ return basicClass;
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/DGAwareEventSubscriptionTransformer.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/DGAwareEventSubscriptionTransformer.java
new file mode 100644
index 00000000..cbe83e9b
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/DGAwareEventSubscriptionTransformer.java
@@ -0,0 +1,198 @@
+package kr.syeyoung.dungeonsguide.launcher.events;
+
+import net.minecraft.launchwrapper.IClassTransformer;
+import net.minecraftforge.fml.common.eventhandler.Event;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.*;
+
+import java.util.List;
+
+import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
+import static org.objectweb.asm.Opcodes.*;
+import static org.objectweb.asm.Type.*;
+import static org.objectweb.asm.Type.VOID_TYPE;
+
+public class DGAwareEventSubscriptionTransformer implements IClassTransformer
+{
+ private ClassLoader classLoader;
+ public DGAwareEventSubscriptionTransformer(ClassLoader classLoader)
+ {
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public byte[] transform(String name, String transformedName, byte[] bytes)
+ {
+ if (bytes == null || name.equals("net.minecraftforge.fml.common.eventhandler.Event") || name.startsWith("net.minecraft.") || name.indexOf('.') == -1)
+ {
+ return bytes;
+ }
+ ClassReader cr = new ClassReader(bytes);
+ ClassNode classNode = new ClassNode();
+ cr.accept(classNode, 0);
+
+ try
+ {
+ if (buildEvents(classNode))
+ {
+ ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
+ classNode.accept(cw);
+ return cw.toByteArray();
+ }
+ return bytes;
+ }
+ catch (ClassNotFoundException ex)
+ {
+ // Discard silently- it's just noise
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ return bytes;
+ }
+
+ private boolean buildEvents(ClassNode classNode) throws Exception
+ {
+ // Yes, this recursively loads classes until we get this base class. THIS IS NOT A ISSUE. Coremods should handle re-entry just fine.
+ // If they do not this a COREMOD issue NOT a Forge/LaunchWrapper issue.
+ Class<?> parent = classLoader.loadClass(classNode.superName.replace('/', '.'));
+ if (!Event.class.isAssignableFrom(parent))
+ {
+ return false;
+ }
+
+ //Class<?> listenerListClazz = Class.forName("net.minecraftforge.fml.common.eventhandler.ListenerList", false, getClass().getClassLoader());
+ Type tList = Type.getType("Lnet/minecraftforge/fml/common/eventhandler/ListenerList;");
+
+ boolean edited = false;
+ boolean hasSetup = false;
+ boolean hasGetListenerList = false;
+ boolean hasDefaultCtr = false;
+ boolean hasCancelable = false;
+ boolean hasResult = false;
+ String voidDesc = Type.getMethodDescriptor(VOID_TYPE);
+ String boolDesc = Type.getMethodDescriptor(BOOLEAN_TYPE);
+ String listDesc = tList.getDescriptor();
+ String listDescM = Type.getMethodDescriptor(tList);
+
+ for (MethodNode method : (List<MethodNode>)classNode.methods)
+ {
+ if (method.name.equals("setup") && method.desc.equals(voidDesc) && (method.access & ACC_PROTECTED) == ACC_PROTECTED) hasSetup = true;
+ if ((method.access & ACC_PUBLIC) == ACC_PUBLIC)
+ {
+ if (method.name.equals("getListenerList") && method.desc.equals(listDescM)) hasGetListenerList = true;
+ if (method.name.equals("isCancelable") && method.desc.equals(boolDesc)) hasCancelable = true;
+ if (method.name.equals("hasResult") && method.desc.equals(boolDesc)) hasResult = true;
+ }
+ if (method.name.equals("<init>") && method.desc.equals(voidDesc)) hasDefaultCtr = true;
+ }
+
+ if (classNode.visibleAnnotations != null)
+ {
+ for (AnnotationNode node : classNode.visibleAnnotations)
+ {
+ if (!hasResult && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Event$HasResult;"))
+ {
+ /* Add:
+ * public boolean hasResult()
+ * {
+ * return true;
+ * }
+ */
+ MethodNode method = new MethodNode(ACC_PUBLIC, "hasResult", boolDesc, null, null);
+ method.instructions.add(new InsnNode(ICONST_1));
+ method.instructions.add(new InsnNode(IRETURN));
+ classNode.methods.add(method);
+ edited = true;
+ }
+ else if (!hasCancelable && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Cancelable;"))
+ {
+ /* Add:
+ * public boolean isCancelable()
+ * {
+ * return true;
+ * }
+ */
+ MethodNode method = new MethodNode(ACC_PUBLIC, "isCancelable", boolDesc, null, null);
+ method.instructions.add(new InsnNode(ICONST_1));
+ method.instructions.add(new InsnNode(IRETURN));
+ classNode.methods.add(method);
+ edited = true;
+ }
+ }
+ }
+
+ if (hasSetup)
+ {
+ if (!hasGetListenerList)
+ throw new RuntimeException("Event class defines setup() but does not define getListenerList! " + classNode.name);
+ else
+ return edited;
+ }
+
+ Type tSuper = Type.getType(classNode.superName);
+
+ //Add private static ListenerList LISTENER_LIST
+ classNode.fields.add(new FieldNode(ACC_PRIVATE | ACC_STATIC, "LISTENER_LIST", listDesc, null, null));
+
+ /*Add:
+ * public <init>()
+ * {
+ * super();
+ * }
+ */
+ if (!hasDefaultCtr)
+ {
+ MethodNode method = new MethodNode(ACC_PUBLIC, "<init>", voidDesc, null, null);
+ method.instructions.add(new VarInsnNode(ALOAD, 0));
+ method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "<init>", voidDesc, false));
+ method.instructions.add(new InsnNode(RETURN));
+ classNode.methods.add(method);
+ }
+
+ /*Add:
+ * protected void setup()
+ * {
+ * super.setup();
+ * if (LISTENER_LIST != NULL)
+ * {
+ * return;
+ * }
+ * LISTENER_LIST = new ListenerList(super.getListenerList());
+ * }
+ */
+ MethodNode method = new MethodNode(ACC_PROTECTED, "setup", voidDesc, null, null);
+ method.instructions.add(new VarInsnNode(ALOAD, 0));
+ method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "setup", voidDesc, false));
+ method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
+ LabelNode initLisitener = new LabelNode();
+ method.instructions.add(new JumpInsnNode(IFNULL, initLisitener));
+ method.instructions.add(new InsnNode(RETURN));
+ method.instructions.add(initLisitener);
+ method.instructions.add(new FrameNode(F_SAME, 0, null, 0, null));
+ method.instructions.add(new TypeInsnNode(NEW, tList.getInternalName()));
+ method.instructions.add(new InsnNode(DUP));
+ method.instructions.add(new VarInsnNode(ALOAD, 0));
+ method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "getListenerList", listDescM, false));
+ method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tList.getInternalName(), "<init>", getMethodDescriptor(VOID_TYPE, tList), false));
+ method.instructions.add(new FieldInsnNode(PUTSTATIC, classNode.name, "LISTENER_LIST", listDesc));
+ method.instructions.add(new InsnNode(RETURN));
+ classNode.methods.add(method);
+
+ /*Add:
+ * public ListenerList getListenerList()
+ * {
+ * return this.LISTENER_LIST;
+ * }
+ */
+ method = new MethodNode(ACC_PUBLIC, "getListenerList", listDescM, null, null);
+ method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
+ method.instructions.add(new InsnNode(ARETURN));
+ classNode.methods.add(method);
+ return true;
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/OwnerAwareASMEventHandler.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/OwnerAwareASMEventHandler.java
new file mode 100644
index 00000000..3475e672
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/OwnerAwareASMEventHandler.java
@@ -0,0 +1,149 @@
+package kr.syeyoung.dungeonsguide.launcher.events;
+
+import static org.objectweb.asm.Opcodes.*;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+import net.minecraftforge.fml.common.ModContainer;
+
+import net.minecraftforge.fml.common.eventhandler.Event;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.IEventListener;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.apache.logging.log4j.ThreadContext;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+
+import com.google.common.collect.Maps;
+
+
+public class OwnerAwareASMEventHandler implements IEventListener
+{
+ private static int IDs = 0;
+ private static final String HANDLER_DESC = Type.getInternalName(IEventListener.class);
+ private static final String HANDLER_FUNC_DESC = Type.getMethodDescriptor(IEventListener.class.getDeclaredMethods()[0]);
+ private static final HashMap<Method, Class<?>> cache = Maps.newHashMap();
+ private static final boolean GETCONTEXT = Boolean.parseBoolean(System.getProperty("fml.LogContext", "false"));
+
+ private final IEventListener handler;
+ private final SubscribeEvent subInfo;
+ private ModContainer owner;
+ private String readable;
+
+ public OwnerAwareASMEventHandler(Object target, Method method, ModContainer owner) throws Exception
+ {
+ this.owner = owner;
+ handler = (IEventListener)createWrapper(method).getConstructor(Object.class).newInstance(target);
+ subInfo = method.getAnnotation(SubscribeEvent.class);
+ readable = "ASM: " + target + " " + method.getName() + Type.getMethodDescriptor(method);
+ }
+
+ @Override
+ public void invoke(Event event)
+ {
+ if (GETCONTEXT)
+ ThreadContext.put("mod", owner == null ? "" : owner.getName());
+ if (handler != null)
+ {
+ if (!event.isCancelable() || !event.isCanceled() || subInfo.receiveCanceled())
+ {
+ handler.invoke(event);
+ }
+ }
+ if (GETCONTEXT)
+ ThreadContext.remove("mod");
+ }
+
+ public EventPriority getPriority()
+ {
+ return subInfo.priority();
+ }
+
+ public Class<?> createWrapper(Method callback)
+ {
+ if (cache.containsKey(callback))
+ {
+ return cache.get(callback);
+ }
+
+ ClassWriter cw = new ClassWriter(0);
+ MethodVisitor mv;
+
+ String name = getUniqueName(callback);
+ String desc = name.replace('.', '/');
+ String instType = Type.getInternalName(callback.getDeclaringClass());
+ String eventType = Type.getInternalName(callback.getParameterTypes()[0]);
+
+ /*
+ System.out.println("Name: " + name);
+ System.out.println("Desc: " + desc);
+ System.out.println("InstType: " + instType);
+ System.out.println("Callback: " + callback.getName() + Type.getMethodDescriptor(callback));
+ System.out.println("Event: " + eventType);
+ */
+
+ cw.visit(V1_6, ACC_PUBLIC | ACC_SUPER, desc, null, "java/lang/Object", new String[]{ HANDLER_DESC });
+
+ cw.visitSource(".dynamic", null);
+ {
+ cw.visitField(ACC_PUBLIC, "instance", "Ljava/lang/Object;", null, null).visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/Object;)V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitFieldInsn(PUTFIELD, desc, "instance", "Ljava/lang/Object;");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(2, 2);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "invoke", HANDLER_FUNC_DESC, null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, desc, "instance", "Ljava/lang/Object;");
+ mv.visitTypeInsn(CHECKCAST, instType);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitTypeInsn(CHECKCAST, eventType);
+ mv.visitMethodInsn(INVOKEVIRTUAL, instType, callback.getName(), Type.getMethodDescriptor(callback), false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(2, 2);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ Class<?> ret = new ASMClassLoader(callback.getDeclaringClass().getClassLoader()).define(name, cw.toByteArray());
+ cache.put(callback, ret);
+ return ret;
+ }
+
+ private String getUniqueName(Method callback)
+ {
+ return String.format("%s_%d_%s_%s_%s", getClass().getName(), IDs++,
+ callback.getDeclaringClass().getSimpleName(),
+ callback.getName(),
+ callback.getParameterTypes()[0].getSimpleName());
+ }
+
+ private static class ASMClassLoader extends ClassLoader
+ {
+ private ASMClassLoader(ClassLoader classLoader)
+ {
+ super(classLoader);
+ }
+
+ public Class<?> define(String name, byte[] data)
+ {
+ return defineClass(name, data, 0, data.length);
+ }
+ }
+
+ public String toString()
+ {
+ return readable;
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiReferenceLeak.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiUnloadingError.java
index 9c0a5980..dd05dec4 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiReferenceLeak.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiUnloadingError.java
@@ -30,9 +30,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
-public class GuiReferenceLeak extends SpecialGuiScreen {
+public class GuiUnloadingError extends SpecialGuiScreen {
private final String stacktrace;
- public GuiReferenceLeak(Throwable cause) {
+ public GuiUnloadingError(Throwable cause) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(byteArrayOutputStream);
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java
index f3146e7f..661ad93c 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java
@@ -6,6 +6,7 @@ import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraftforge.client.event.GuiScreenEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Mouse;
@@ -28,6 +29,64 @@ public class NotificationManager {
tooltipList.remove(uid);
}
+
+ @SubscribeEvent
+ public void onRender(RenderGameOverlayEvent.Post postRender) {
+ ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ int widthX = fr.getStringWidth("X");
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(sr.getScaledWidth() - 5, sr.getScaledHeight() -5, 0);
+
+ int currY = sr.getScaledHeight() - 5;
+
+ for (Notification tooltip : tooltipList.values()) {
+ int width, height;
+ String[] description = tooltip.getDescription().split("\n");
+ width =
+ Math.max(
+ fr.getStringWidth(tooltip.getTitle()),
+ Arrays.stream(description).map(fr::getStringWidth).max(Integer::compareTo).orElse(300)
+ ) + 10;
+ height = description.length * fr.FONT_HEIGHT + 15 + fr.FONT_HEIGHT;
+
+ GlStateManager.translate(0, -height, 0);
+ currY -= height;
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(-width, 0, 0);
+ Gui.drawRect(0, 0,width,height, 0xFF23272a);
+ Gui.drawRect(1, 1, width-1, height-1, 0XFF2c2f33);
+
+ if (!tooltip.isUnremovable()) {
+ fr.drawString("X", width - widthX - 2, 2, 0xFFFF0000);
+ }
+
+ GlStateManager.translate(5,5,0);
+ fr.drawString(tooltip.getTitle(), 0,0, tooltip.getTitleColor());
+ GlStateManager.translate(0, fr.FONT_HEIGHT + 5, 0);
+ int y = 0;
+ for (String line : description) {
+ fr.drawString(line, 0, y, 0xFFAAAAAA);
+ y += fr.FONT_HEIGHT;
+ }
+ GlStateManager.popMatrix();
+
+ tooltip.setBoundRect(new Rectangle(
+ sr.getScaledWidth() - width - 5,
+ currY,
+ width,
+ height
+ ));
+
+ currY -= 5;
+ GlStateManager.translate(0, -5, 0);
+ }
+
+ GlStateManager.popMatrix();
+
+ }
@SubscribeEvent
public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) {
ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/DGClassLoader.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/DGClassLoader.java
index 1fbc39b0..a2f1a784 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/DGClassLoader.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/DGClassLoader.java
@@ -1,12 +1,14 @@
package kr.syeyoung.dungeonsguide.launcher.loader;
-import sun.misc.Resource;
+import kr.syeyoung.dungeonsguide.launcher.events.DGAwareEventSubscriptionTransformer;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
public abstract class DGClassLoader extends ClassLoader implements ByteStreamURLHandler.InputStreamGenerator{
+
+ DGAwareEventSubscriptionTransformer eventSubscriptionTransformer = new DGAwareEventSubscriptionTransformer(this);
public DGClassLoader(ClassLoader parent) {
super(parent);
}
@@ -53,6 +55,7 @@ public abstract class DGClassLoader extends ClassLoader implements ByteStreamURL
throw new ClassNotFoundException(name, e);
}
if (res != null) {
+ res = eventSubscriptionTransformer.transform(name, name, res);
return defineClass(name, res, 0, res.length);
} else {
throw new ClassNotFoundException(name);
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java
index dbb86dee..39fcbf58 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/JarLoader.java
@@ -66,7 +66,7 @@ public class JarLoader implements IDGLoader {
@Override
public InputStream convert(String name) { // / separated
if (this.loadedResources.containsKey(name.substring(1)))
- return new ByteArrayInputStream(this.loadedResources.get(name.substring(1)));
+ return new ByteArrayInputStream(this.loadedResources.get(name));
return null;
}
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java
index a47b2aaf..ec3e59fb 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/LocalLoader.java
@@ -23,6 +23,7 @@ import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideLoadingExcepti
import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
import org.apache.commons.io.IOUtils;
+import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -47,14 +48,16 @@ public class LocalLoader implements IDGLoader {
}
@Override
public byte[] getClassBytes(String name) throws IOException { // . separated.
- InputStream in = convert("/"+name.replace(".", "/")+".class");
+ if (name.startsWith("kr.syeyoung.dungeonsguide.launcher")) return null;
+ InputStream in = convert(name.replace(".", "/")+".class");
+ if (!(in instanceof BufferedInputStream)) return null;
if (in == null) return null;
return IOUtils.toByteArray(in);
}
@Override
public InputStream convert(String name) { // / separated
- return LocalLoader.class.getResourceAsStream(name);
+ return LocalLoader.class.getResourceAsStream("/"+name);
}
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java
index 446958a0..ceafb6f7 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java
@@ -73,7 +73,7 @@ public class RemoteLoader implements IDGLoader {
@Override
public InputStream convert(String name) { // / separated
if (this.loadedResources.containsKey(name.substring(1)))
- return new ByteArrayInputStream(this.loadedResources.get(name.substring(1)));
+ return new ByteArrayInputStream(this.loadedResources.get(name));
return null;
}
}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java
index 912e3ebc..52515a38 100755
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java
@@ -30,6 +30,7 @@ import kr.syeyoung.dungeonsguide.mod.config.Config;
import kr.syeyoung.dungeonsguide.mod.cosmetics.CosmeticsManager;
import kr.syeyoung.dungeonsguide.mod.discord.rpc.RichPresenceManager;
import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonFacade;
+import kr.syeyoung.dungeonsguide.mod.events.listener.DungeonListener;
import kr.syeyoung.dungeonsguide.mod.events.listener.FeatureListener;
import kr.syeyoung.dungeonsguide.mod.events.listener.PacketListener;
import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry;
@@ -58,6 +59,7 @@ import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -91,9 +93,17 @@ public class DungeonsGuide implements DGInterface {
CommandReparty commandReparty;
+ private List<Object> registeredListeners = new ArrayList<>();
+ public void registerEventsForge(Object object) {
+ registeredListeners.add(object);
+ MinecraftForge.EVENT_BUS.register(object);
+ }
public void init(File f) {
+ ClassLoader orignalLoader = Thread.currentThread().getContextClassLoader();
+
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
ProgressManager.ProgressBar progressbar = ProgressManager.push("DungeonsGuide", 4);
progressbar.step("Creating Configuration");
@@ -115,18 +125,19 @@ public class DungeonsGuide implements DGInterface {
e.printStackTrace();
}
- MinecraftForge.EVENT_BUS.register(this);
+ registerEventsForge(this);
progressbar.step("Registering Events & Commands");
skyblockStatus = new SkyblockStatus();
- MinecraftForge.EVENT_BUS.register(skyblockStatus);
-
+ registerEventsForge(skyblockStatus);
+ registerEventsForge(ChatTransmitter.INSTANCE);
+ registerEventsForge(new BlockCache());
+ registerEventsForge(TitleRender.getInstance());
(new FeatureRegistry()).init();
- new ChatTransmitter();
try {
Set<String> invalid = ReflectionHelper.getPrivateValue(LaunchClassLoader.class, (LaunchClassLoader) Main.class.getClassLoader(), "invalidClasses");
@@ -139,7 +150,9 @@ public class DungeonsGuide implements DGInterface {
this.blockCache = new BlockCache();
+ registerEventsForge(new DungeonListener());
this.dungeonFacade = new DungeonFacade();
+
dungeonFacade.init();
@@ -152,24 +165,24 @@ public class DungeonsGuide implements DGInterface {
ClientCommandHandler.instance.registerCommand(commandDungeonsGuide);
ClientCommandHandler.instance.registerCommand(command);
- MinecraftForge.EVENT_BUS.register(command);
- MinecraftForge.EVENT_BUS.register(commandDungeonsGuide);
+ registerEventsForge(command);
+ registerEventsForge(commandDungeonsGuide);
- MinecraftForge.EVENT_BUS.register(commandReparty = new CommandReparty());
+ registerEventsForge(commandReparty = new CommandReparty());
- MinecraftForge.EVENT_BUS.register(new FeatureListener());
- MinecraftForge.EVENT_BUS.register(new PacketListener());
- MinecraftForge.EVENT_BUS.register(new Keybinds());
+ registerEventsForge(new FeatureListener());
+ registerEventsForge(new PacketListener());
+ registerEventsForge(new Keybinds());
- MinecraftForge.EVENT_BUS.register(PartyManager.INSTANCE);
- MinecraftForge.EVENT_BUS.register(ChatProcessor.INSTANCE);
- MinecraftForge.EVENT_BUS.register(StaticResourceCache.INSTANCE);
+ registerEventsForge(PartyManager.INSTANCE);
+ registerEventsForge(ChatProcessor.INSTANCE);
+ registerEventsForge(StaticResourceCache.INSTANCE);
- MinecraftForge.EVENT_BUS.register(new AhUtils());
+ registerEventsForge(new AhUtils());
progressbar.step("Opening connection");
- MinecraftForge.EVENT_BUS.register(cosmeticsManager = new CosmeticsManager());
+ registerEventsForge(cosmeticsManager = new CosmeticsManager());
progressbar.step("Loading Config");
@@ -187,20 +200,20 @@ public class DungeonsGuide implements DGInterface {
System.setProperty("dg.safe", "true");
}
- MinecraftForge.EVENT_BUS.register(RichPresenceManager.INSTANCE);
+ registerEventsForge(RichPresenceManager.INSTANCE);
TimeScoreUtil.init();
ProgressManager.pop(progressbar);
+ Thread.currentThread().setContextClassLoader(orignalLoader);
}
@Override
public void unload() {
// have FUN!
-
-// bar.step("Instantiating...");
-// partialLoad(obtainLoader(configuration));
- throw new UnsupportedOperationException("Who the heck registered events in features?? This will stay unsupported for now");
+ for (Object registeredListener : registeredListeners) {
+ MinecraftForge.EVENT_BUS.unregister(registeredListener);
+ }
}
@Override
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java
index bfdbd5db..8a50211d 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java
@@ -17,9 +17,8 @@ public class ChatTransmitter {
public static final String PREFIX = "§eDungeons Guide §7:: ";
public static String prefix = "§eDungeons Guide §7:: ";
- public ChatTransmitter() {
- MinecraftForge.EVENT_BUS.register(this);
- }
+
+ public static ChatTransmitter INSTANCE = new ChatTransmitter();
static Queue<ChatComponentText> receiveQueue = new ConcurrentLinkedQueue<>();
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java
index 9b9811cd..5c65424e 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java
@@ -18,6 +18,7 @@
package kr.syeyoung.dungeonsguide.mod.commands;
+import kr.syeyoung.dungeonsguide.launcher.Main;
import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
import kr.syeyoung.dungeonsguide.mod.config.guiconfig.GuiConfigV2;
@@ -139,17 +140,20 @@ public class CommandDungeonsGuide extends CommandBase {
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §c" + args[1] + " is not valid number."));
}
}
+ } else if (args[0].equals("reload")) {
+ Main.getMain().reloadWithoutStacktraceReference(Main.getMain().getCurrentLoader());
} else {
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg §7-§fOpens configuration gui"));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg gui §7-§fOpens configuration gui"));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg help §7-§fShows command help"));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg reloadah §7-§f Reloads price data from server."));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg reparty §7-§f Reparty."));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg asktojoin or /dg atj §7-§f Toggle ask to join §cRequires Discord Rich Presence enabled. (/dg -> Advanced)"));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg partymax [number] or /dg pm [number] §7-§f Sets partymax §7(maximum amount people in party, for discord rpc)"));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg pv [ign] §7-§f Profile Viewer"));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg pvall §7-§f Profile Viewer For all people on party"));
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg purge §7-§f Purge api cache."));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg §7-§fOpens configuration gui"));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg gui §7-§fOpens configuration gui"));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg help §7-§fShows command help"));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg reloadah §7-§f Reloads price data from server."));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg reparty §7-§f Reparty."));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg asktojoin or /dg atj §7-§f Toggle ask to join §cRequires Discord Rich Presence enabled. (/dg -> Advanced)"));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg partymax [number] or /dg pm [number] §7-§f Sets partymax §7(maximum amount people in party, for discord rpc)"));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg pv [ign] §7-§f Profile Viewer"));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg pvall §7-§f Profile Viewer For all people on party"));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg purge §7-§f Purge api cache."));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg reload §7-§f Reload Current Version of Dungeons Guide. Auto update versions will not be updated."));
}
}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java
index 434d3998..76fc482e 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java
@@ -6,6 +6,7 @@ import kr.syeyoung.dungeonsguide.mod.events.listener.DungeonListener;
import lombok.Getter;
import lombok.Setter;
import net.minecraftforge.common.MinecraftForge;
+import org.apache.logging.log4j.ThreadContext;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
@@ -22,9 +23,6 @@ public class DungeonFacade {
private DungeonContext context;
public void init() {
- DungeonListener dgEventListener = new DungeonListener();
- MinecraftForge.EVENT_BUS.register(dgEventListener);
-
try {
DungeonRoomInfoRegistry.loadAll(Main.getConfigDir());
} catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException |
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java
index cc2f911a..bd495225 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java
@@ -56,7 +56,6 @@ public class FeatureTestPepole extends GuiFeature implements ChatListener, Dunge
addParameter("scale", new FeatureParameter<>("scale", "Scale", "Scale", 2.0f, "float", nval -> this.scale = nval));
- MinecraftForge.EVENT_BUS.register(this);
// (new Thread(() -> {
// while (true){
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java
index f88b2884..70af9397 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java
@@ -5,6 +5,7 @@ import kr.syeyoung.dungeonsguide.mod.chat.ChatProcessResult;
import kr.syeyoung.dungeonsguide.mod.chat.ChatProcessor;
import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
+import kr.syeyoung.dungeonsguide.mod.features.listener.TickListener;
import kr.syeyoung.dungeonsguide.mod.utils.ScoreBoardUtils;
import kr.syeyoung.dungeonsguide.mod.utils.TextUtils;
import kr.syeyoung.dungeonsguide.mod.utils.TitleRender;
@@ -23,7 +24,7 @@ import static kr.syeyoung.dungeonsguide.mod.chat.ChatProcessResult.REMOVE_CHAT;
/**
* CREDITS FOR THE COUNTDOWN SOUNDTRACK: <a href="https://www.youtube.com/watch?v=acCqrA-JxAw">...</a>
*/
-public class FeatureEpicCountdown extends SimpleFeature {
+public class FeatureEpicCountdown extends SimpleFeature implements TickListener {
static volatile long updatedAt;
static volatile int secondsLeft;
@@ -40,7 +41,6 @@ public class FeatureEpicCountdown extends SimpleFeature {
lastSec = GO_TEXT;
ChatProcessor.INSTANCE.subscribe(FeatureEpicCountdown::processChat);
- MinecraftForge.EVENT_BUS.register(this);
}
public static ChatProcessResult processChat(String txt, Map<String, Object> context) {
@@ -87,8 +87,8 @@ public class FeatureEpicCountdown extends SimpleFeature {
String lastSec;
@SubscribeEvent
- public void onTick(TickEvent.ClientTickEvent e){
- if(e.phase != TickEvent.Phase.START || !isEnabled() || !DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnDungeon()) return;
+ public void onTick(){
+ if(!isEnabled() || !DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnDungeon()) return;
ScoreBoardUtils.forEachLineClean(line -> {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompClient.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompClient.java
index 84705a1d..d23debc2 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompClient.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompClient.java
@@ -131,7 +131,7 @@ public class StompClient extends WebSocketClient {
if (heartbeat != null) heartbeat.cancel(true);
MinecraftForge.EVENT_BUS.post(new StompDiedEvent(code, reason, remote));
-
+ StompManager.getInstance().onStompDied(new StompDiedEvent(code, reason, remote));
}
@Override
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompManager.java
index e7248484..d430e586 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompManager.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompManager.java
@@ -21,7 +21,6 @@ public class StompManager {
public static StompManager getInstance() {
if (instance == null) {
instance = new StompManager();
- MinecraftForge.EVENT_BUS.register(instance);
}
return instance;
}
@@ -48,7 +47,6 @@ public class StompManager {
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
- @SubscribeEvent
public void onStompDied(StompDiedEvent event) {
logger.info("Stomp Connection closed, trying to reconnect - {} - {}", event.reason, event.code);
connectStomp();
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/BlockCache.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/BlockCache.java
index b8313778..366e09a0 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/BlockCache.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/BlockCache.java
@@ -15,9 +15,6 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.TimeUnit;
public class BlockCache {
- public BlockCache() {
- MinecraftForge.EVENT_BUS.register(this);
- }
@SuppressWarnings("UnstableApiUsage")
private final LoadingCache<BlockPos, IBlockState> cache = CacheBuilder.newBuilder()
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TitleRender.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TitleRender.java
index dfc0b0a1..3b8fe964 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TitleRender.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TitleRender.java
@@ -27,7 +27,6 @@ public class TitleRender {
}
private TitleRender() {
- MinecraftForge.EVENT_BUS.register(this);
}
protected static int titlesTimer;