diff options
15 files changed, 208 insertions, 74 deletions
diff --git a/loader/build.gradle b/loader/build.gradle index 921d9d41..2889f402 100644 --- a/loader/build.gradle +++ b/loader/build.gradle @@ -65,7 +65,6 @@ dependencies {      implementation "org.json:json:20171018"      implementation 'io.nayuki:qrcodegen:1.4.0' -    runtimeOnly project(':mod')      compileOnly "org.projectlombok:lombok:1.18.20"      annotationProcessor "org.projectlombok:lombok:1.18.16" @@ -99,13 +98,9 @@ tasks.withType(Jar) {  tasks.shadowJar {      archiveFileName = jar.archiveFileName -    relocate "org.java_websocket", "kr.syeyoung.org.java_websocket" -      dependencies { -        include(dependency("org.java-websocket:Java-WebSocket:1.5.1"))          include(dependency("org.slf4j:slf4j-api:1.7.25"))          include(dependency("org.json:json:20171018")) -        include(dependency("com.twelvemonkeys..*:.*"))      }  } 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 1678c58f..2ada9dc8 100755 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java @@ -23,7 +23,7 @@ import kr.syeyoung.dungeonsguide.launcher.branch.UpdateRetrieverUtil;  import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideLoadingException;  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.DungeonsGuideUnloadingException;  import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiDisplayer;  import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiLoadingError;  import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiUnloadingError; @@ -134,7 +134,7 @@ public class Main          }      } -    public void unload() throws ReferenceLeakedException { +    public void unload() throws DungeonsGuideUnloadingException {          if (currentLoader != null && !currentLoader.isUnloadable()) {              throw new UnsupportedOperationException("Current version is not unloadable");          } @@ -171,7 +171,7 @@ public class Main                              GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e2));                          }                          GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e)); -                    } catch (ReferenceLeakedException e) { +                    } catch (DungeonsGuideUnloadingException e) {                          GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e));                      }                  }) @@ -221,17 +221,17 @@ public class Main                      GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e2));                  }                  GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e)); -            } catch (ReferenceLeakedException e) { +            } catch (DungeonsGuideUnloadingException e) {                  GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e));              }          }      } -    public void reload(IDGLoader newLoader) throws DungeonsGuideLoadingException, ReferenceLeakedException { +    public void reload(IDGLoader newLoader) throws DungeonsGuideLoadingException, DungeonsGuideUnloadingException {          try {              unload();              load(newLoader); -        } catch (DungeonsGuideLoadingException | ReferenceLeakedException | UnsupportedOperationException e) { +        } catch (DungeonsGuideLoadingException | DungeonsGuideUnloadingException | UnsupportedOperationException e) {              dgInterface = null;              currentLoader = null; 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 index 3475e672..83f78720 100644 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/OwnerAwareASMEventHandler.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/events/OwnerAwareASMEventHandler.java @@ -4,6 +4,7 @@ import static org.objectweb.asm.Opcodes.*;  import java.lang.reflect.Method;  import java.util.HashMap; +import java.util.WeakHashMap;  import net.minecraftforge.fml.common.ModContainer; @@ -24,7 +25,6 @@ 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; @@ -63,11 +63,6 @@ public class OwnerAwareASMEventHandler implements IEventListener      public Class<?> createWrapper(Method callback)      { -        if (cache.containsKey(callback)) -        { -            return cache.get(callback); -        } -          ClassWriter cw = new ClassWriter(0);          MethodVisitor mv; @@ -116,9 +111,7 @@ public class OwnerAwareASMEventHandler implements IEventListener              mv.visitEnd();          }          cw.visitEnd(); -        Class<?> ret = new ASMClassLoader(callback.getDeclaringClass().getClassLoader()).define(name, cw.toByteArray()); -        cache.put(callback, ret); -        return ret; +        return new ASMClassLoader(callback.getDeclaringClass().getClassLoader()).define(name, cw.toByteArray());      }      private String getUniqueName(Method callback) diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/ReferenceLeakedException.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/DungeonsGuideUnloadingException.java index 3a88b862..6b2850f6 100644 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/ReferenceLeakedException.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/DungeonsGuideUnloadingException.java @@ -18,5 +18,7 @@  package kr.syeyoung.dungeonsguide.launcher.exceptions; -public class ReferenceLeakedException extends Exception { +public class DungeonsGuideUnloadingException extends Exception { +    public  DungeonsGuideUnloadingException(String message) {super(message);} +    public  DungeonsGuideUnloadingException(Exception cause) {super(cause);}  } diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java index 1edc0b7c..52982355 100644 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/IDGLoader.java @@ -20,14 +20,12 @@ package kr.syeyoung.dungeonsguide.launcher.loader;  import kr.syeyoung.dungeonsguide.launcher.DGInterface;  import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideLoadingException; -import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException; - -import java.io.IOException; +import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideUnloadingException;  public interface IDGLoader {      DGInterface loadDungeonsGuide() throws DungeonsGuideLoadingException;      DGInterface getInstance(); -    void unloadDungeonsGuide() throws ReferenceLeakedException; +    void unloadDungeonsGuide() throws DungeonsGuideUnloadingException;      boolean isUnloadable(); 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 39fcbf58..61dec833 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 @@ -19,22 +19,16 @@  package kr.syeyoung.dungeonsguide.launcher.loader;  import kr.syeyoung.dungeonsguide.launcher.DGInterface; -import kr.syeyoung.dungeonsguide.launcher.Main;  import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideLoadingException; -import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException; +import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideUnloadingException;  import org.apache.commons.io.IOUtils; -import sun.misc.Resource;  import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream;  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;  import java.util.HashMap;  import java.util.zip.ZipEntry;  import java.util.zip.ZipInputStream; @@ -94,13 +88,17 @@ public class JarLoader implements IDGLoader {      }      @Override -    public void unloadDungeonsGuide() throws ReferenceLeakedException { +    public void unloadDungeonsGuide() throws DungeonsGuideUnloadingException {          classLoader = null; -        dgInterface.unload(); +        try { +            dgInterface.unload(); +        } catch (Exception e) { +            throw new DungeonsGuideUnloadingException(e); +        }          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) +        if (t == null) throw new DungeonsGuideUnloadingException("Reference Leaked"); // 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;      } 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 ec3e59fb..519578f1 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 @@ -20,19 +20,15 @@ package kr.syeyoung.dungeonsguide.launcher.loader;  import kr.syeyoung.dungeonsguide.launcher.DGInterface;  import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideLoadingException; -import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException; +import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideUnloadingException;  import org.apache.commons.io.IOUtils;  import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream;  import java.io.IOException;  import java.io.InputStream;  import java.lang.ref.PhantomReference;  import java.lang.ref.Reference;  import java.lang.ref.ReferenceQueue; -import java.util.HashMap; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream;  public class LocalLoader implements IDGLoader {      private DGInterface dgInterface; @@ -84,13 +80,17 @@ public class LocalLoader implements IDGLoader {      }      @Override -    public void unloadDungeonsGuide() throws ReferenceLeakedException { +    public void unloadDungeonsGuide() throws DungeonsGuideUnloadingException {          classLoader = null; -        dgInterface.unload(); +        try { +            dgInterface.unload(); +        } catch (Exception e) { +            throw new DungeonsGuideUnloadingException(e); +        }          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) +        if (t == null) throw new DungeonsGuideUnloadingException("Reference Leaked"); // 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;      } 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 ceafb6f7..e4becc53 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 @@ -20,12 +20,11 @@ package kr.syeyoung.dungeonsguide.launcher.loader;  import kr.syeyoung.dungeonsguide.launcher.DGInterface;  import kr.syeyoung.dungeonsguide.launcher.branch.Update; -import kr.syeyoung.dungeonsguide.launcher.branch.UpdateBranch;  import kr.syeyoung.dungeonsguide.launcher.branch.UpdateRetrieverUtil;  import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideLoadingException;  import kr.syeyoung.dungeonsguide.launcher.exceptions.InvalidSignatureException;  import kr.syeyoung.dungeonsguide.launcher.exceptions.NoVersionFoundException; -import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException; +import kr.syeyoung.dungeonsguide.launcher.exceptions.DungeonsGuideUnloadingException;  import org.apache.commons.io.IOUtils;  import java.io.ByteArrayInputStream; @@ -35,7 +34,6 @@ import java.lang.ref.PhantomReference;  import java.lang.ref.Reference;  import java.lang.ref.ReferenceQueue;  import java.util.HashMap; -import java.util.List;  import java.util.zip.ZipEntry;  import java.util.zip.ZipInputStream; @@ -123,13 +121,18 @@ public class RemoteLoader implements IDGLoader {      }      @Override -    public void unloadDungeonsGuide() throws ReferenceLeakedException { +    public void unloadDungeonsGuide() throws DungeonsGuideUnloadingException {          classLoader = null; -        dgInterface.unload(); + +        try { +            dgInterface.unload(); +        } catch (Exception e) { +            throw new DungeonsGuideUnloadingException(e); +        }          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) +        if (t == null) throw new DungeonsGuideUnloadingException("Reference Leaked"); // 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;      } diff --git a/mod/build.gradle b/mod/build.gradle index 85b44238..33d028be 100644 --- a/mod/build.gradle +++ b/mod/build.gradle @@ -16,12 +16,20 @@ java {  loom {      launchConfigs { -        "client" { +        client {              // 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") + +        } +    } +    runs { +        client { +            runDir = 'runtime' +            property('devauth.enabled','true') +            client()          }      }      forge { @@ -38,6 +46,7 @@ sourceSets.main {  repositories {      mavenCentral()      maven { url "https://jitpack.io" } +    maven {url "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1"}  }  configurations { @@ -56,15 +65,16 @@ dependencies {      implementation "org.json:json:20171018"      implementation "com.twelvemonkeys.imageio:imageio-bmp:3.7.0" -    compileOnly project(':loader') - -      compileOnly "org.projectlombok:lombok:1.18.20"      compileOnly files("../jars/Hychat-1.12.1-BETA.jar")      annotationProcessor "org.projectlombok:lombok:1.18.16"      testCompileOnly "org.projectlombok:lombok:1.18.20"      testAnnotationProcessor "org.projectlombok:lombok:1.18.20" + + +    compileOnly project(path: ":loader") +    runtimeOnly project(path: ":loader")  }  tasks.withType(JavaCompile) { @@ -74,9 +84,6 @@ tasks.withType(JavaCompile) {  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" 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 f45164e9..f3c600fc 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java @@ -28,6 +28,8 @@ import kr.syeyoung.dungeonsguide.mod.commands.CommandDungeonsGuide;  import kr.syeyoung.dungeonsguide.mod.commands.CommandReparty;  import kr.syeyoung.dungeonsguide.mod.config.Config;  import kr.syeyoung.dungeonsguide.mod.cosmetics.CosmeticsManager; +import kr.syeyoung.dungeonsguide.mod.cosmetics.CustomNetworkPlayerInfo; +import kr.syeyoung.dungeonsguide.mod.discord.gamesdk.GameSDK;  import kr.syeyoung.dungeonsguide.mod.discord.rpc.RichPresenceManager;  import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonFacade;  import kr.syeyoung.dungeonsguide.mod.events.listener.DungeonListener; @@ -44,11 +46,21 @@ import kr.syeyoung.dungeonsguide.mod.utils.cursor.GLCursors;  import kr.syeyoung.dungeonsguide.mod.wsresource.StaticResourceCache;  import lombok.Getter;  import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.entity.EntityPlayerSP;  import net.minecraft.client.gui.*; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.client.renderer.entity.RenderManager;  import net.minecraft.client.resources.IResourceManager;  import net.minecraft.client.resources.IResourcePack; +import net.minecraft.command.CommandHandler;  import net.minecraft.command.ICommand; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP;  import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraft.network.play.server.S38PacketPlayerListItem; +import net.minecraft.world.World;  import net.minecraftforge.client.ClientCommandHandler;  import net.minecraftforge.client.event.GuiOpenEvent;  import net.minecraftforge.common.MinecraftForge; @@ -60,9 +72,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; +import java.util.*;  import java.util.concurrent.ThreadFactory;  import java.util.concurrent.atomic.AtomicInteger; @@ -139,10 +149,8 @@ public class DungeonsGuide implements DGInterface {      } +    private PacketListener packetListener;      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"); @@ -210,7 +218,7 @@ public class DungeonsGuide implements DGInterface {          registerEventsForge(commandReparty = new CommandReparty());          registerEventsForge(new FeatureListener()); -        registerEventsForge(new PacketListener()); +        registerEventsForge(packetListener = new PacketListener());          registerEventsForge(new Keybinds());          registerEventsForge(PartyManager.INSTANCE); @@ -232,7 +240,7 @@ public class DungeonsGuide implements DGInterface {          }          if (FeatureRegistry.ETC_REPARTY.isEnabled()) { -            ClientCommandHandler.instance.registerCommand(commandReparty); +            registerCommands(commandReparty);          }          if (FeatureRegistry.DISCORD_DONOTUSE.isEnabled()) { @@ -244,7 +252,29 @@ public class DungeonsGuide implements DGInterface {          ProgressManager.pop(progressbar); -        Thread.currentThread().setContextClassLoader(orignalLoader); +    } + +    // hotswap fails in dev env due to intellij auto log collection or smth. it holds ref to stacktrace. + +    private void transform(AbstractClientPlayer abstractClientPlayer) { +        NetworkPlayerInfo uuidNetworkPlayerInfoEntry = ReflectionHelper.getPrivateValue(AbstractClientPlayer.class, +                abstractClientPlayer, +                "playerInfo", "field_175157_a", "a" +        ); +        if (uuidNetworkPlayerInfoEntry instanceof CustomNetworkPlayerInfo) { +            S38PacketPlayerListItem s38PacketPlayerListItem = new S38PacketPlayerListItem(); +            NetworkPlayerInfo newInfo = new NetworkPlayerInfo(s38PacketPlayerListItem.new AddPlayerData( +                    uuidNetworkPlayerInfoEntry.getGameProfile(), +                    uuidNetworkPlayerInfoEntry.getResponseTime(), +                    uuidNetworkPlayerInfoEntry.getGameType(), +                    ((CustomNetworkPlayerInfo)uuidNetworkPlayerInfoEntry).getOriginalDisplayName() +            )); +            ReflectionHelper.setPrivateValue(AbstractClientPlayer.class, +                    abstractClientPlayer, +                    newInfo, +                    "playerInfo", "field_175157_a", "a" +            ); +        }      }      @Override @@ -255,7 +285,7 @@ public class DungeonsGuide implements DGInterface {          for (Object registeredListener : registeredListeners) {              MinecraftForge.EVENT_BUS.unregister(registeredListener);          } -        Set<ICommand> commands = ReflectionHelper.getPrivateValue(ClientCommandHandler.class, ClientCommandHandler.instance, "commandSet"); +        Set<ICommand> commands = ReflectionHelper.getPrivateValue(CommandHandler.class, ClientCommandHandler.instance, "commandSet");          for (ICommand registeredCommand : registeredCommands) {              ClientCommandHandler.instance.getCommands().remove(registeredCommand.getCommandName()); @@ -264,13 +294,72 @@ public class DungeonsGuide implements DGInterface {              }              commands.remove(registeredCommand);          } + +        if (packetListener != null) packetListener.cleanup(); + +        try { +            EntityPlayerSP ep = (EntityPlayerSP) Minecraft.getMinecraft().getRenderManager().livingPlayer; +            transform(ep); +        } catch (Exception e) { +            e.printStackTrace(); +        } + +        try { +            if (Minecraft.getMinecraft().pointedEntity instanceof AbstractClientPlayer) { +                AbstractClientPlayer ep = (AbstractClientPlayer) Minecraft.getMinecraft().pointedEntity; +                transform(ep); +            } +        } catch (Exception e) { +            e.printStackTrace(); +        } +        NetHandlerPlayClient netHandlerPlayClient = Minecraft.getMinecraft().getNetHandler(); +        if (netHandlerPlayClient == null) +            netHandlerPlayClient = ((EntityPlayerSP) Minecraft.getMinecraft().getRenderManager().livingPlayer).sendQueue; + +        if (netHandlerPlayClient != null) { +            Map<UUID, NetworkPlayerInfo> playerInfoMap = ReflectionHelper.getPrivateValue(NetHandlerPlayClient.class, +                    netHandlerPlayClient, "playerInfoMap", "field_147310_i", "i"); +            for (Map.Entry<UUID, NetworkPlayerInfo> uuidNetworkPlayerInfoEntry : playerInfoMap.entrySet()) { +                if (uuidNetworkPlayerInfoEntry.getValue() instanceof CustomNetworkPlayerInfo) { +                    S38PacketPlayerListItem s38PacketPlayerListItem = new S38PacketPlayerListItem(); +                    NetworkPlayerInfo newInfo =  new NetworkPlayerInfo(s38PacketPlayerListItem.new AddPlayerData( +                            uuidNetworkPlayerInfoEntry.getValue().getGameProfile(), +                            uuidNetworkPlayerInfoEntry.getValue().getResponseTime(), +                            uuidNetworkPlayerInfoEntry.getValue().getGameType(), +                            ((CustomNetworkPlayerInfo) uuidNetworkPlayerInfoEntry.getValue()).getOriginalDisplayName() +                    )); +                    playerInfoMap.put(uuidNetworkPlayerInfoEntry.getKey(), newInfo); +                } +            } +        } + +        World world = Minecraft.getMinecraft().getRenderManager().worldObj; +        if (world != null) { +            for (AbstractClientPlayer entity : world.getEntities(AbstractClientPlayer.class, input -> true)) { +                transform(entity); +            } +            for (AbstractClientPlayer player : world.getPlayers(AbstractClientPlayer.class, input -> true)) { +                transform(player); +            } +        } + +        try { +            List<IResourcePack> resourcePackList = ReflectionHelper.getPrivateValue(Minecraft.class, Minecraft.getMinecraft(), "defaultResourcePacks", "aA", "field_110449_ao"); +            resourcePackList.removeIf(a -> a instanceof DGTexturePack); +            Minecraft.getMinecraft().refreshResources(); +        } catch (Exception e) { +            e.printStackTrace(); +        } + +          THREAD_GROUP.interrupt();          THREAD_GROUP.stop();          try { -            Thread.sleep(1000); // This is requirement for all the threads to finish within 1 second. or reference leak. +            Thread.sleep(2000); // This is requirement for all the threads to finish within 1 second. or reference leak.          } catch (InterruptedException e) {          }          THREAD_GROUP.destroy(); +        GameSDK.cleanup();      }      @Override 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 5c65424e..fa516bfd 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 @@ -32,8 +32,12 @@ import kr.syeyoung.dungeonsguide.mod.stomp.StompManager;  import kr.syeyoung.dungeonsguide.mod.stomp.StompPayload;  import kr.syeyoung.dungeonsguide.mod.wsresource.StaticResourceCache;  import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiMainMenu; +import net.minecraft.client.gui.GuiMultiplayer; +import net.minecraft.client.multiplayer.WorldClient;  import net.minecraft.command.CommandBase;  import net.minecraft.command.ICommandSender; +import net.minecraft.realms.RealmsBridge;  import net.minecraft.util.ChatComponentText;  import net.minecraft.util.ChatStyle;  import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -141,7 +145,21 @@ public class CommandDungeonsGuide extends CommandBase {                  }              }          } else if (args[0].equals("reload")) { -            Main.getMain().reloadWithoutStacktraceReference(Main.getMain().getCurrentLoader()); +            Minecraft.getMinecraft().addScheduledTask(() -> { +                boolean flag = Minecraft.getMinecraft().isIntegratedServerRunning(); +                boolean flag1 = Minecraft.getMinecraft().isConnectedToRealms(); +                Minecraft.getMinecraft().theWorld.sendQuittingDisconnectingPacket(); +                Minecraft.getMinecraft().loadWorld((WorldClient)null); +                if (flag) { +                    Minecraft.getMinecraft().displayGuiScreen(new GuiMainMenu()); +                } else if (flag1) { +                    RealmsBridge realmsbridge = new RealmsBridge(); +                    realmsbridge.switchToRealms(new GuiMainMenu()); +                } else { +                    Minecraft.getMinecraft().displayGuiScreen(new GuiMultiplayer(new GuiMainMenu())); +                } +                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")); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/cosmetics/CustomNetworkPlayerInfo.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/cosmetics/CustomNetworkPlayerInfo.java index 7be9a1ca..a54efaf4 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/cosmetics/CustomNetworkPlayerInfo.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/cosmetics/CustomNetworkPlayerInfo.java @@ -18,17 +18,24 @@  package kr.syeyoung.dungeonsguide.mod.cosmetics; +import com.google.common.base.Objects;  import com.mojang.authlib.GameProfile; +import com.mojang.authlib.minecraft.MinecraftProfileTexture;  import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;  import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.client.Minecraft;  import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.client.resources.SkinManager;  import net.minecraft.network.play.server.S38PacketPlayerListItem;  import net.minecraft.scoreboard.ScorePlayerTeam;  import net.minecraft.util.ChatComponentText;  import net.minecraft.util.IChatComponent; +import net.minecraft.util.ResourceLocation;  import java.util.List; +// Reimplement this using ASM. Removing reference to this is too painful.  public class CustomNetworkPlayerInfo extends NetworkPlayerInfo {      public CustomNetworkPlayerInfo(GameProfile gameProfile) {          super(gameProfile); @@ -44,6 +51,10 @@ public class CustomNetworkPlayerInfo extends NetworkPlayerInfo {      private String unformattedDisplayText;      private String playerNameWithoutColor; +    public IChatComponent getOriginalDisplayName() { +        return displayName; +    } +      @Override      public void setDisplayName(IChatComponent displayNameIn) {          displayName = displayNameIn; @@ -66,6 +77,7 @@ public class CustomNetworkPlayerInfo extends NetworkPlayerInfo {          }      } +      public IChatComponent getDisplayName()      { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/GameSDK.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/GameSDK.java index f66043b5..cde3f7e2 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/GameSDK.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/GameSDK.java @@ -18,12 +18,11 @@  package kr.syeyoung.dungeonsguide.mod.discord.gamesdk; -import com.sun.jna.Library; -import com.sun.jna.Native; -import com.sun.jna.Platform; +import com.sun.jna.*;  import kr.syeyoung.dungeonsguide.mod.discord.gamesdk.jna.GameSDKTypeMapper;  import kr.syeyoung.dungeonsguide.mod.discord.gamesdk.jna.NativeGameSDK;  import lombok.Getter; +import net.minecraftforge.fml.relauncher.ReflectionHelper;  import java.io.File;  import java.io.IOException; @@ -31,6 +30,7 @@ import java.io.InputStream;  import java.nio.file.Files;  import java.nio.file.StandardCopyOption;  import java.util.Collections; +import java.util.Map;  public class GameSDK {      @Getter @@ -73,6 +73,20 @@ public class GameSDK {                  Collections.singletonMap(Library.OPTION_TYPE_MAPPER, GameSDKTypeMapper.INSTANCE));      } +    public static void cleanup() { +//        com.sun.jna.CallbackReference has reference of DiscordCallback. idk how i should approach fixing this -> I would better write native lib myself later. +        if (System.getProperty("dg.safe") == null) return; + +        Map infos = ReflectionHelper.getPrivateValue(Structure.class, null, "layoutInfo"); +        infos.clear(); +        Map options = ReflectionHelper.getPrivateValue(Native.class, null, "options"); +        options.clear(); +        Map alignments = ReflectionHelper.getPrivateValue(Native.class, null, "alignments"); +        alignments.clear(); +        Map<Class, TypeMapper> typeMapperMap = ReflectionHelper.getPrivateValue(Native.class, null, "typeMappers"); +        typeMapperMap.clear(); +    } +      public static void writeString(byte[] bts, String str) {          System.arraycopy(str.getBytes(), 0, bts, 0, str.getBytes().length);          bts[str.getBytes().length] = 0; diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketListener.java index acfffb7c..dcdc2c53 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketListener.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketListener.java @@ -188,6 +188,11 @@ public class PacketListener extends ChannelDuplexHandler {      }      public void cleanup() { -        thePipeline.remove("dg_packet_handler"); +        try { +            if (thePipeline != null) +                thePipeline.remove("dg_packet_handler"); +        } catch (Exception e) { + +        }      }  } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/AhUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/AhUtils.java index 62b11d3d..b28b97a5 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/AhUtils.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/AhUtils.java @@ -43,7 +43,7 @@ public class AhUtils {      static Logger logger = LogManager.getLogger("AhUtils"); -    public static Timer timer = new Timer(); +//    public static Timer timer = new Timer();      public static int totalAuctions = 0;  | 
