From d4bb5a94308d4379ef3d6cc7b9221ea0d98ff051 Mon Sep 17 00:00:00 2001 From: Wyvest <45589059+Wyvest@users.noreply.github.com> Date: Sat, 2 Jul 2022 06:12:23 +0700 Subject: Separate Minecraft dependant and non-dependant code --- versions/build.gradle.kts | 306 +++++++++++++++++++ versions/root.gradle.kts | 9 + .../oneconfig/events/event/ChatReceiveEvent.java | 22 ++ .../oneconfig/events/event/ReceivePacketEvent.java | 11 + .../oneconfig/events/event/ScreenOpenEvent.java | 17 ++ .../oneconfig/events/event/SendPacketEvent.java | 11 + .../oneconfig/events/event/TimerUpdateEvent.java | 24 ++ .../cc/polyfrost/oneconfig/internal/OneConfig.java | 93 ++++++ .../internal/gui/impl/BlurHandlerImpl.java | 132 +++++++++ .../internal/mixin/GuiIngameForgeMixin.java | 19 ++ .../oneconfig/internal/mixin/MinecraftMixin.java | 100 +++++++ .../internal/mixin/NetHandlerPlayClientMixin.java | 38 +++ .../internal/mixin/NetworkManagerMixin.java | 25 ++ .../internal/mixin/OptifineConfigMixin.java | 23 ++ .../internal/mixin/ShaderGroupAccessor.java | 16 + .../oneconfig/internal/mixin/VigilantMixin.java | 10 + .../oneconfig/internal/mixin/WorldClientMixin.java | 23 ++ .../internal/plugin/asm/ClassTransformer.java | 102 +++++++ .../internal/plugin/asm/ITransformer.java | 24 ++ .../internal/plugin/asm/OneConfigTweaker.java | 117 ++++++++ .../asm/tweakers/NanoVGGLConfigTransformer.java | 47 +++ .../plugin/asm/tweakers/VigilantTransformer.java | 89 ++++++ .../plugin/hooks/Lwjgl2FunctionProvider.java | 47 +++ .../internal/plugin/hooks/OptifineConfigHook.java | 22 ++ .../internal/plugin/hooks/VigilantHook.java | 26 ++ .../oneconfig/platform/impl/GLPlatformImpl.java | 67 +++++ .../oneconfig/platform/impl/GuiPlatformImpl.java | 31 ++ .../oneconfig/platform/impl/I18nPlatformImpl.java | 13 + .../platform/impl/LoaderPlatformImpl.java | 26 ++ .../oneconfig/platform/impl/MousePlatformImpl.java | 53 ++++ .../oneconfig/platform/impl/PlatformImpl.java | 12 + .../platform/impl/ServerPlatformImpl.java | 22 ++ .../utils/commands/PlatformCommandManagerImpl.java | 330 +++++++++++++++++++++ .../cc/polyfrost/oneconfig/utils/gui/GuiUtils.java | 100 +++++++ .../cc/polyfrost/oneconfig/utils/dsl/DSLs.kt | 9 + .../polyfrost/oneconfig/utils/dsl/GuiUtilsDSL.kt | 11 + ...cc.polyfrost.oneconfig.internal.gui.BlurHandler | 1 + .../cc.polyfrost.oneconfig.platform.GLPlatform | 1 + .../cc.polyfrost.oneconfig.platform.GuiPlatform | 1 + .../cc.polyfrost.oneconfig.platform.I18nPlatform | 1 + .../cc.polyfrost.oneconfig.platform.LoaderPlatform | 1 + .../cc.polyfrost.oneconfig.platform.MousePlatform | 1 + .../cc.polyfrost.oneconfig.platform.Platform | 1 + .../cc.polyfrost.oneconfig.platform.ServerPlatform | 1 + ...oneconfig.utils.commands.PlatformCommandManager | 1 + versions/src/main/resources/mixins.oneconfig.json | 21 ++ 46 files changed, 2057 insertions(+) create mode 100644 versions/build.gradle.kts create mode 100644 versions/root.gradle.kts create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/events/event/ChatReceiveEvent.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/events/event/ReceivePacketEvent.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/events/event/ScreenOpenEvent.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/events/event/SendPacketEvent.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/events/event/TimerUpdateEvent.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/OneConfig.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/gui/impl/BlurHandlerImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/OptifineConfigMixin.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/ShaderGroupAccessor.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/VigilantMixin.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/OneConfigTweaker.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/Lwjgl2FunctionProvider.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/OptifineConfigHook.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/hooks/VigilantHook.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/platform/impl/GLPlatformImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/platform/impl/GuiPlatformImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/platform/impl/I18nPlatformImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/platform/impl/LoaderPlatformImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/platform/impl/MousePlatformImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/platform/impl/PlatformImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/platform/impl/ServerPlatformImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/utils/commands/PlatformCommandManagerImpl.java create mode 100644 versions/src/main/java/cc/polyfrost/oneconfig/utils/gui/GuiUtils.java create mode 100644 versions/src/main/kotlin/cc/polyfrost/oneconfig/utils/dsl/DSLs.kt create mode 100644 versions/src/main/kotlin/cc/polyfrost/oneconfig/utils/dsl/GuiUtilsDSL.kt create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.internal.gui.BlurHandler create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.platform.GLPlatform create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.platform.GuiPlatform create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.platform.I18nPlatform create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.platform.LoaderPlatform create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.platform.MousePlatform create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.platform.Platform create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.platform.ServerPlatform create mode 100644 versions/src/main/resources/META-INF/services/cc.polyfrost.oneconfig.utils.commands.PlatformCommandManager create mode 100644 versions/src/main/resources/mixins.oneconfig.json (limited to 'versions') diff --git a/versions/build.gradle.kts b/versions/build.gradle.kts new file mode 100644 index 0000000..939e61b --- /dev/null +++ b/versions/build.gradle.kts @@ -0,0 +1,306 @@ +import gg.essential.gradle.util.RelocationTransform.Companion.registerRelocationAttribute +import gg.essential.gradle.util.noServerRunConfigs +import gg.essential.gradle.util.prebundle +import net.fabricmc.loom.task.RemapSourcesJarTask + + +plugins { + kotlin("jvm") + id("gg.essential.multi-version") + id("gg.essential.defaults.repo") + id("gg.essential.defaults.java") + id("gg.essential.defaults.loom") + id("net.kyori.blossom") version "1.3.0" + id("org.jetbrains.dokka") version "1.6.21" + id("maven-publish") + id("signing") + java +} + +kotlin.jvmToolchain { + (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(8)) +} + +java { + withSourcesJar() +} + +val mod_name: String by project +val mod_version: String by project +val mod_id: String by project + +preprocess { + vars.put("MODERN", if (project.platform.mcMinor >= 16) 1 else 0) +} + +blossom { + replaceToken("@VER@", mod_version) + replaceToken("@NAME@", mod_name) + replaceToken("@ID@", mod_id) +} + +version = mod_version +group = "cc.polyfrost" +base { + archivesName.set("$mod_id-$platform") +} +loom { + noServerRunConfigs() + if (project.platform.isLegacyForge) { + launchConfigs.named("client") { + arg("--tweakClass", "cc.polyfrost.oneconfig.internal.plugin.asm.OneConfigTweaker") + property("mixin.debug.export", "true") + property("debugBytecode", "true") + } + } + if (project.platform.isForge) { + forge { + mixinConfig("mixins.${mod_id}.json") + } + } + mixin.defaultRefmapName.set("mixins.${mod_id}.refmap.json") +} + +repositories { + maven("https://repo.polyfrost.cc/releases") +} + +val relocated = registerRelocationAttribute("relocate") { + relocate("gg.essential", "cc.polyfrost.oneconfig.libs") + relocate("me.kbrewster", "cc.polyfrost.oneconfig.libs") + relocate("com.github.benmanes", "cc.polyfrost.oneconfig.libs") + relocate("com.google", "cc.polyfrost.oneconfig.libs") + relocate("org.checkerframework", "cc.polyfrost.oneconfig.libs") + remapStringsIn("com.github.benmanes.caffeine.cache.LocalCacheFactory") + remapStringsIn("com.github.benmanes.caffeine.cache.NodeFactory") +} + +val shadeRelocated: Configuration by configurations.creating { + attributes { attribute(relocated, true) } +} + +val shade: Configuration by configurations.creating { + configurations.api.get().extendsFrom(this) +} + +val shadeNoPom: Configuration by configurations.creating + +sourceSets { + main { + output.setResourcesDir(java.classesDirectory) + } +} + +dependencies { + compileOnly("gg.essential:vigilance-$platform:222") { + isTransitive = false + } + + shadeRelocated("gg.essential:universalcraft-$platform:211") { + isTransitive = false + } + + shadeRelocated("com.github.KevinPriv:keventbus:c52e0a2ea0") { + isTransitive = false + } + + @Suppress("GradlePackageUpdate") + shadeRelocated("com.github.ben-manes.caffeine:caffeine:2.9.3") + + // for other mods and universalcraft + val kotlinVersion: String by project + val coroutinesVersion: String by project + val serializationVersion: String by project + val atomicfuVersion: String by project + shade("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") + shade("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") + shade("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion") + shade("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion") + + shade("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") + shade("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:$coroutinesVersion") + shade("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$coroutinesVersion") + shade("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:$serializationVersion") + shade("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:$serializationVersion") + shade("org.jetbrains.kotlinx:kotlinx-serialization-cbor-jvm:$serializationVersion") + shade("org.jetbrains.kotlinx:atomicfu-jvm:$atomicfuVersion") + + shade("org.spongepowered:mixin:0.7.11-SNAPSHOT") { + isTransitive = false + } + shadeNoPom(project(":")) { + isTransitive = false + } + shade("cc.polyfrost:lwjgl:1.0.0-alpha1") + shadeNoPom(prebundle(shadeRelocated)) + + dokkaHtmlPlugin("org.jetbrains.dokka:kotlin-as-java-plugin:1.6.21") + + configurations.named(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME) { extendsFrom(shadeNoPom) } + configurations.named(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) { extendsFrom(shadeNoPom) } +} + +tasks { + processResources { + inputs.property("id", mod_id) + inputs.property("name", mod_name) + val java = if (project.platform.mcMinor >= 18) { + 17 + } else { + if (project.platform.mcMinor == 17) 16 else 8 + } + val compatLevel = "JAVA_${java}" + inputs.property("java", java) + inputs.property("java_level", compatLevel) + inputs.property("version", mod_version) + inputs.property("mcVersionStr", project.platform.mcVersionStr) + filesMatching(listOf("mcmod.info", "mixins.${mod_id}.json", "mods.toml")) { + expand( + mapOf( + "id" to mod_id, + "name" to mod_name, + "java" to java, + "java_level" to compatLevel, + "version" to mod_version, + "mcVersionStr" to project.platform.mcVersionStr + ) + ) + } + filesMatching("fabric.mod.json") { + expand( + mapOf( + "id" to mod_id, + "name" to mod_name, + "java" to java, + "java_level" to compatLevel, + "version" to mod_version, + "mcVersionStr" to project.platform.mcVersionStr.substringBeforeLast(".") + ".x" + ) + ) + } + } + + withType(Jar::class.java) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + if (project.platform.isFabric) { + exclude("mcmod.info", "mods.toml") + } else { + exclude("fabric.mod.json") + if (project.platform.isLegacyForge) { + exclude("mods.toml") + exclude("META-INF/versions/**") + exclude("**/module-info.class") + exclude("**/package-info.class") + } else { + exclude("mcmod.info") + } + } + if (!name.contains("sourcesjar", ignoreCase = true) || !name.contains("dokka", ignoreCase = true)) { + exclude("**/**_Test.**") + exclude("**/**_Test$**.**") + } + } + + remapJar { + archiveClassifier.set("full") + } + + fun Jar.excludeInternal() { + exclude("**/internal/**") + } + jar { + dependsOn(shadeNoPom, shade) + from({ ArrayList().also { it.addAll(shadeNoPom); it.addAll(shade) }.map { if (it.isDirectory) it else zipTree(it) } }) + manifest { + attributes( + mapOf( + "ModSide" to "CLIENT", + "ForceLoadAsMod" to true, + "TweakOrder" to "0", + "MixinConfigs" to "mixins.oneconfig.json", + "TweakClass" to "cc.polyfrost.oneconfig.internal.plugin.asm.OneConfigTweaker" + ) + ) + } + excludeInternal() + archiveClassifier.set("") + } + dokkaHtml.configure { + outputDirectory.set(buildDir.resolve("dokka")) + moduleName.set("OneConfig $platform") + moduleVersion.set(mod_version) + dokkaSourceSets { + configureEach { + jdkVersion.set(8) + //reportUndocumented.set(true) + } + } + doLast { + val outputFile = outputDirectory.get().resolve("images/logo-icon.svg") + if (outputFile.exists()) { + outputFile.delete() + } + val inputFile = project.rootDir.resolve("src/main/resources/assets/oneconfig/icons/OneConfig.svg") + inputFile.copyTo(outputFile) + } + } + val dokkaJar = create("dokkaJar", Jar::class.java) { + archiveClassifier.set("dokka") + group = "build" + dependsOn(dokkaHtml) + from(layout.buildDirectory.dir("dokka")) + } + named("sourcesJar") { + from(project(":").sourceSets.main.map { it.allSource }) + dependsOn(dokkaJar) + excludeInternal() + archiveClassifier.set("sources") + doFirst { + archiveClassifier.set("sources") + } + } + withType { + enabled = false + } +} + +publishing { + publications { + register("oneconfig-$platform") { + groupId = "cc.polyfrost" + artifactId = base.archivesName.get() + + artifact(tasks["jar"]) + artifact(tasks["remapJar"]) + artifact(tasks["sourcesJar"]) + artifact(tasks["dokkaJar"]) + } + } + + repositories { + maven { + name = "releases" + url = uri("https://repo.polyfrost.cc/releases") + credentials(PasswordCredentials::class) + authentication { + create("basic") + } + } + maven { + name = "snapshots" + url = uri("https://repo.polyfrost.cc/snapshots") + credentials(PasswordCredentials::class) + authentication { + create("basic") + } + } + maven { + name = "private" + url = uri("https://repo.polyfrost.cc/private") + credentials(PasswordCredentials::class) + authentication { + create("basic") + } + } + } +} \ No newline at end of file diff --git a/versions/root.gradle.kts b/versions/root.gradle.kts new file mode 100644 index 0000000..f23a159 --- /dev/null +++ b/versions/root.gradle.kts @@ -0,0 +1,9 @@ +plugins { + kotlin("jvm") version "1.6.21" apply false + id("gg.essential.multi-version.root") + id("io.github.juuxel.loom-quiltflower-mini") version "171a6e2e49" apply false +} + +preprocess { + "1.8.9-forge"(10809, "srg") {} +} \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ChatReceiveEvent.java b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ChatReceiveEvent.java new file mode 100644 index 0000000..6585729 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ChatReceiveEvent.java @@ -0,0 +1,22 @@ +package cc.polyfrost.oneconfig.events.event; + +import cc.polyfrost.oneconfig.libs.universal.wrappers.message.UTextComponent; +import net.minecraft.util.IChatComponent; + +/** + * Called when a chat message is received. + */ +public class ChatReceiveEvent extends CancellableEvent { + /** + * The message that was received. + */ + public final IChatComponent message; + + public ChatReceiveEvent(IChatComponent message) { + this.message = message; + } + + public String getFullyUnformattedMessage() { + return UTextComponent.Companion.stripFormatting(message.getUnformattedText()); + } +} diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ReceivePacketEvent.java b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ReceivePacketEvent.java new file mode 100644 index 0000000..17bc16d --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ReceivePacketEvent.java @@ -0,0 +1,11 @@ +package cc.polyfrost.oneconfig.events.event; + +import net.minecraft.network.Packet; + +public class ReceivePacketEvent extends CancellableEvent { + public final Packet packet; + + public ReceivePacketEvent(Packet packet) { + this.packet = packet; + } +} diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ScreenOpenEvent.java b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ScreenOpenEvent.java new file mode 100644 index 0000000..4593638 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/ScreenOpenEvent.java @@ -0,0 +1,17 @@ +package cc.polyfrost.oneconfig.events.event; + +import net.minecraft.client.gui.GuiScreen; +import org.jetbrains.annotations.Nullable; + +/** + * Called when a screen is opened or closed. + * If the screen is closed, {@link ScreenOpenEvent#screen} will be null. + */ +public class ScreenOpenEvent extends CancellableEvent { + @Nullable + public final GuiScreen screen; + + public ScreenOpenEvent(@Nullable GuiScreen screen) { + this.screen = screen; + } +} diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/events/event/SendPacketEvent.java b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/SendPacketEvent.java new file mode 100644 index 0000000..3cee784 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/SendPacketEvent.java @@ -0,0 +1,11 @@ +package cc.polyfrost.oneconfig.events.event; + +import net.minecraft.network.Packet; + +public class SendPacketEvent extends CancellableEvent { + public final Packet packet; + + public SendPacketEvent(Packet packet) { + this.packet = packet; + } +} diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/events/event/TimerUpdateEvent.java b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/TimerUpdateEvent.java new file mode 100644 index 0000000..a8b88dc --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/events/event/TimerUpdateEvent.java @@ -0,0 +1,24 @@ +package cc.polyfrost.oneconfig.events.event; + +import net.minecraft.util.Timer; + +/** + * Called when the {@link Timer} is updated. + * Can be used as an alternative to getting instances of {@link Timer} + * via Mixin or Access Wideners / Transformers + */ +public class TimerUpdateEvent { + /** + * Whether the deltaTicks / renderPartialTicks was updated + */ + public final boolean updatedDeltaTicks; + /** + * The {@link Timer} instance + */ + public final Timer timer; + + public TimerUpdateEvent(Timer timer, boolean updatedDeltaTicks) { + this.timer = timer; + this.updatedDeltaTicks = updatedDeltaTicks; + } +} \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/OneConfig.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/OneConfig.java new file mode 100644 index 0000000..7ecfe98 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/OneConfig.java @@ -0,0 +1,93 @@ +package cc.polyfrost.oneconfig.internal; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.ShutdownEvent; +import cc.polyfrost.oneconfig.internal.command.OneConfigCommand; +import cc.polyfrost.oneconfig.internal.config.OneConfigConfig; +import cc.polyfrost.oneconfig.internal.config.Preferences; +import cc.polyfrost.oneconfig.internal.config.core.ConfigCore; +import cc.polyfrost.oneconfig.internal.config.core.KeyBindHandler; +import cc.polyfrost.oneconfig.internal.gui.BlurHandler; +import cc.polyfrost.oneconfig.internal.hud.HudCore; +import cc.polyfrost.oneconfig.libs.eventbus.Subscribe; +import cc.polyfrost.oneconfig.utils.commands.CommandManager; +import cc.polyfrost.oneconfig.utils.gui.GuiUtils; +import cc.polyfrost.oneconfig.utils.hypixel.HypixelUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.util.ServiceLoader; + +/** + * The main class of OneConfig. + */ +@net.minecraftforge.fml.common.Mod(modid = "@ID@", name = "@NAME@", version = "@VER@") +public class OneConfig { + + public OneConfig() { + EventManager.INSTANCE.register(this); + } + + public static final File oneConfigDir = new File("./OneConfig"); + public static final Logger LOGGER = LogManager.getLogger("@NAME@"); + private static boolean preLaunched = false; + private static boolean initialized = false; + private static boolean isObfuscated = true; + + /** + * Called before mods are loaded. + *

SHOULD NOT BE CALLED!

+ */ + public static void preLaunch() { + if (preLaunched) return; + try { + Class.forName("net.minecraft.world.World"); + LOGGER.warn("OneConfig is NOT obfuscated!"); + isObfuscated = false; + } catch (Exception ignored) { + } + oneConfigDir.mkdirs(); + new File(oneConfigDir, "profiles").mkdirs(); + if (OneConfigConfig.getInstance() == null) { + OneConfigConfig.getInstance(); + } + if (Preferences.getInstance() == null) { + Preferences.getInstance(); + } + preLaunched = true; + } + + /** + * Called after mods are loaded. + *

SHOULD NOT BE CALLED!

+ */ + @SuppressWarnings("ResultOfMethodCallIgnored") + public static void init() { + if (initialized) return; + GuiUtils.getDeltaTime(); // called to make sure static initializer is called + try { + EventManager.INSTANCE.register(BlurHandler.INSTANCE); + } catch (Exception e) { + e.printStackTrace(); + } + CommandManager.INSTANCE.registerCommand(OneConfigCommand.class); + EventManager.INSTANCE.register(new HudCore()); + HypixelUtils.INSTANCE.initialize(); + EventManager.INSTANCE.register(KeyBindHandler.INSTANCE); + ConfigCore.sortMods(); + + initialized = true; + } + + /** Returns weather this is an obfuscated environment, using a check for obfuscated name of net.minecraft.world.World.class. + * @return true if this is an obfuscated environment, which is normal for Minecraft or false if not. */ + public static boolean isObfuscated() { + return isObfuscated; + } + + @Subscribe + private void onShutdown(ShutdownEvent event) { + ConfigCore.saveAll(); + } +} diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/gui/impl/BlurHandlerImpl.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/gui/impl/BlurHandlerImpl.java new file mode 100644 index 0000000..0ef5f2b --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/gui/impl/BlurHandlerImpl.java @@ -0,0 +1,132 @@ +package cc.polyfrost.oneconfig.internal.gui.impl; + +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.config.Preferences; +import cc.polyfrost.oneconfig.internal.gui.BlurHandler; +import cc.polyfrost.oneconfig.internal.mixin.ShaderGroupAccessor; +import cc.polyfrost.oneconfig.libs.eventbus.Subscribe; +import cc.polyfrost.oneconfig.libs.universal.UMinecraft; +import cc.polyfrost.oneconfig.libs.universal.UScreen; +import net.minecraft.client.Minecraft; +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. + *

+ * For the original source see ... + * For the public license, see ... + *

+ * License available under ... + * + * @author tterrag1098, boomboompower + *

+ * Taken from ToggleChat + * ... + */ +public class BlurHandlerImpl implements 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 progress = 0; + + @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; + } + if (progress >= 5) return; + progress = getBlurStrengthProgress(); + + // 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 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 + */ + public void reloadBlur(Object 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 && Preferences.enableBlur) { + UMinecraft.getMinecraft().entityRenderer.loadShader(this.blurShader); + + this.start = System.currentTimeMillis(); + this.progress = 0; + + // 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 || !Preferences.enableBlur)) { + 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. + *

+ * 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/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java new file mode 100644 index 0000000..2a89972 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java @@ -0,0 +1,19 @@ +//#if MC==10809 +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)); + } +} +//#endif \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java new file mode 100644 index 0000000..0603d12 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java @@ -0,0 +1,100 @@ +//#if MC==10809 +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 = "shutdownMinecraftApplet", at = @At("HEAD")) + private void onShutdown(CallbackInfo ci) { + EventManager.INSTANCE.post(new PreShutdownEvent()); + } + + @Inject(method = "startGame", at = @At("HEAD")) + private void onStart(CallbackInfo ci) { + EventManager.INSTANCE.post(new StartEvent()); + Runtime.getRuntime().addShutdownHook(new Thread(() -> EventManager.INSTANCE.post(new ShutdownEvent()))); + } + + @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) { + EventManager.INSTANCE.post(new InitializationEvent()); + 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)); + } + + @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/FMLCommonHandler;fireKeyInput()V")) + private void onKeyEvent(CallbackInfo ci) { + EventManager.INSTANCE.post(new KeyInputEvent()); + } + + @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/FMLCommonHandler;fireMouseInput()V")) + private void onMouseEvent(CallbackInfo ci) { + EventManager.INSTANCE.post(new MouseInputEvent()); + } +} +//#endif \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java new file mode 100644 index 0000000..7a446c7 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java @@ -0,0 +1,38 @@ +//#if MC==10809 +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(); + } + } + } +} +//#endif \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java new file mode 100644 index 0000000..3da0c91 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java @@ -0,0 +1,25 @@ +//#if MC==10809 +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(); + } + } +} +//#endif \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/OptifineConfigMixin.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/OptifineConfigMixin.java new file mode 100644 index 0000000..9012091 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/OptifineConfigMixin.java @@ -0,0 +1,23 @@ +//#if MC==10809 +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.internal.plugin.hooks.OptifineConfigHook; +import org.spongepowered.asm.mixin.Dynamic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Pseudo +@Mixin(targets = "Config", remap = false) +public class OptifineConfigMixin { + @Dynamic("OptiFine") + @Inject(method = "isFastRender", at = @At("HEAD"), cancellable = true) + private static void cancelFastRender(CallbackInfoReturnable cir) { + if (OptifineConfigHook.shouldNotApplyFastRender()) { + cir.setReturnValue(false); + } + } +} +//#endif \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/ShaderGroupAccessor.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/ShaderGroupAccessor.java new file mode 100644 index 0000000..588da19 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/ShaderGroupAccessor.java @@ -0,0 +1,16 @@ +//#if MC==10809 +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 getListShaders(); +} +//#endif \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/VigilantMixin.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/VigilantMixin.java new file mode 100644 index 0000000..6b474ab --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/VigilantMixin.java @@ -0,0 +1,10 @@ +//#if MC==10809 +package cc.polyfrost.oneconfig.internal.mixin; + +import gg.essential.vigilance.Vigilant; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Vigilant.class) +public class VigilantMixin { +} +//#endif \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java new file mode 100644 index 0000000..05c6920 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java @@ -0,0 +1,23 @@ +//#if MC==10809 +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 = "", 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()); + } +} +//#endif \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java new file mode 100644 index 0000000..52256ca --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ClassTransformer.java @@ -0,0 +1,102 @@ +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.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collection; + +/** + * Taken from LWJGLTwoPointFive under The Unlicense + * https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/ + *

also half taken from asmworkspace by asbyth ty

+ */ +@SuppressWarnings("unused") +public class ClassTransformer implements IClassTransformer { + private static final Logger logger = LogManager.getLogger("OneConfig ASM"); + private final Multimap transformerMap = ArrayListMultimap.create(); + private static final boolean outputBytecode = Boolean.parseBoolean(System.getProperty("debugBytecode", "false")); + + 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[] bytes) { + if (bytes == null) return null; + + Collection transformers = transformerMap.get(transformedName); + if (transformers.isEmpty()) return bytes; + + ClassReader reader = new ClassReader(bytes); + 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(); + } + + if (outputBytecode) { + File bytecodeDirectory = new File("bytecode"); + String transformedClassName; + + // anonymous classes + if (transformedName.contains("$")) { + transformedClassName = transformedName.replace('$', '.') + ".class"; + } else { + transformedClassName = transformedName + ".class"; + } + + if (!bytecodeDirectory.exists()) { + bytecodeDirectory.mkdirs(); + } + + File bytecodeOutput = new File(bytecodeDirectory, transformedClassName); + + try { + if (!bytecodeOutput.exists()) { + bytecodeOutput.createNewFile(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + try (FileOutputStream os = new FileOutputStream(bytecodeOutput)) { + // write to the generated class to /run/bytecode/classfile.class + // with the class bytes from transforming + os.write(cw.toByteArray()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return cw.toByteArray(); + } +} \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java new file mode 100644 index 0000000..1bc50d1 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/ITransformer.java @@ -0,0 +1,24 @@ +package cc.polyfrost.oneconfig.internal.plugin.asm; + +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +public interface ITransformer { + String[] getClassName(); + + void transform(String transformedName, ClassNode node); + + default void clearInstructions(MethodNode methodNode) { + methodNode.instructions.clear(); + + // dont waste time clearing local variables if they're empty + if (!methodNode.localVariables.isEmpty()) { + methodNode.localVariables.clear(); + } + + // dont waste time clearing try-catches if they're empty + if (!methodNode.tryCatchBlocks.isEmpty()) { + methodNode.tryCatchBlocks.clear(); + } + } +} diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/OneConfigTweaker.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/OneConfigTweaker.java new file mode 100644 index 0000000..d302b9d --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/OneConfigTweaker.java @@ -0,0 +1,117 @@ +package cc.polyfrost.oneconfig.internal.plugin.asm; + +import cc.polyfrost.oneconfig.internal.init.OneConfigInit; +import net.minecraft.launchwrapper.ITweaker; +import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraftforge.fml.relauncher.CoreModManager; +import org.spongepowered.asm.launch.MixinBootstrap; +import org.spongepowered.asm.launch.MixinTweaker; +import org.spongepowered.asm.mixin.Mixins; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URL; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarFile; + +public class OneConfigTweaker implements ITweaker { + + public OneConfigTweaker() { + for (URL url : Launch.classLoader.getSources()) { + doMagicMixinStuff(url); + } + } + + private void doMagicMixinStuff(URL url) { + try { + URI uri = url.toURI(); + if (Objects.equals(uri.getScheme(), "file")) { + File file = new File(uri); + if (file.exists() && file.isFile()) { + try (JarFile jarFile = new JarFile(file)) { + if (jarFile.getManifest() != null) { + Attributes attributes = jarFile.getManifest().getMainAttributes(); + String tweakerClass = attributes.getValue("TweakClass"); + if (Objects.equals(tweakerClass, "cc.polyfrost.oneconfigwrapper.OneConfigWrapper")) { + CoreModManager.getIgnoredMods().remove(file.getName()); + CoreModManager.getReparseableCoremods().add(file.getName()); + String mixinConfig = attributes.getValue("MixinConfigs"); + if (mixinConfig != null) { + try { + try { + List tweakClasses = (List) Launch.blackboard.get("TweakClasses"); // tweak classes before other mod trolling + if (tweakClasses.contains("org.spongepowered.asm.launch.MixinTweaker")) { // if there's already a mixin tweaker, we'll just load it like "usual" + new MixinTweaker(); // also we might not need to make a new mixin tweawker all the time but im just making sure + } else if (!Launch.blackboard.containsKey("mixin.initialised")) { // if there isnt, we do our own trolling + List tweaks = (List) Launch.blackboard.get("Tweaks"); + tweaks.add(new MixinTweaker()); + } + } catch (Exception ignored) { + // if it fails i *think* we can just ignore it + } + MixinBootstrap.getPlatform().addContainer(uri); + } catch (Exception ignored) { + + } + } + } + } + } + } + } + } catch (Exception ignored) { + + } + } + + @Override + public void acceptOptions(List args, File gameDir, File assetsDir, String profile) { + MixinBootstrap.init(); + boolean captureNext = false; + for (String arg : args) { + if (captureNext) { + Mixins.addConfiguration(arg); + } + captureNext = "--mixin".equals(arg); + } + } + + @Override + public void injectIntoClassLoader(LaunchClassLoader classLoader) { + removeLWJGLException(); + Launch.classLoader.registerTransformer(ClassTransformer.class.getName()); + OneConfigInit.initialize(new String[]{}); + Launch.blackboard.put("oneconfig.init.initialized", true); + Launch.classLoader.addClassLoaderExclusion("cc.polyfrost.oneconfig.internal.plugin.asm."); + } + + /** + * Taken from LWJGLTwoPointFive under The Unlicense + * https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/ + */ + private void removeLWJGLException() { + try { + Field f_exceptions = LaunchClassLoader.class.getDeclaredField("classLoaderExceptions"); + f_exceptions.setAccessible(true); + Set exceptions = (Set) f_exceptions.get(Launch.classLoader); + exceptions.remove("org.lwjgl."); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String getLaunchTarget() { + return null; + } + + @Override + public String[] getLaunchArguments() { + return new String[0]; + } +} \ No newline at end of file diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java new file mode 100644 index 0000000..bbbf4a1 --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/NanoVGGLConfigTransformer.java @@ -0,0 +1,47 @@ +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.*; + +/** + * Taken from LWJGLTwoPointFive under The Unlicense + * https://github.com/DJtheRedstoner/LWJGLTwoPointFive/blob/master/LICENSE/ + */ +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/hooks/Lwjgl2FunctionProvider")); + list.add(new InsnNode(Opcodes.DUP)); + list.add(new MethodInsnNode( + Opcodes.INVOKESPECIAL, + "cc/polyfrost/oneconfig/internal/plugin/hooks/Lwjgl2FunctionProvider", + "", + "()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)); + + clearInstructions(method); + method.instructions.insert(list); + } + } + } +} diff --git a/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java new file mode 100644 index 0000000..8dd60cf --- /dev/null +++ b/versions/src/main/java/cc/polyfrost/oneconfig/internal/plugin/asm/tweakers/VigilantTransformer.java @@ -0,0 +1,89 @@ +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.Type; +import org.objectweb.asm.tree.*; + +import java.io.File; + +public class VigilantTransformer implements ITransformer { + + @Override + public String[] getClassName() { + return new String[]{"gg.essential.vigilance.Vigilant"}; + } + + /** + * If anything here is changed, edit the corresponding method in OneConfigMixinPlugin! + */ + @Override + public void transform(String transformedName, ClassNode node) { + if (!node.interfaces.contains("cc/polyfrost/oneconfig/config/compatibility/vigilance/VigilantAccessor")) { + node.fields.add(new FieldNode(Opcodes.ACC_PUBLIC, "oneconfig$config", "Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;", 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", "Lgg/essential/vigilance/data/PropertyCollector;")); + 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", "Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;")); + + 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", "Lcc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig;")); + methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); + methodNode2.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); + methodNode2.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "cc/polyfrost/oneconfig/config/compatibility/vigilance/VigilanceConfig", "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, "cc/polyfrost/oneconfig/internal/plugin/hooks/VigilantHook", "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$