diff options
author | DeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com> | 2022-06-05 17:43:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-05 17:43:23 +0200 |
commit | ab7256dff5d6d37488081ba7a01b36d3ee9ef563 (patch) | |
tree | 8207341e6c402848cdbe7b2f2297f5f975e0e083 /src/main/java/cc/polyfrost/oneconfig/internal | |
parent | a903cfc4d3f76cf3db24749b65156d126fa714e7 (diff) | |
download | OneConfig-ab7256dff5d6d37488081ba7a01b36d3ee9ef563.tar.gz OneConfig-ab7256dff5d6d37488081ba7a01b36d3ee9ef563.tar.bz2 OneConfig-ab7256dff5d6d37488081ba7a01b36d3ee9ef563.zip |
refactor (#36)
* refactor
* fix vig compat
* fix nanovg thingy
* e
* finalize
* gui utils package thingy
Diffstat (limited to 'src/main/java/cc/polyfrost/oneconfig/internal')
19 files changed, 910 insertions, 0 deletions
diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/OneConfig.java b/src/main/java/cc/polyfrost/oneconfig/internal/OneConfig.java new file mode 100644 index 0000000..3a00e06 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/OneConfig.java @@ -0,0 +1,85 @@ +package cc.polyfrost.oneconfig.internal; + +import cc.polyfrost.oneconfig.config.core.ConfigCore; +import cc.polyfrost.oneconfig.config.data.Mod; +import cc.polyfrost.oneconfig.config.data.ModType; +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.hud.HudCore; +import cc.polyfrost.oneconfig.internal.config.OneConfigConfig; +import cc.polyfrost.oneconfig.internal.command.OneConfigCommand; +import cc.polyfrost.oneconfig.internal.gui.BlurHandler; +import cc.polyfrost.oneconfig.test.TestCommand; +import cc.polyfrost.oneconfig.test.TestConfig; +import cc.polyfrost.oneconfig.utils.gui.GuiUtils; +import cc.polyfrost.oneconfig.utils.commands.CommandManager; +import cc.polyfrost.oneconfig.utils.hypixel.HypixelUtils; +import net.minecraftforge.fml.common.DummyModContainer; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.ModContainer; +import net.minecraftforge.fml.common.ModMetadata; + +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; + +/** + * The main class of OneConfig. + */ +@net.minecraftforge.fml.common.Mod(modid = "@ID@", name = "@NAME@", version = "@VER@") +public class OneConfig { + public static final File oneConfigDir = new File("./OneConfig"); + public static final List<Mod> loadedMods = new ArrayList<>(); + public static final List<ModMetadata> loadedOtherMods = new ArrayList<>(); + public static OneConfigConfig config; + public static TestConfig testConfig; + private static boolean preLaunched = false; + private static boolean initialized = false; + + /** + * Called before mods are loaded. + * <p><b>SHOULD NOT BE CALLED!</b></p> + */ + public static void preLaunch() { + if (preLaunched) return; + if (!net.minecraft.launchwrapper.Launch.blackboard.containsKey("oneconfig.initialized")) { + throw new RuntimeException("OneConfig has not been initialized! Please add the OneConfig tweaker or call OneConfigInit via an ITweaker or a FMLLoadingPlugin!"); + } + oneConfigDir.mkdirs(); + new File(oneConfigDir, "profiles").mkdirs(); + config = new OneConfigConfig(); + preLaunched = true; + } + + /** + * Called after mods are loaded. + * <p><b>SHOULD NOT BE CALLED!</b></p> + */ + @SuppressWarnings("ResultOfMethodCallIgnored") + public static void init() { + if (initialized) return; + GuiUtils.getDeltaTime(); // called to make sure static initializer is called + BlurHandler.INSTANCE.load(); + testConfig = new TestConfig(); + CommandManager.INSTANCE.registerCommand(OneConfigCommand.class); + CommandManager.INSTANCE.registerCommand(TestCommand.class); + EventManager.INSTANCE.register(new HudCore()); + EventManager.INSTANCE.register(HypixelUtils.INSTANCE); + reloadModsList(); + initialized = true; + } + + public static void reloadModsList() { + loadedMods.addAll(ConfigCore.oneConfigMods); + LinkedHashSet<Mod> modData = new LinkedHashSet<>(ConfigCore.oneConfigMods); + for (ModContainer mod : Loader.instance().getActiveModList()) { + ModMetadata metadata = mod.getMetadata(); + loadedOtherMods.add(metadata); + String imageName = Loader.instance().activeModContainer() == null || Loader.instance().activeModContainer().getMetadata().logoFile.trim().equals("") ? null : "/" + Loader.instance().activeModContainer().getMetadata().logoFile; + Mod newMod = new Mod(metadata.name, ModType.THIRD_PARTY, imageName); + newMod.isShortCut = true; + if (mod instanceof DummyModContainer || newMod.name.equals("OneConfig")) continue; + if (modData.add(newMod)) loadedMods.add(newMod); + } + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/command/OneConfigCommand.java b/src/main/java/cc/polyfrost/oneconfig/internal/command/OneConfigCommand.java new file mode 100644 index 0000000..82d040a --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/command/OneConfigCommand.java @@ -0,0 +1,38 @@ +package cc.polyfrost.oneconfig.internal.command; + +import cc.polyfrost.oneconfig.gui.HudGui; +import cc.polyfrost.oneconfig.gui.OneConfigGui; +import cc.polyfrost.oneconfig.utils.gui.GuiUtils; +import cc.polyfrost.oneconfig.utils.InputUtils; +import cc.polyfrost.oneconfig.utils.commands.annotations.Command; +import cc.polyfrost.oneconfig.utils.commands.annotations.Main; +import cc.polyfrost.oneconfig.utils.commands.annotations.SubCommand; + +/** + * The main OneConfig command. + */ +@Command(value = "oneconfig", aliases = {"ocfg", "oneconfig"}, description = "Access the OneConfig GUI.") +public class OneConfigCommand { + + @Main + private static void main() { + GuiUtils.displayScreen(OneConfigGui.create()); + } + + @SubCommand(value = "hud", description = "Open the OneConfig HUD config.") + private static class HUDSubCommand { + @Main + private static void main() { + GuiUtils.displayScreen(new HudGui()); + } + } + + @SubCommand(value = "destroy", description = "Destroy the cached OneConfig GUI.") + private static class DestroySubCommand { + @Main + private static void main() { + OneConfigGui.instanceToRestore = null; + InputUtils.blockClicks(false); + } + } +}
\ No newline at end of file diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/config/OneConfigConfig.java b/src/main/java/cc/polyfrost/oneconfig/internal/config/OneConfigConfig.java new file mode 100644 index 0000000..8f67ee6 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/config/OneConfigConfig.java @@ -0,0 +1,48 @@ +package cc.polyfrost.oneconfig.internal.config; + +import cc.polyfrost.oneconfig.config.Config; +import cc.polyfrost.oneconfig.config.core.OneColor; +import cc.polyfrost.oneconfig.config.data.Mod; +import cc.polyfrost.oneconfig.utils.JsonUtils; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; + +public class OneConfigConfig extends Config { + public static String currentProfile = "Default Profile"; + public static ArrayList<String> favoriteMods = new ArrayList<>(); + public static ArrayList<OneColor> favoriteColors = new ArrayList<>(); + public static ArrayList<OneColor> recentColors = new ArrayList<>(); + public static boolean allShowShortCut = false; + + public OneConfigConfig() { + super(null, "OneConfig.json"); + } + + @Override + public void init(Mod mod) { + if (new File("OneConfig/" + configFile).exists()) load(); + else save(); + } + + @Override + public void save() { + try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get("OneConfig/" + configFile)), StandardCharsets.UTF_8))) { + writer.write(gson.toJson(this)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void load() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get("OneConfig/" + configFile)), StandardCharsets.UTF_8))) { + deserializePart(JsonUtils.PARSER.parse(reader).getAsJsonObject(), this); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/gui/BlurHandler.java b/src/main/java/cc/polyfrost/oneconfig/internal/gui/BlurHandler.java new file mode 100644 index 0000000..f5c332f --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/gui/BlurHandler.java @@ -0,0 +1,148 @@ +package cc.polyfrost.oneconfig.internal.gui; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.RenderEvent; +import cc.polyfrost.oneconfig.events.event.ScreenOpenEvent; +import cc.polyfrost.oneconfig.events.event.Stage; +import cc.polyfrost.oneconfig.gui.OneConfigGui; +import cc.polyfrost.oneconfig.internal.mixin.ShaderGroupAccessor; +import gg.essential.universal.UMinecraft; +import gg.essential.universal.UScreen; +import me.kbrewster.eventbus.Subscribe; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.shader.Shader; +import net.minecraft.client.shader.ShaderUniform; +import net.minecraft.util.ResourceLocation; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.List; + +/** + * An implementation of the BlurMC mod by tterrag1098. + * <p> + * For the original source see https://github.com/tterrag1098/Blur/blob/1.8.9/src/main/java/com/tterrag/blur/Blur.java + * For the public license, see https://github.com/tterrag1098/Blur/blob/1.8.9/LICENSE + * <p> + * License available under https://github.com/boomboompower/ToggleChat/blob/master/src/main/resources/licenses/BlurMC-License.txt + * + * @author tterrag1098, boomboompower + * <p> + * Taken from ToggleChat + * https://github.com/boomboompower/ToggleChat/blob/master/LICENSE + */ +public class BlurHandler { + public static BlurHandler INSTANCE = new BlurHandler(); + private final ResourceLocation blurShader = new ResourceLocation("shaders/post/fade_in_blur.json"); + private final Logger logger = LogManager.getLogger("OneConfig - Blur"); + private long start; + private float lastProgress = 0; + + /** + * Simply initializes the blur mod so events are properly handled by forge. + */ + public void load() { + EventManager.INSTANCE.register(this); + } + + @Subscribe + private void onGuiChange(ScreenOpenEvent event) { + reloadBlur(event.screen); + } + + @Subscribe + private void onRenderTick(RenderEvent event) { + if (event.stage != Stage.END) { + return; + } + + // Only blur on our own menus + if (UScreen.getCurrentScreen() == null) { + return; + } + + // Only update the shader if one is active + if (!UMinecraft.getMinecraft().entityRenderer.isShaderActive()) { + return; + } + + float progress = getBlurStrengthProgress(); + + // If the new progress value matches the old one this + // will skip the frame update, which (hopefully) resolves the issue + // with the heavy computations after the "animation" is complete. + if (progress == this.lastProgress) { + return; + } + + // Store it for the next iteration! + this.lastProgress = progress; + + // This is hilariously bad, and could cause frame issues on low-end computers. + // Why is this being computed every tick? Surely there is a better way? + // This needs to be optimized. + try { + final List<Shader> listShaders = ((ShaderGroupAccessor) Minecraft.getMinecraft().entityRenderer.getShaderGroup()).getListShaders(); + + // Should not happen. Something bad happened. + if (listShaders == null) { + return; + } + + // Iterate through the list of shaders. + for (Shader shader : listShaders) { + ShaderUniform su = shader.getShaderManager().getShaderUniform("Progress"); + + if (su == null) { + continue; + } + + // All this for this. + su.set(progress); + } + } catch (IllegalArgumentException ex) { + this.logger.error("An error.png occurred while updating OneConfig's blur. Please report this!", ex); + } + } + + /** + * Activates/deactivates the blur in the current world if + * one of many conditions are met, such as no current other shader + * is being used, we actually have the blur setting enabled + */ + private void reloadBlur(GuiScreen gui) { + // Don't do anything if no world is loaded + if (UMinecraft.getWorld() == null) { + return; + } + + // If a shader is not already active and the UI is + // a one of ours, we should load our own blur! + if (!UMinecraft.getMinecraft().entityRenderer.isShaderActive() && gui instanceof OneConfigGui) { + UMinecraft.getMinecraft().entityRenderer.loadShader(this.blurShader); + + this.start = System.currentTimeMillis(); + + // If a shader is active and the incoming UI is null or we have blur disabled, stop using the shader. + } else if (UMinecraft.getMinecraft().entityRenderer.isShaderActive() && (gui == null)) { + String name = UMinecraft.getMinecraft().entityRenderer.getShaderGroup().getShaderGroupName(); + + // Only stop our specific blur ;) + if (!name.endsWith("fade_in_blur.json")) { + return; + } + + UMinecraft.getMinecraft().entityRenderer.stopUseShader(); + } + } + + /** + * Returns the strength of the blur as determined by the duration the effect of the blur. + * <p> + * The strength of the blur does not go below 5.0F. + */ + private float getBlurStrengthProgress() { + return Math.min((System.currentTimeMillis() - this.start) / 50F, 5.0F); + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/init/OneConfigInit.java b/src/main/java/cc/polyfrost/oneconfig/internal/init/OneConfigInit.java new file mode 100644 index 0000000..438c60e --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/init/OneConfigInit.java @@ -0,0 +1,24 @@ +package cc.polyfrost.oneconfig.internal.init; + +import net.minecraft.launchwrapper.Launch; +import org.spongepowered.asm.launch.MixinBootstrap; +import org.spongepowered.asm.mixin.Mixins; + +/** + * Initializes the OneConfig mod. + * <p><b>MUST BE CALLED VIA AN ITWEAKER / FMLLOADINGPLUGIN FOR 1.12 AND BELOW, OR A PRELAUNCH TWEAKER FOR 1.14+ FABRIC.</b></p> + */ +@SuppressWarnings("unused") +public class OneConfigInit { + + /** + * Initializes the OneConfig mod. + * + * @param args The arguments passed to the mod. + */ + public static void initialize(String[] args) { + Launch.blackboard.put("oneconfig.initialized", true); + MixinBootstrap.init(); + Mixins.addConfiguration("mixins.oneconfig.json"); + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/mixin/FontRendererMixin.java b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/FontRendererMixin.java new file mode 100644 index 0000000..227b99e --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/FontRendererMixin.java @@ -0,0 +1,15 @@ +package cc.polyfrost.oneconfig.internal.mixin; + + +import net.minecraft.client.gui.FontRenderer; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(FontRenderer.class) +public class FontRendererMixin { + + //@Inject(method = "renderDefaultChar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/FontRenderer;bindTexture(Lnet/minecraft/util/ResourceLocation;)V", shift = At.Shift.AFTER)) + //public void whoAsked(int ch, boolean italic, CallbackInfoReturnable<Float> cir) { + // GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + // GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + //} +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java new file mode 100644 index 0000000..f08d37e --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java @@ -0,0 +1,17 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.HudRenderEvent; +import net.minecraftforge.client.GuiIngameForge; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = GuiIngameForge.class, remap = false) +public class GuiIngameForgeMixin { + @Inject(method = "renderGameOverlay", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/client/GuiIngameForge;post(Lnet/minecraftforge/client/event/RenderGameOverlayEvent$ElementType;)V", shift = At.Shift.AFTER, remap = false), remap = true) + private void onRenderGameOverlay(float partialTicks, CallbackInfo ci) { + EventManager.INSTANCE.post(new HudRenderEvent(partialTicks)); + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java new file mode 100644 index 0000000..f0d201c --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java @@ -0,0 +1,76 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.internal.OneConfig; +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.*; +import net.minecraft.client.Minecraft; +import net.minecraft.util.Timer; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.fml.common.eventhandler.Event; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + @Shadow + private Timer timer; + + @Inject(method = "startGame", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/client/FMLClientHandler;beginMinecraftLoading(Lnet/minecraft/client/Minecraft;Ljava/util/List;Lnet/minecraft/client/resources/IReloadableResourceManager;)V", remap = false), remap = true) + private void onPreLaunch(CallbackInfo ci) { + OneConfig.preLaunch(); + } + + @Inject(method = "startGame", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/client/FMLClientHandler;onInitializationComplete()V", shift = At.Shift.AFTER, remap = false), remap = true) + private void onInit(CallbackInfo ci) { + OneConfig.init(); + } + + @Inject(method = "runGameLoop", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/FMLCommonHandler;onRenderTickStart(F)V", shift = At.Shift.AFTER, remap = false), remap = true) + private void onRenderTickStart(CallbackInfo ci) { + EventManager.INSTANCE.post(new RenderEvent(Stage.START, timer.renderPartialTicks)); + } + + @Inject(method = "runGameLoop", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/FMLCommonHandler;onRenderTickEnd(F)V", shift = At.Shift.AFTER, remap = false), remap = true) + private void onRenderTickEnd(CallbackInfo ci) { + EventManager.INSTANCE.post(new RenderEvent(Stage.END, timer.renderPartialTicks)); + } + + @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/FMLCommonHandler;onPreClientTick()V", shift = At.Shift.AFTER, remap = false), remap = true) + private void onClientTickStart(CallbackInfo ci) { + EventManager.INSTANCE.post(new TickEvent(Stage.START)); + } + + @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/FMLCommonHandler;onPostClientTick()V", shift = At.Shift.AFTER, remap = false), remap = true) + private void onClientTickEnd(CallbackInfo ci) { + EventManager.INSTANCE.post(new TickEvent(Stage.END)); + } + + @ModifyArg(method = "displayGuiScreen", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/eventhandler/EventBus;post(Lnet/minecraftforge/fml/common/eventhandler/Event;)Z", remap = false), remap = true) + private Event onGuiOpenEvent(Event a) { + if (a instanceof GuiOpenEvent) { + GuiOpenEvent forgeEvent = (GuiOpenEvent) a; + ScreenOpenEvent event = new ScreenOpenEvent(forgeEvent.gui); + EventManager.INSTANCE.post(event); + if (event.isCancelled) { + forgeEvent.setCanceled(true); + } + return forgeEvent; + } + return a; + } + + @Inject(method = "runGameLoop", at = @At(value = "FIELD", target = "Lnet/minecraft/util/Timer;renderPartialTicks:F", opcode = Opcodes.PUTFIELD, shift = At.Shift.AFTER)) + private void onNonDeltaTickTimerUpdate(CallbackInfo ci) { + EventManager.INSTANCE.post(new TimerUpdateEvent(timer, false)); + } + + @Inject(method = "runGameLoop", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Timer;updateTimer()V", shift = At.Shift.AFTER, ordinal = 1)) + private void onDeltaTickTimerUpdate(CallbackInfo ci) { + EventManager.INSTANCE.post(new TimerUpdateEvent(timer, true)); + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java new file mode 100644 index 0000000..877d540 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java @@ -0,0 +1,36 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.ChatReceiveEvent; +import cc.polyfrost.oneconfig.events.event.SendPacketEvent; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S02PacketChat; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = NetHandlerPlayClient.class, priority = Integer.MAX_VALUE) +public class NetHandlerPlayClientMixin { + + @Inject(method = "addToSendQueue", at = @At("HEAD"), cancellable = true) + private void onSendPacket(Packet<?> p_147297_1_, CallbackInfo ci) { + SendPacketEvent event = new SendPacketEvent(p_147297_1_); + EventManager.INSTANCE.post(event); + if (event.isCancelled) { + ci.cancel(); + } + } + + @Inject(method = "handleChat", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/event/ForgeEventFactory;onClientChat(BLnet/minecraft/util/IChatComponent;)Lnet/minecraft/util/IChatComponent;", remap = false), cancellable = true, remap = true) + private void onClientChat(S02PacketChat packetIn, CallbackInfo ci) { + if (packetIn.getType() == 0) { + ChatReceiveEvent event = new ChatReceiveEvent(packetIn.getChatComponent()); + EventManager.INSTANCE.post(event); + if (event.isCancelled) { + ci.cancel(); + } + } + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java new file mode 100644 index 0000000..51988f2 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java @@ -0,0 +1,23 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.ReceivePacketEvent; +import io.netty.channel.ChannelHandlerContext; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = NetworkManager.class, priority = Integer.MAX_VALUE) +public class NetworkManagerMixin { + @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/Packet;)V", at = @At("HEAD"), cancellable = true) + private void onReceivePacket(ChannelHandlerContext p_channelRead0_1_, Packet<?> p_channelRead0_2_, CallbackInfo ci) { + ReceivePacketEvent event = new ReceivePacketEvent(p_channelRead0_2_); + EventManager.INSTANCE.post(event); + if (event.isCancelled) { + ci.cancel(); + } + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/mixin/ShaderGroupAccessor.java b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/ShaderGroupAccessor.java new file mode 100644 index 0000000..8014670 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/ShaderGroupAccessor.java @@ -0,0 +1,14 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import net.minecraft.client.shader.Shader; +import net.minecraft.client.shader.ShaderGroup; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(ShaderGroup.class) +public interface ShaderGroupAccessor { + @Accessor("listShaders") + List<Shader> getListShaders(); +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java new file mode 100644 index 0000000..d1fce6a --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java @@ -0,0 +1,21 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.WorldLoadEvent; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.profiler.Profiler; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.WorldSettings; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(WorldClient.class) +public class WorldClientMixin { + @Inject(method = "<init>", at = @At("RETURN")) + private void onWorldLoad(NetHandlerPlayClient p_i45063_1_, WorldSettings p_i45063_2_, int p_i45063_3_, EnumDifficulty p_i45063_4_, Profiler p_i45063_5_, CallbackInfo ci) { + EventManager.INSTANCE.post(new WorldLoadEvent()); + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/plugin/LoadingPlugin.java b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/LoadingPlugin.java new file mode 100644 index 0000000..b819f24 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/LoadingPlugin.java @@ -0,0 +1,53 @@ +package cc.polyfrost.oneconfig.internal.plugin; + +import cc.polyfrost.oneconfig.internal.init.OneConfigInit; +import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; + +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Set; + +public class LoadingPlugin implements IFMLLoadingPlugin { + + /** + * Taken from LWJGLTwoPointFive under The Unlicense + * <a href="https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/">https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/</a> + */ + public LoadingPlugin() { + try { + Field f_exceptions = LaunchClassLoader.class.getDeclaredField("classLoaderExceptions"); + f_exceptions.setAccessible(true); + Set<String> exceptions = (Set<String>) f_exceptions.get(Launch.classLoader); + exceptions.remove("org.lwjgl."); + OneConfigInit.initialize(new String[]{}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String[] getASMTransformerClass() { + return new String[]{"cc.polyfrost.oneconfig.internal.plugin.asm.ClassTransformer"}; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map<String, Object> data) { + } + + @Override + public String getAccessTransformerClass() { + return null; + } +}
\ No newline at end of file diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/plugin/Lwjgl2FunctionProvider.java b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/Lwjgl2FunctionProvider.java new file mode 100644 index 0000000..105afa2 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/Lwjgl2FunctionProvider.java @@ -0,0 +1,39 @@ +package cc.polyfrost.oneconfig.internal.plugin; + +import org.lwjgl.opengl.GLContext; +import org.lwjgl.system.FunctionProvider; + +import java.lang.reflect.Method; +import java.nio.ByteBuffer; + +/** + * Taken from LWJGLTwoPointFive under The Unlicense + * <a href="https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/">https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/</a> + */ +public class Lwjgl2FunctionProvider implements FunctionProvider { + + private final Method m_getFunctionAddress; + + public Lwjgl2FunctionProvider() { + try { + m_getFunctionAddress = GLContext.class.getDeclaredMethod("getFunctionAddress", String.class); + m_getFunctionAddress.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public long getFunctionAddress(CharSequence functionName) { + try { + return (long) m_getFunctionAddress.invoke(null, functionName.toString()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public long getFunctionAddress(ByteBuffer byteBuffer) { + throw new UnsupportedOperationException(); + } +}
\ No newline at end of file diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/plugin/OneConfigMixinPlugin.java b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/OneConfigMixinPlugin.java new file mode 100644 index 0000000..c55febc --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/OneConfigMixinPlugin.java @@ -0,0 +1,52 @@ +package cc.polyfrost.oneconfig.internal.plugin; + +import org.spongepowered.asm.lib.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +public class OneConfigMixinPlugin implements IMixinConfigPlugin { + public static boolean isVigilance = false; + + @Override + public void onLoad(String mixinPackage) { + try { + Class.forName("gg.essential.vigilance.Vigilant"); + isVigilance = true; + } catch (Exception e) { + isVigilance = false; + } + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + return !targetClassName.contains("vigilance") || isVigilance; + } + + @Override + public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { + + } + + @Override + public List<String> getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java new file mode 100644 index 0000000..1a2766f --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java @@ -0,0 +1,64 @@ +package cc.polyfrost.oneconfig.internal.plugin.asm; + +import cc.polyfrost.oneconfig.internal.plugin.asm.tweakers.NanoVGGLConfigTransformer; +import cc.polyfrost.oneconfig.internal.plugin.asm.tweakers.VigilantTransformer; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import net.minecraft.launchwrapper.IClassTransformer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.tree.ClassNode; + +import java.util.Collection; + +/** + * Taken from LWJGLTwoPointFive under The Unlicense + * <a href="https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/">https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/</a> + * <p>also half taken from asmworkspace by asbyth ty</p> + */ +@SuppressWarnings("unused") +public class ClassTransformer implements IClassTransformer { + private static final Logger logger = LogManager.getLogger("OneConfig ASM"); + private final Multimap<String, ITransformer> transformerMap = ArrayListMultimap.create(); + + public ClassTransformer() { + registerTransformer(new NanoVGGLConfigTransformer()); + registerTransformer(new VigilantTransformer()); + } + + private void registerTransformer(ITransformer transformer) { + // loop through names of classes + for (String cls : transformer.getClassName()) { + // put the classes into the transformer map + transformerMap.put(cls, transformer); + } + } + + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if (basicClass == null) return null; + + Collection<ITransformer> transformers = transformerMap.get(transformedName); + if (transformers.isEmpty()) return basicClass; + + + ClassReader reader = new ClassReader(basicClass); + ClassNode node = new ClassNode(); + reader.accept(node, ClassReader.EXPAND_FRAMES); + + for (ITransformer transformer : transformers) { + transformer.transform(transformedName, node); + } + + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + try { + node.accept(cw); + } catch (Throwable t) { + logger.error("Exception when transforming " + transformedName + " : " + t.getClass().getSimpleName()); + t.printStackTrace(); + } + return cw.toByteArray(); + } +}
\ No newline at end of file diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java new file mode 100644 index 0000000..482a310 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java @@ -0,0 +1,9 @@ +package cc.polyfrost.oneconfig.internal.plugin.asm; + +import org.objectweb.asm.tree.ClassNode; + +public interface ITransformer { + String[] getClassName(); + + void transform(String transformedName, ClassNode node); +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java new file mode 100644 index 0000000..4d7a5cc --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java @@ -0,0 +1,43 @@ +package cc.polyfrost.oneconfig.internal.plugin.asm.tweakers; + +import cc.polyfrost.oneconfig.internal.plugin.asm.ITransformer; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; + +public class NanoVGGLConfigTransformer implements ITransformer { + @Override + public String[] getClassName() { + return new String[]{"org.lwjgl.nanovg.NanoVGGLConfig"}; + } + + @Override + public void transform(String transformedName, ClassNode node) { + for (MethodNode method : node.methods) { + if (method.name.equals("configGL")) { + InsnList list = new InsnList(); + + list.add(new VarInsnNode(Opcodes.LLOAD, 0)); + list.add(new TypeInsnNode(Opcodes.NEW, "cc/polyfrost/oneconfig/internal/plugin/Lwjgl2FunctionProvider")); + list.add(new InsnNode(Opcodes.DUP)); + list.add(new MethodInsnNode( + Opcodes.INVOKESPECIAL, + "cc/polyfrost/oneconfig/internal/plugin/Lwjgl2FunctionProvider", + "<init>", + "()V", + false + )); + list.add(new MethodInsnNode( + Opcodes.INVOKESTATIC, + "org/lwjgl/nanovg/NanoVGGLConfig", + "config", + "(JLorg/lwjgl/system/FunctionProvider;)V", + false + )); + list.add(new InsnNode(Opcodes.RETURN)); + + method.instructions.clear(); + method.instructions.insert(list); + } + } + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java new file mode 100644 index 0000000..f241c74 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java @@ -0,0 +1,105 @@ +package cc.polyfrost.oneconfig.internal.plugin.asm.tweakers; + +import cc.polyfrost.oneconfig.config.compatibility.vigilance.VigilanceConfig; +import cc.polyfrost.oneconfig.config.core.ConfigCore; +import cc.polyfrost.oneconfig.config.data.Mod; +import cc.polyfrost.oneconfig.config.data.ModType; +import cc.polyfrost.oneconfig.internal.plugin.asm.ITransformer; +import gg.essential.vigilance.Vigilant; +import gg.essential.vigilance.data.PropertyCollector; +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.Loader; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.*; + +import java.io.File; + +public class VigilantTransformer implements ITransformer { + @SuppressWarnings("unused") + public static VigilanceConfig returnNewConfig(Vigilant vigilant, File file) { + if (vigilant != null && Minecraft.getMinecraft().isCallingFromMinecraftThread()) { + String name = !vigilant.getGuiTitle().equals("Settings") ? vigilant.getGuiTitle() : Loader.instance().activeModContainer() == null ? "Unknown" : Loader.instance().activeModContainer().getName(); + if (name.equals("OneConfig")) name = "Essential"; + String finalName = name; + // duplicate fix + if (ConfigCore.oneConfigMods.stream().anyMatch(mod -> mod.name.equals(finalName))) return null; + return new VigilanceConfig(new Mod(name, ModType.THIRD_PARTY), file.getAbsolutePath(), vigilant); + } else { + return null; + } + } + + @Override + public String[] getClassName() { + return new String[]{"gg.essential.vigilance.Vigilant"}; + } + + @Override + public void transform(String transformedName, ClassNode node) { + node.fields.add(new FieldNode(Opcodes.ACC_PUBLIC, "oneconfig$config", Type.getDescriptor(VigilanceConfig.class), null, null)); + node.fields.add(new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "oneconfig$file", Type.getDescriptor(File.class), null, null)); + + node.interfaces.add("cc/polyfrost/oneconfig/config/compatibility/vigilance/VigilantAccessor"); + MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC, "getPropertyCollector", "()Lgg/essential/vigilance/data/PropertyCollector;", null, null); + LabelNode labelNode = new LabelNode(); + methodNode.instructions.add(labelNode); + methodNode.instructions.add(new LineNumberNode(421421, labelNode)); + methodNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); + methodNode.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "gg/essential/vigilance/Vigilant", "propertyCollector", Type.getDescriptor(PropertyCollector.class))); + methodNode.instructions.add(new InsnNode(Opcodes.ARETURN)); + node.methods.add(methodNode); + + MethodNode methodNode2 = new MethodNode(Opcodes.ACC_PUBLIC, "handleOneConfigDependency", "(Lgg/essential/vigilance/data/PropertyData;Lgg/essential/vigilance/data/PropertyData;)V", null, null); + LabelNode labelNode2 = new LabelNode(); + LabelNode labelNode3 = new LabelNode(); + LabelNode labelNode4 = new LabelNode(); + methodNode2.instructions.add(labelNode2); + methodNode2.instructions.add(new LineNumberNode(15636436, labelNode2)); + methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); + methodNode2.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$config", Type.getDescriptor(VigilanceConfig.class))); + + methodNode2.instructions.add(new JumpInsnNode(Opcodes.IFNULL, labelNode4)); + + methodNode2.instructions.add(labelNode3); + methodNode2.instructions.add(new LineNumberNode(15636437, labelNode3)); + methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); + methodNode2.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$config", Type.getDescriptor(VigilanceConfig.class))); + methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); + methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); + methodNode2.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Type.getInternalName(VigilanceConfig.class), "addDependency", "(Lgg/essential/vigilance/data/PropertyData;Lgg/essential/vigilance/data/PropertyData;)V", false)); + + methodNode2.instructions.add(labelNode4); + methodNode2.instructions.add(new LineNumberNode(15636438, labelNode4)); + methodNode2.instructions.add(new InsnNode(Opcodes.RETURN)); + node.methods.add(methodNode2); + + for (MethodNode method : node.methods) { + if (method.name.equals("initialize")) { + InsnList list = new InsnList(); + list.add(new VarInsnNode(Opcodes.ALOAD, 0)); + list.add(new VarInsnNode(Opcodes.ALOAD, 0)); + list.add(new VarInsnNode(Opcodes.ALOAD, 0)); + list.add(new FieldInsnNode(Opcodes.GETFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$file", Type.getDescriptor(File.class))); + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(getClass()), "returnNewConfig", "(Lgg/essential/vigilance/Vigilant;Ljava/io/File;)Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;", false)); + list.add(new FieldInsnNode(Opcodes.PUTFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$config", Type.getDescriptor(VigilanceConfig.class))); + method.instructions.insertBefore(method.instructions.getLast().getPrevious(), list); + } else if (method.name.equals("addDependency") && method.desc.equals("(Lgg/essential/vigilance/data/PropertyData;Lgg/essential/vigilance/data/PropertyData;)V")) { + InsnList list = new InsnList(); + + list.add(new VarInsnNode(Opcodes.ALOAD, 0)); + list.add(new VarInsnNode(Opcodes.ALOAD, 1)); + list.add(new VarInsnNode(Opcodes.ALOAD, 2)); + list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "gg/essential/vigilance/Vigilant", "handleOneConfigDependency", "(Lgg/essential/vigilance/data/PropertyData;Lgg/essential/vigilance/data/PropertyData;)V", false)); + + method.instructions.insertBefore(method.instructions.getLast().getPrevious(), list); + } else if (method.name.equals("<init>") && method.desc.equals("(Ljava/io/File;Ljava/lang/String;Lgg/essential/vigilance/data/PropertyCollector;Lgg/essential/vigilance/data/SortingBehavior;)V")) { + InsnList list = new InsnList(); + list.add(new VarInsnNode(Opcodes.ALOAD, 0)); + list.add(new VarInsnNode(Opcodes.ALOAD, 1)); + list.add(new FieldInsnNode(Opcodes.PUTFIELD, "gg/essential/vigilance/Vigilant", "oneconfig$file", Type.getDescriptor(File.class))); + method.instructions.insertBefore(method.instructions.getLast().getPrevious(), list); + } + } + } +} |