diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 5c01fd5..0000000 --- a/build.gradle +++ /dev/null @@ -1,126 +0,0 @@ -//file:noinspection UnnecessaryQualifiedReference -//file:noinspection GroovyAssignabilityCheck - -plugins { - id "dev.architectury.architectury-pack200" version "0.1.3" - id "com.github.johnrengelman.shadow" version "7.1.2" - id "org.jetbrains.kotlin.jvm" version "1.6.10" - id "gg.essential.loom" version "0.10.0.4" - id "net.kyori.blossom" version "1.3.0" - id "java" -} - -version = mod_version -group = "co.skyclient" -archivesBaseName = mod_name - -blossom { - String className = "src/main/java/co/skyclient/scc/SkyclientCosmetics.java" - replaceToken("@VER@", project.version, className) - replaceToken("@NAME@", mod_name, className) - replaceToken("@ID@", mod_id, className) -} - -sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 -compileJava.options.encoding = 'UTF-8' - -compileKotlin { - kotlinOptions { - freeCompilerArgs += "-Xjvm-default=all-compatibility" - } -} - -loom { - launchConfigs { - client { - arg("--tweakClass", "co.skyclient.scc.hooks.ReplacedModRemover") - property("onecore.mixin", "mixins.scc.json") - property("mixin.debug.export", "true") - } - } - runConfigs { - client { - ideConfigGenerated = true - } - } - forge { - pack200Provider = new dev.architectury.pack200.java.Pack200Adapter() - mixinConfig("mixins.scc.json") - mixin.defaultRefmapName.set("mixins.scc.refmap.json") - } -} - -configurations { - include - implementation.extendsFrom(include) - dummyBuild - dummyImplementation.extendsFrom(dummyBuild) -} - -repositories { - maven { url 'https://repo.polyfrost.cc/releases' } - maven { url = "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1" } -} - -dependencies { - minecraft("com.mojang:minecraft:1.8.9") - mappings("de.oceanlabs.mcp:mcp_stable:22-1.8.9") - forge("net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9") - dummyBuild("gg.essential:essential-1.8.9-forge:1933") - compileOnly("gg.essential:essential-1.8.9-forge:1933") - include 'gg.essential:loader-launchwrapper:1.1.3' - include 'com.github.JnCrMx:discord-game-sdk4j:v0.5.5' - compileOnly ('org.spongepowered:mixin:0.8.5-SNAPSHOT') - runtimeOnly ("me.djtheredstoner:DevAuth-forge-legacy:1.1.2") -} - -processResources { - // this will ensure that this task is redone when the versions change. - inputs.property "version", version - inputs.property "name", mod_name - inputs.property "id", mod_id - - filesMatching("mcmod.info") { - expand( - "id": mod_id, - "name": mod_name, - "version": version - ) - } - - rename '(.+_at.cfg)', 'META-INF/$1' -} - -sourceSets { - dummy { - java {} - } - main { - compileClasspath += dummy.output - output.resourcesDir = java.classesDirectory - } -} - - -shadowJar { - archiveClassifier.set('dev') - configurations = [project.configurations.include] - duplicatesStrategy DuplicatesStrategy.EXCLUDE -} - -remapJar { - archiveClassifier.set('') - from(shadowJar.archiveFile) -} - -jar { - manifest.attributes( - 'ModSide': 'CLIENT', - 'ForceLoadAsMod': true, - 'TweakClass': 'co.skyclient.scc.hooks.ReplacedModRemover', - 'MixinConfigs': "mixins.scc.json", - "TweakOrder": "0" - ) - enabled = false -} -jar.dependsOn(shadowJar) \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..31c56f0 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,199 @@ +@file:Suppress("UnstableApiUsage", "PropertyName") + +import org.polyfrost.gradle.util.noServerRunConfigs +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +// Adds support for kotlin, and adds the Polyfrost Gradle Toolkit +// which we use to prepare the environment. +plugins { + kotlin("jvm") + id("org.polyfrost.multi-version") + id("org.polyfrost.defaults.repo") + id("org.polyfrost.defaults.java") + id("org.polyfrost.defaults.loom") + id("com.github.johnrengelman.shadow") + id("net.kyori.blossom") version "1.3.1" + id("signing") + java +} + +// Gets the mod name, version and id from the `gradle.properties` file. +val mod_name: String by project +val mod_version: String by project +val mod_id: String by project +val mod_archives_name: String by project + +// Sets up the variables for when we preprocess to other Minecraft versions. +preprocess { + vars.put("MODERN", if (project.platform.mcMinor >= 16) 1 else 0) +} + +// Replaces the variables in `ExampleMod.java` to the ones specified in `gradle.properties`. +blossom { + replaceToken("@VER@", mod_version) + replaceToken("@NAME@", mod_name) + replaceToken("@ID@", mod_id) +} + +// Sets the mod version to the one specified in `gradle.properties`. Make sure to change this following semver! +version = mod_version +// Sets the group, make sure to change this to your own. It can be a website you own backwards or your GitHub username. +// e.g. com.github. or com. +group = "co.skyclient" + +// Sets the name of the output jar (the one you put in your mods folder and send to other people) +// It outputs all versions of the mod into the `build` directory. +base { + archivesName.set("$mod_archives_name-$platform") +} + +// Configures the Polyfrost Loom, our plugin fork to easily set up the programming environment. +loom { + // Removes the server configs from IntelliJ IDEA, leaving only client runs. + // If you're developing a server-side mod, you can remove this line. + noServerRunConfigs() + + // Adds the tweak class if we are building legacy version of forge as per the documentation (https://docs.polyfrost.org) + if (project.platform.isLegacyForge) { + runConfigs { + "client" { + programArgs("--tweakClass", "co.skyclient.scc.hooks.ReplacedModRemover") + property("mixin.debug.export", "true") + } + } + } + // Configures the mixins if we are building for forge, useful for when we are dealing with cross-platform projects. + if (project.platform.isForge) { + forge { + mixinConfig("mixins.scc.json") + } + } + // Configures the name of the mixin "refmap" using an experimental loom api. + mixin.defaultRefmapName.set("mixins.scc.refmap.json") +} + +// Creates the shade/shadow configuration, so we can include libraries inside our mod, rather than having to add them separately. +val shade: Configuration by configurations.creating { + configurations.modImplementation.get().extendsFrom(this) +} + +// Configures the output directory for when building from the `src/resources` directory. +sourceSets { + val dummy by creating + main { + compileClasspath += dummy.output + output.setResourcesDir(java.classesDirectory) + } +} + +// Adds the Polyfrost maven repository so that we can get the libraries necessary to develop the mod. +repositories { + maven("https://repo.polyfrost.org/releases") +} + +// Configures the libraries/dependencies for your mod. +dependencies { + // Adds the OneConfig library, so we can develop with it. + modCompileOnly("cc.polyfrost:oneconfig-$platform:0.2.1-alpha+") + + modRuntimeOnly("me.djtheredstoner:DevAuth-${if (platform.isFabric) "fabric" else if (platform.isLegacyForge) "forge-legacy" else "forge-latest"}:1.1.2") + + shade("com.github.JnCrMx:discord-game-sdk4j:v0.5.5") + shade("cc.polyfrost:elementa-$platform:560") + + // If we are building for legacy forge, includes the launch wrapper with `shade` as we configured earlier. + if (platform.isLegacyForge) { + compileOnly("org.spongepowered:mixin:0.7.11-SNAPSHOT") + shade("cc.polyfrost:oneconfig-wrapper-launchwrapper:1.0.0-beta+") + } +} + +tasks { + // Processes the `src/resources/mcmod.info or fabric.mod.json` and replaces + // the mod id, name and version with the ones in `gradle.properties` + processResources { + inputs.property("id", mod_id) + inputs.property("name", mod_name) + val java = if (project.platform.mcMinor >= 18) { + 17 // If we are playing on version 1.18, set the java version to 17 + } else { + // Else if we are playing on version 1.17, use java 16. + if (project.platform.mcMinor == 17) + 16 + else + 8 // For all previous versions, we **need** java 8 (for Forge support). + } + 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.scc.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" + ) + ) + } + } + + // Configures the resources to include if we are building for forge or fabric. + withType(Jar::class.java) { + if (project.platform.isFabric) { + exclude("mcmod.info", "mods.toml") + } else { + exclude("fabric.mod.json") + if (project.platform.isLegacyForge) { + exclude("mods.toml") + } else { + exclude("mcmod.info") + } + } + } + + // Configures our shadow/shade configuration, so we can + // include some dependencies within our mod jar file. + named("shadowJar") { + archiveClassifier.set("dev") // TODO: machete gets confused by the `dev` prefix. + configurations = listOf(shade) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } + + remapJar { + inputFile.set(shadowJar.get().archiveFile) + archiveClassifier.set("") + } + + jar { + // Sets the jar manifest attributes. + if (platform.isLegacyForge) { + manifest.attributes += mapOf( + "ModSide" to "CLIENT", // We aren't developing a server-side mod, so this is fine. + "ForceLoadAsMod" to true, // We want to load this jar as a mod, so we force Forge to do so. + "TweakOrder" to "0", // Makes sure that the OneConfig launch wrapper is loaded as soon as possible. + "MixinConfigs" to "mixins.scc.json", // We want to use our mixin configuration, so we specify it here. + "TweakClass" to "co.skyclient.scc.hooks.ReplacedModRemover" // Loads the OneConfig launch wrapper. + ) + } + dependsOn(shadowJar) + archiveClassifier.set("") + enabled = false + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 9eca7cf..4c5df80 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,12 @@ mod_id=skyclientcosmetics mod_name=SkyClientCosmetics -mod_version=1.1.13 +mod_version=1.1.14 +mod_archives_name=SkyClientCosmetics -org.gradle.jvmargs=-Xmx2G -loom.platform = forge +# Gradle Configuration -- DO NOT TOUCH THESE VALUES. +polyfrost.defaults.loom=1 +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.configureoncommand=true +org.gradle.parallel.threads=4 +org.gradle.jvmargs=-Xmx2G \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b1159fc..e411586 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/root.gradle.kts b/root.gradle.kts new file mode 100644 index 0000000..d3fa8a6 --- /dev/null +++ b/root.gradle.kts @@ -0,0 +1,11 @@ +plugins { + kotlin("jvm") version "1.9.10" apply false + id("org.polyfrost.multi-version.root") + id("com.github.johnrengelman.shadow") version "7.1.2" apply false +} + +preprocess { + "1.8.9-forge"(10809, "srg") { + + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 262fc29..0000000 --- a/settings.gradle +++ /dev/null @@ -1,9 +0,0 @@ -pluginManagement { - repositories { - gradlePluginPortal() - maven { url = "https://repo.polyfrost.cc/releases" } - maven { url = "https://maven.architectury.dev/" } - } -} - -rootProject.name = mod_name \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..9692a27 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,30 @@ +@file:Suppress("PropertyName") + +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + maven("https://repo.polyfrost.org/releases") // Adds the Polyfrost maven repository to get Polyfrost Gradle Toolkit + } + plugins { + val pgtVersion = "0.2.9" // Sets the default versions for Polyfrost Gradle Toolkit + id("org.polyfrost.multi-version.root") version pgtVersion + } +} + +val mod_name: String by settings + +// Configures the root project Gradle name based on the value in `gradle.properties` +rootProject.name = mod_name +rootProject.buildFileName = "root.gradle.kts" + +// Adds all of our build target versions to the classpath if we need to add version-specific code. +listOf( + "1.8.9-forge" +).forEach { version -> + include(":$version") + project(":$version").apply { + projectDir = file("versions/$version") + buildFileName = "../../build.gradle.kts" + } +} \ No newline at end of file diff --git a/src/dummy/java/club/sk1er/patcher/config/PatcherConfig.java b/src/dummy/java/club/sk1er/patcher/config/PatcherConfig.java index 8d61ab9..73d00b9 100644 --- a/src/dummy/java/club/sk1er/patcher/config/PatcherConfig.java +++ b/src/dummy/java/club/sk1er/patcher/config/PatcherConfig.java @@ -1,10 +1,6 @@ package club.sk1er.patcher.config; -import gg.essential.vigilance.Vigilant; - -import java.io.File; - -public class PatcherConfig extends Vigilant { +public class PatcherConfig { public static boolean hudCaching; public static boolean cullingFix; public static boolean separateResourceLoading; @@ -21,7 +17,11 @@ public class PatcherConfig extends Vigilant { public static PatcherConfig INSTANCE = new PatcherConfig(); - public PatcherConfig() { - super(new File("")); + public void markDirty() { + // lol + } + + public void writeData() { + // lol } } diff --git a/src/dummy/java/gg/essential/api/EssentialAPI.java b/src/dummy/java/gg/essential/api/EssentialAPI.java new file mode 100644 index 0000000..828a47e --- /dev/null +++ b/src/dummy/java/gg/essential/api/EssentialAPI.java @@ -0,0 +1,20 @@ +package gg.essential.api; + +import gg.essential.api.data.OnboardingData; + +public interface EssentialAPI { + + static OnboardingData getOnboardingData() { + return new OnboardingData() { + @Override + public boolean hasAcceptedEssentialTOS() { + return false; + } + + @Override + public boolean hasDeniedEssentialTOS() { + return false; + } + }; + } +} diff --git a/src/dummy/java/gg/essential/api/data/OnboardingData.java b/src/dummy/java/gg/essential/api/data/OnboardingData.java new file mode 100644 index 0000000..5efa009 --- /dev/null +++ b/src/dummy/java/gg/essential/api/data/OnboardingData.java @@ -0,0 +1,7 @@ +package gg.essential.api.data; + +public interface OnboardingData { + public boolean hasAcceptedEssentialTOS(); + + public boolean hasDeniedEssentialTOS(); +} diff --git a/src/main/java/co/skyclient/scc/SkyclientCosmetics.java b/src/main/java/co/skyclient/scc/SkyclientCosmetics.java index 3ebb485..05c44a9 100644 --- a/src/main/java/co/skyclient/scc/SkyclientCosmetics.java +++ b/src/main/java/co/skyclient/scc/SkyclientCosmetics.java @@ -17,6 +17,7 @@ package co.skyclient.scc; +import cc.polyfrost.oneconfig.utils.commands.CommandManager; import club.sk1er.patcher.config.PatcherConfig; import co.skyclient.scc.commands.SccComand; import co.skyclient.scc.config.Settings; @@ -29,7 +30,6 @@ import co.skyclient.scc.rpc.RPC; import co.skyclient.scc.utils.Files; import de.jcm.discordgamesdk.Core; -import gg.essential.vigilance.Vigilant; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.multiplayer.ServerList; @@ -69,7 +69,8 @@ public class SkyclientCosmetics { public static Logger LOGGER; public static boolean isPatcher; - public static Vigilant scuConfig = null; + public static boolean isEssential; + public static Object scuConfig = null; //private static boolean hasFailed; @Mod.EventHandler @@ -107,7 +108,7 @@ public void onInit(FMLInitializationEvent event) { progress.step("Registering Commands"); - new SccComand().register(); + CommandManager.INSTANCE.registerCommand(new SccComand()); progress.step("Loading Tags"); @@ -143,10 +144,12 @@ public void onPostInit(FMLPostInitializationEvent event) { } } else if ("skyblockclientupdater".equals(mod.getModId())) { try { - scuConfig = (Vigilant) Class.forName("mynameisjeff.skyblockclientupdater.config.Config").getDeclaredField("INSTANCE").get(null); + scuConfig = Class.forName("mynameisjeff.skyblockclientupdater.config.Config").getDeclaredField("INSTANCE").get(null); } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } + } else if ("essential".equals(mod.getModId())) { + isEssential = true; } } diff --git a/src/main/java/co/skyclient/scc/commands/SccComand.java b/src/main/java/co/skyclient/scc/commands/SccComand.java index 1fb1a9e..ee9298c 100644 --- a/src/main/java/co/skyclient/scc/commands/SccComand.java +++ b/src/main/java/co/skyclient/scc/commands/SccComand.java @@ -1,50 +1,36 @@ package co.skyclient.scc.commands; +import cc.polyfrost.oneconfig.utils.commands.annotations.Command; +import cc.polyfrost.oneconfig.utils.commands.annotations.Description; +import cc.polyfrost.oneconfig.utils.commands.annotations.Main; +import cc.polyfrost.oneconfig.utils.commands.annotations.SubCommand; import co.skyclient.scc.SkyclientCosmetics; import co.skyclient.scc.cosmetics.Tag; import co.skyclient.scc.cosmetics.TagCosmetics; import co.skyclient.scc.utils.ChatUtils; -import gg.essential.api.EssentialAPI; -import gg.essential.api.commands.Command; -import gg.essential.api.commands.DefaultHandler; -import gg.essential.api.commands.DisplayName; -import gg.essential.api.commands.SubCommand; -import java.util.HashSet; -import java.util.Set; +@Command(value = "scc", aliases = "skyclientcosmetics") +public class SccComand { -public class SccComand extends Command { - private final Set hashSet = new HashSet<>(); - - public SccComand() { - super("scc"); - hashSet.add(new Alias("skyclientcosmetics")); - } - - @Override - public Set getCommandAliases() { - return hashSet; - } - - @DefaultHandler + @Main public void handle() { - EssentialAPI.getGuiUtil().openScreen(SkyclientCosmetics.config.gui()); + SkyclientCosmetics.config.openGui(); } - @SubCommand("reload") + @SubCommand public void reload() { if (TagCosmetics.getInstance().isInitialized()) TagCosmetics.getInstance().reInitialize(); } - @SubCommand("displaytag") - public void displaytag(@DisplayName("Player name") String name) { + @SubCommand + public void displaytag(@Description("Player name") String name) { Tag tag = TagCosmetics.getInstance().getTag(name); if (tag != null) { ChatUtils.sendSystemMessage(name + "'s tag: " + tag); } } - @SubCommand("tags") + @SubCommand public void tags() { ChatUtils.sendSystemMessage(String.valueOf(TagCosmetics.getInstance().getTags())); } diff --git a/src/main/java/co/skyclient/scc/config/Settings.java b/src/main/java/co/skyclient/scc/config/Settings.java index a71a581..6e15032 100644 --- a/src/main/java/co/skyclient/scc/config/Settings.java +++ b/src/main/java/co/skyclient/scc/config/Settings.java @@ -17,58 +17,51 @@ package co.skyclient.scc.config; +import cc.polyfrost.oneconfig.config.Config; +import cc.polyfrost.oneconfig.config.annotations.Button; +import cc.polyfrost.oneconfig.config.annotations.Switch; +import cc.polyfrost.oneconfig.config.annotations.Text; +import cc.polyfrost.oneconfig.config.data.Mod; +import cc.polyfrost.oneconfig.config.data.ModType; +import cc.polyfrost.oneconfig.config.migration.VigilanceMigrator; import co.skyclient.scc.cosmetics.TagCosmetics; -import gg.essential.vigilance.Vigilant; -import gg.essential.vigilance.data.Property; -import gg.essential.vigilance.data.PropertyType; -import java.io.File; +public class Settings extends Config { -public class Settings extends Vigilant { - - @Property(type = PropertyType.SWITCH, name = "Custom Main Menu", description = "Enable the SkyClient Custom Main Menu.", category = "Main") + @Switch(name = "Custom Main Menu", description = "Enable the SkyClient Custom Main Menu.", category = "Main") public static boolean customMainMenu = true; - @Property(type = PropertyType.SWITCH, name = "Show Custom Tags", description = "Show the custom tags, which are the main focus of this mod.", category = "Main", subcategory = "Tags") + @Switch(name = "Show Custom Tags", description = "Show the custom tags, which are the main focus of this mod.", category = "Main", subcategory = "Tags") public static boolean showTags = true; - @Property(type = PropertyType.SWITCH, name = "Shorten Custom Tags", description = "Use shorter tags.\n[BOOSTER] becomes [B], for example.", category = "Main", subcategory = "Tags") + @Switch(name = "Shorten Custom Tags", description = "Use shorter tags.\n[BOOSTER] becomes [B], for example.", category = "Main", subcategory = "Tags") public static boolean shortenTags = false; - @Property(type = PropertyType.BUTTON, name = "Reload Tags", description = "Reloads the custom tags.", category = "Main", subcategory = "Tags", placeholder = "Reload") + @Button(name = "Reload Tags", description = "Reloads the custom tags.", category = "Misc", subcategory = "Tags", text = "Reload") public static void reloadTags() { if (TagCosmetics.getInstance().isInitialized()) TagCosmetics.getInstance().reInitialize(); } - @Property(type = PropertyType.TEXT, name = "Discord RPC Second Line", description = "Allows you to edit the second line of the Discord RPC\n\u00A7aAllows usage of Placeholders. More info on the wiki (https://github.com/koxx12-dev/Skyclient-Cosmetics/wiki/Discord-RPC)", category = "Main", subcategory = "Discord Rich Presence") + @Text(name = "Discord RPC Second Line", description = "Allows you to edit the second line of the Discord RPC\n\u00A7aAllows usage of Placeholders. More info on the wiki (https://github.com/koxx12-dev/Skyclient-Cosmetics/wiki/Discord-RPC)", category = "Main", subcategory = "Discord Rich Presence") public static String rpcLineTwo = "Playing Hypixel"; - @Property(type = PropertyType.TEXT, name = "Discord RPC First Line", description = "Allows you to edit the first line of the Discord RPC\n\u00A7aAllows usage of Placeholders. More info on the wiki (https://github.com/koxx12-dev/Skyclient-Cosmetics/wiki/Discord-RPC)", category = "Main", subcategory = "Discord Rich Presence") + @Text(name = "Discord RPC First Line", description = "Allows you to edit the first line of the Discord RPC\n\u00A7aAllows usage of Placeholders. More info on the wiki (https://github.com/koxx12-dev/Skyclient-Cosmetics/wiki/Discord-RPC)", category = "Main", subcategory = "Discord Rich Presence") public static String rpcLineOne = "%player% is very cool"; - @Property(type = PropertyType.TEXT, name = "Discord RPC Img Text", description = "Allows you to set text of the img\n\u00A7aAllows usage of Placeholders. More info on the wiki (https://github.com/koxx12-dev/Skyclient-Cosmetics/wiki/Discord-RPC)", category = "Main", subcategory = "Discord Rich Presence") + @Text(name = "Discord RPC Img Text", description = "Allows you to set text of the img\n\u00A7aAllows usage of Placeholders. More info on the wiki (https://github.com/koxx12-dev/Skyclient-Cosmetics/wiki/Discord-RPC)", category = "Main", subcategory = "Discord Rich Presence") public static String rpcImgText = "SkyClient is cool"; - @Property(type = PropertyType.SWITCH, name = "Discord RPC", description = "Enables Discord RPC", category = "Main", subcategory = "Discord Rich Presence") + @Switch(name = "Discord RPC", description = "Enables Discord RPC", category = "Main", subcategory = "Discord Rich Presence") public static boolean rpc = true; - @Property(type = PropertyType.SWITCH, name = "First Time Message", description = "Get \"First time message\" when u join next time", category = "Misc", subcategory = "Chat", hidden = true) + @Switch(name = "First Time Message", description = "Get \"First time message\" when u join next time", category = "Misc", subcategory = "Chat") public static boolean joinMessage = true; -// @Property(type = PropertyType.SWITCH, name = "SBE Sucks Mode", description = "https://github.com/MicrocontrollersDev/Alternatives/blob/1e409e056e3e14ca874a2368c045de96787e8cbd/SkyblockExtras.md", category = "Main", subcategory = "Discord Rich Presence") -// public static boolean sbeBadMode = false; - - @Property(type = PropertyType.SWITCH, name = "Tags in Display Names", description = "Shows tags above player names\n\u00A7c(May crash)", category = "Main", subcategory = "Tags") + @Switch(name = "Tags in Display Names", description = "Shows tags above player names\n\u00A7c(May crash)", category = "Misc", subcategory = "Tags") public static boolean displayTags = false; - @Property(type = PropertyType.TEXT, name = "Hypixel API key", description = "Hypixel API key used for requests", category = "Main", subcategory = "Hypixel", protectedText = true) - public static String hpApiKey = ""; - - //@Property(type = PropertyType.TEXT, name = "Skyclient Cosmetics API key", description = "SkyclientCosmetics Api key is used for every feature of this mod", category = "Main", subcategory = "Main", protectedText = true) - //public static String SCCApiKey = ""; - public Settings() { - super(new File("./SkyclientCosmetics/skyclientcosmetics.toml")); + super(new Mod("SkyClientCosmetics", ModType.UTIL_QOL, "/assets/scc/SkyClient.png", new VigilanceMigrator("./SkyclientCosmetics/skyclientcosmetics.toml")), "skyclientcosmetics.json"); //final Class SettingsClass = Settings.class; @@ -78,6 +71,7 @@ public Settings() { addDependency("rpcLineTwo", "rpc"); addDependency("rpcLineOne", "rpc"); addDependency("rpcImgText", "rpc"); + hideIf("joinMessage", () -> true); addDependency("shortenTags", "showTags"); //addDependency("reloadTags","showTags"); diff --git a/src/main/java/co/skyclient/scc/cosmetics/TagCosmetics.java b/src/main/java/co/skyclient/scc/cosmetics/TagCosmetics.java index 682f5de..156ab99 100644 --- a/src/main/java/co/skyclient/scc/cosmetics/TagCosmetics.java +++ b/src/main/java/co/skyclient/scc/cosmetics/TagCosmetics.java @@ -1,10 +1,10 @@ package co.skyclient.scc.cosmetics; +import cc.polyfrost.oneconfig.libs.universal.ChatColor; +import cc.polyfrost.oneconfig.utils.Multithreading; +import cc.polyfrost.oneconfig.utils.NetworkUtils; import co.skyclient.scc.utils.Files; import com.google.gson.*; -import gg.essential.api.utils.Multithreading; -import gg.essential.api.utils.WebUtil; -import gg.essential.universal.ChatColor; import org.apache.commons.io.FileUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,7 +42,7 @@ public void initialize() { Multithreading.runAsync(() -> { try { try { - rawData = new JsonParser().parse(Objects.requireNonNull(WebUtil.fetchString("https://cdn.jsdelivr.net/gh/KTibow/Skyclient@main/docs/assets/tags.json")).replace('&', ChatColor.COLOR_CHAR)).getAsJsonObject(); + rawData = new JsonParser().parse(Objects.requireNonNull(NetworkUtils.getString("https://cdn.jsdelivr.net/gh/KTibow/Skyclient@main/docs/assets/tags.json")).replace('&', ChatColor.COLOR_CHAR)).getAsJsonObject(); Multithreading.runAsync(() -> { try { FileUtils.writeStringToFile(cacheFile, GSON.toJson(rawData), StandardCharsets.UTF_8); diff --git a/src/main/java/co/skyclient/scc/cosmetics/TagPerm.java b/src/main/java/co/skyclient/scc/cosmetics/TagPerm.java index a5eefc1..5d1cfce 100644 --- a/src/main/java/co/skyclient/scc/cosmetics/TagPerm.java +++ b/src/main/java/co/skyclient/scc/cosmetics/TagPerm.java @@ -1,12 +1,11 @@ package co.skyclient.scc.cosmetics; +import cc.polyfrost.oneconfig.utils.NetworkUtils; import com.google.gson.JsonArray; import com.google.gson.JsonElement; -import gg.essential.api.EssentialAPI; +import com.google.gson.JsonObject; import java.util.ArrayList; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; public class TagPerm { private final String identifier; @@ -17,8 +16,8 @@ public class TagPerm { for (JsonElement element : users) { String uuid = element.getAsString(); try { - CompletableFuture profile = EssentialAPI.getMojangAPI().getName(UUID.fromString(uuid.substring(0, 8) + "-" + uuid.substring(8, 12) + "-" + uuid.substring(12, 16) + "-" + uuid.substring(16, 20) + "-" + uuid.substring(20))); - if (profile != null) profiles.add(profile.get()); + String profile = getName(uuid.substring(0, 8) + "-" + uuid.substring(8, 12) + "-" + uuid.substring(12, 16) + "-" + uuid.substring(16, 20) + "-" + uuid.substring(20)); + if (profile != null) profiles.add(profile); } catch (Exception e) { e.printStackTrace(); } @@ -27,6 +26,11 @@ public class TagPerm { this.identifier = identifier; } + public static String getName(String uuid) { + JsonObject object = NetworkUtils.getJsonElement("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid).getAsJsonObject(); + return object.get("name").getAsString(); + } + public ArrayList getUsers() { return users; } diff --git a/src/main/java/co/skyclient/scc/gui/CustomSplashProgress.java b/src/main/java/co/skyclient/scc/gui/CustomSplashProgress.java index ca1c5a1..e67861a 100644 --- a/src/main/java/co/skyclient/scc/gui/CustomSplashProgress.java +++ b/src/main/java/co/skyclient/scc/gui/CustomSplashProgress.java @@ -1,7 +1,7 @@ package co.skyclient.scc.gui; -import gg.essential.api.utils.Multithreading; -import gg.essential.api.utils.WebUtil; +import cc.polyfrost.oneconfig.utils.Multithreading; +import cc.polyfrost.oneconfig.utils.NetworkUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.texture.TextureManager; @@ -186,7 +186,7 @@ public void printStackTrace(final PrintStream s) { Multithreading.runAsync(() -> { try { - String text = WebUtil.fetchString("https://cdn.jsdelivr.net/gh/KTibow/Skyclient@main/docs/assets/funfacts.txt"); + String text = NetworkUtils.getString("https://cdn.jsdelivr.net/gh/KTibow/Skyclient@main/docs/assets/funfacts.txt"); if (text != null) { String[] lines = text.split("\n"); int index = (int) (Math.random() * lines.length); diff --git a/src/main/java/co/skyclient/scc/gui/SkyClientMainMenu.java b/src/main/java/co/skyclient/scc/gui/SkyClientMainMenu.java index ac60753..295725c 100644 --- a/src/main/java/co/skyclient/scc/gui/SkyClientMainMenu.java +++ b/src/main/java/co/skyclient/scc/gui/SkyClientMainMenu.java @@ -1,14 +1,17 @@ package co.skyclient.scc.gui; +import cc.polyfrost.oneconfig.config.Config; +import cc.polyfrost.oneconfig.libs.universal.ChatColor; +import cc.polyfrost.oneconfig.libs.universal.USound; +import cc.polyfrost.oneconfig.utils.NetworkUtils; +import cc.polyfrost.oneconfig.utils.Notifications; +import cc.polyfrost.oneconfig.utils.TickDelay; +import cc.polyfrost.oneconfig.utils.gui.GuiUtils; import co.skyclient.scc.SkyclientCosmetics; import co.skyclient.scc.gui.greeting.IntroductionGreetingSlide; import co.skyclient.scc.gui.greeting.components.GreetingSlide; import co.skyclient.scc.hooks.GuiWinGameHook; import co.skyclient.scc.utils.Files; -import co.skyclient.scc.utils.TickDelay; -import gg.essential.api.EssentialAPI; -import gg.essential.universal.ChatColor; -import gg.essential.universal.USound; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.*; import net.minecraft.client.multiplayer.ServerData; @@ -98,7 +101,25 @@ protected void actionPerformed(GuiButton button) { this.mc.displayGuiScreen(new GuiOptions(this, this.mc.gameSettings)); break; case 5: - this.mc.displayGuiScreen(SkyclientCosmetics.scuConfig.gui()); + if (SkyclientCosmetics.scuConfig != null) { + if (SkyclientCosmetics.scuConfig instanceof Config) { + try { + ((Config) SkyclientCosmetics.scuConfig).openGui(); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + try { + GuiUtils.displayScreen((GuiScreen) Class.forName("gg.essential.vigilance.Vigilant").getDeclaredMethod("gui").invoke(SkyclientCosmetics.scuConfig)); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | + ClassNotFoundException e) { + e.printStackTrace(); + Notifications.INSTANCE.send("SkyClient", "§cFailed to open SkyClient Updater GUI. Please go to inv.wtf/skyclient to fix this issue.", () -> { + NetworkUtils.browseLink("https://inv.wtf/skyclient"); + }); + } + } + } break; case 6: this.mc.shutdown(); @@ -242,14 +263,14 @@ private void renderSkybox(float partialTicks) { @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { if (!Files.greetingFile.exists()) { - new TickDelay(2, () -> { + new TickDelay(() -> { try { Class> clazz = GreetingSlide.Companion.getCurrentSlide(); Minecraft.getMinecraft().displayGuiScreen(clazz != null ? clazz.newInstance() : new IntroductionGreetingSlide()); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } - }); + }, 2); } //background GlStateManager.disableAlpha(); @@ -312,7 +333,7 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { if (isMouseOver) { GuiWinGame gui = new GuiWinGame(); ((GuiWinGameHook) gui).setMainMenu(); - EssentialAPI.getGuiUtil().openScreen(gui); + GuiUtils.displayScreen(gui); USound.INSTANCE.playButtonPress(); } for (int i = 0; i < this.buttonList.size(); ++i) { diff --git a/src/main/java/co/skyclient/scc/hooks/ReplacedModRemover.java b/src/main/java/co/skyclient/scc/hooks/ReplacedModRemover.java index 44a8cfc..bd40066 100644 --- a/src/main/java/co/skyclient/scc/hooks/ReplacedModRemover.java +++ b/src/main/java/co/skyclient/scc/hooks/ReplacedModRemover.java @@ -1,20 +1,30 @@ package co.skyclient.scc.hooks; +import cc.polyfrost.oneconfig.loader.stage0.LaunchWrapperTweaker; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.stream.MalformedJsonException; -import gg.essential.loader.stage0.EssentialSetupTweaker; +import net.minecraft.launchwrapper.ITweaker; import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraftforge.fml.relauncher.CoreModManager; +import org.apache.logging.log4j.LogManager; +import org.spongepowered.asm.launch.MixinBootstrap; +import org.spongepowered.asm.launch.MixinTweaker; import java.io.File; import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.security.CodeSource; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -public class ReplacedModRemover extends EssentialSetupTweaker { +public class ReplacedModRemover extends LaunchWrapperTweaker { private static final JsonParser PARSER = new JsonParser(); @Override @@ -60,6 +70,51 @@ public void injectIntoClassLoader(LaunchClassLoader classLoader) { } catch (Exception e) { e.printStackTrace(); } + + CodeSource codeSource = this.getClass().getProtectionDomain().getCodeSource(); + if (codeSource != null) { + URL location = codeSource.getLocation(); + try { + File file = new File(location.toURI()); + if (file.isFile()) { + CoreModManager.getIgnoredMods().remove(file.getName()); + CoreModManager.getReparseableCoremods().add(file.getName()); + 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 + } + try { + MixinBootstrap.getPlatform().addContainer(location.toURI()); + } catch (Exception ignore) { + // fuck you essential + try { + Class containerClass = Class.forName("org.spongepowered.asm.launch.platform.container.IContainerHandle"); + Class urlContainerClass = Class.forName("org.spongepowered.asm.launch.platform.container.ContainerHandleURI"); + Object container = urlContainerClass.getConstructor(URI.class).newInstance(location.toURI()); + MixinBootstrap.getPlatform().getClass().getDeclaredMethod("addContainer", containerClass).invoke(MixinBootstrap.getPlatform(), container); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("OneConfig's Mixin loading failed. Please contact https://polyfrost.cc/discord to resolve this issue!"); + } + } + } catch (Exception ignored) { + + } + } + } catch (URISyntaxException ignored) {} + } else { + LogManager.getLogger().warn("No CodeSource, if this is not a development environment we might run into problems!"); + LogManager.getLogger().warn(this.getClass().getProtectionDomain()); + } + super.injectIntoClassLoader(classLoader); } diff --git a/src/main/java/co/skyclient/scc/listeners/ChatListeners.java b/src/main/java/co/skyclient/scc/listeners/ChatListeners.java index 23e5005..9765a95 100644 --- a/src/main/java/co/skyclient/scc/listeners/ChatListeners.java +++ b/src/main/java/co/skyclient/scc/listeners/ChatListeners.java @@ -17,18 +17,13 @@ package co.skyclient.scc.listeners; -import co.skyclient.scc.SkyclientCosmetics; +import cc.polyfrost.oneconfig.libs.universal.ChatColor; import co.skyclient.scc.config.Settings; import co.skyclient.scc.cosmetics.Tag; import co.skyclient.scc.cosmetics.TagCosmetics; -import co.skyclient.scc.utils.ChatUtils; import co.skyclient.scc.utils.StringUtils; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import gg.essential.api.utils.Multithreading; -import gg.essential.api.utils.WebUtil; -import gg.essential.universal.ChatColor; -import net.minecraft.client.Minecraft; import net.minecraft.util.ChatComponentText; import net.minecraft.util.IChatComponent; import net.minecraftforge.client.event.ClientChatReceivedEvent; @@ -44,8 +39,6 @@ public class ChatListeners { //TODO: Stop using fucking regexes and make this more modular also optimize this mess - public static Pattern hypixelAPIKeyMsgRegex = Pattern.compile("Your new API key is [0-9a-z]{8}-([0-9a-z]{4}-){3}[0-9a-z]{12}"); - public static Pattern chatRegex = Pattern.compile("((To|From)\\s)?((Guild|Co-op|Officer|Party)\\s\\>\\s)?(\\[(MVP|VIP|PIG|YOUTUBE|MOD|HELPER|ADMIN|OWNER|MOJANG|SLOTH|EVENTS|MCP)([\\+]{1,2})?\\]\\s)?[\\w]+:\\s.*"); public static Pattern dmRegex = Pattern.compile("((To|From)\\s)(\\[(MVP|VIP|PIG|YOUTUBE|MOD|HELPER|ADMIN|OWNER|MOJANG|SLOTH|EVENTS|MCP)([\\+]{1,2})?\\]\\s)?[\\w]+:\\s.*"); public static Pattern groupRegex = Pattern.compile("((Guild|Co-op|Officer|Party)\\s\\>\\s)(\\[(MVP|VIP|PIG|YOUTUBE|MOD|HELPER|ADMIN|OWNER|MOJANG|SLOTH|EVENTS|MCP)([\\+]{1,2})?\\]\\s)?[\\w]+:\\s.*"); @@ -116,37 +109,4 @@ public void onChatMsgTags(ClientChatReceivedEvent event) { } } } - - @SubscribeEvent - public void onChatMsgHpApi(ClientChatReceivedEvent event) { - if (event.type == 0) { - String msg = StringUtils.cleanMessage(event.message.getUnformattedText()); - if (msg.contains("Your new API key is ")) { - Matcher match = hypixelAPIKeyMsgRegex.matcher(msg); - if (match.find()) { - String cleanMsg = match.group(); - String key = cleanMsg.replace("Your new API key is ", ""); - SkyclientCosmetics.LOGGER.info(key); - ChatUtils.sendSystemMessage(ChatColor.GREEN + "Checking API key"); - Multithreading.runAsync(() -> { - try { - JsonObject response = WebUtil.fetchJSON("https://api.hypixel.net/key?key=" + key).getObject(); - - if (response.get("success").getAsBoolean() && response.get("record").getAsJsonObject().get("owner").getAsString().replaceAll("-", "").equals(Minecraft.getMinecraft().getSession().getPlayerID())) { - ChatUtils.sendSystemMessage(ChatColor.GREEN + "Verified API key!"); - Settings.hpApiKey = key; - SkyclientCosmetics.config.markDirty(); - SkyclientCosmetics.config.writeData(); - } else { - ChatUtils.sendSystemMessage(ChatColor.RED + "Couldn't verify \"" + key + "\" as a API key"); - } - - } catch (Exception e) { - ChatUtils.sendSystemMessage(ChatColor.RED + "\"" + key + "\" is not a valid API key"); - } - }); - } - } - } - } } diff --git a/src/main/java/co/skyclient/scc/listeners/GuiListeners.java b/src/main/java/co/skyclient/scc/listeners/GuiListeners.java index 9329f55..12c59d9 100644 --- a/src/main/java/co/skyclient/scc/listeners/GuiListeners.java +++ b/src/main/java/co/skyclient/scc/listeners/GuiListeners.java @@ -20,7 +20,6 @@ import co.skyclient.scc.SkyclientCosmetics; import co.skyclient.scc.config.Settings; import co.skyclient.scc.gui.SkyClientMainMenu; -import gg.essential.api.EssentialAPI; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiIngameMenu; @@ -43,7 +42,7 @@ public void onGuiInitPost(GuiScreenEvent.InitGuiEvent.Post event) { @SubscribeEvent public void onGuiAction(GuiScreenEvent.ActionPerformedEvent.Post event) { if (event.gui instanceof GuiIngameMenu && event.button.id == 2666487) { - EssentialAPI.getGuiUtil().openScreen(SkyclientCosmetics.config.gui()); + SkyclientCosmetics.config.openGui(); } } diff --git a/src/main/java/co/skyclient/scc/listeners/PlayerListeners.java b/src/main/java/co/skyclient/scc/listeners/PlayerListeners.java index f55cbaa..bcf473f 100644 --- a/src/main/java/co/skyclient/scc/listeners/PlayerListeners.java +++ b/src/main/java/co/skyclient/scc/listeners/PlayerListeners.java @@ -17,11 +17,11 @@ package co.skyclient.scc.listeners; +import cc.polyfrost.oneconfig.utils.Notifications; import co.skyclient.scc.SkyclientCosmetics; import co.skyclient.scc.config.Settings; import co.skyclient.scc.cosmetics.Tag; import co.skyclient.scc.cosmetics.TagCosmetics; -import gg.essential.api.EssentialAPI; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent; @@ -31,10 +31,9 @@ public class PlayerListeners { @SubscribeEvent public void onPlayerLoggedIn(FMLNetworkEvent.ClientConnectedToServerEvent event) { if (Settings.joinMessage) { - EssentialAPI.getNotifications().push(SkyclientCosmetics.MOD_NAME, "Welcome to SkyClient Cosmetics!\nType /scc in chat to get started!\nType /api new in chat to set your Hypixel API Key!"); + Notifications.INSTANCE.send(SkyclientCosmetics.MOD_NAME, "Welcome to SkyClient Cosmetics!\nType /scc in chat to get started!\nType /api new in chat to set your Hypixel API Key!"); Settings.joinMessage = false; - SkyclientCosmetics.config.markDirty(); - SkyclientCosmetics.config.writeData(); + SkyclientCosmetics.config.save(); } } diff --git a/src/main/java/co/skyclient/scc/mixins/GuiMainMenuMixin.java b/src/main/java/co/skyclient/scc/mixins/GuiMainMenuMixin.java index 64370e6..d510595 100644 --- a/src/main/java/co/skyclient/scc/mixins/GuiMainMenuMixin.java +++ b/src/main/java/co/skyclient/scc/mixins/GuiMainMenuMixin.java @@ -1,8 +1,8 @@ package co.skyclient.scc.mixins; +import cc.polyfrost.oneconfig.utils.TickDelay; import co.skyclient.scc.gui.greeting.IntroductionGreetingSlide; import co.skyclient.scc.utils.Files; -import co.skyclient.scc.utils.TickDelay; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiMainMenu; import org.spongepowered.asm.mixin.Mixin; @@ -16,7 +16,7 @@ public class GuiMainMenuMixin { @Inject(method = "drawScreen", at = @At("HEAD")) private void onDrawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { if (!Files.greetingFile.exists()) { - new TickDelay(2, () -> Minecraft.getMinecraft().displayGuiScreen(new IntroductionGreetingSlide())); + new TickDelay(() -> Minecraft.getMinecraft().displayGuiScreen(new IntroductionGreetingSlide()), 2); } } } diff --git a/src/main/java/co/skyclient/scc/mixins/MinecraftMixin.java b/src/main/java/co/skyclient/scc/mixins/MinecraftMixin.java index 1d53356..d8ea814 100644 --- a/src/main/java/co/skyclient/scc/mixins/MinecraftMixin.java +++ b/src/main/java/co/skyclient/scc/mixins/MinecraftMixin.java @@ -4,7 +4,7 @@ import co.skyclient.scc.config.Settings; import co.skyclient.scc.gui.SkyClientMainMenu; import co.skyclient.scc.utils.IconLoader; -import gg.essential.api.EssentialAPI; +import co.skyclient.scc.utils.MixinHook; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.GuiScreen; @@ -27,7 +27,7 @@ public abstract class MinecraftMixin { @Inject(method = "displayGuiScreen", at = @At("HEAD"), cancellable = true) private void onDisplayScreen(GuiScreen i, CallbackInfo ci) { if (Settings.customMainMenu) { - if (i instanceof GuiMainMenu && !(i instanceof SkyClientMainMenu) && (EssentialAPI.getOnboardingData().hasAcceptedEssentialTOS() || EssentialAPI.getOnboardingData().hasDeniedEssentialTOS())) { + if (i instanceof GuiMainMenu && !(i instanceof SkyClientMainMenu) && MixinHook.hasEssentialAcceptedTOS()) { ci.cancel(); displayGuiScreen(new SkyClientMainMenu()); } diff --git a/src/main/java/co/skyclient/scc/utils/ChatUtils.java b/src/main/java/co/skyclient/scc/utils/ChatUtils.java index f1e566e..45506f9 100644 --- a/src/main/java/co/skyclient/scc/utils/ChatUtils.java +++ b/src/main/java/co/skyclient/scc/utils/ChatUtils.java @@ -17,8 +17,8 @@ package co.skyclient.scc.utils; -import gg.essential.api.EssentialAPI; -import gg.essential.universal.ChatColor; +import cc.polyfrost.oneconfig.libs.universal.ChatColor; +import cc.polyfrost.oneconfig.libs.universal.UChat; import net.minecraft.client.Minecraft; public class ChatUtils { @@ -27,7 +27,7 @@ public class ChatUtils { public static void sendSystemMessage(String message) { if (mc.theWorld != null) { - EssentialAPI.getMinecraftUtil().sendMessage(ChatColor.DARK_GREEN + "[" + ChatColor.AQUA + "SkyClien" + ChatColor.DARK_AQUA + "'" + ChatColor.AQUA + "t Cosmetics" + ChatColor.DARK_GREEN + "]" + ChatColor.WHITE + ": ", message); + UChat.chat(ChatColor.DARK_GREEN + "[" + ChatColor.AQUA + "SkyClien" + ChatColor.DARK_AQUA + "'" + ChatColor.AQUA + "t Cosmetics" + ChatColor.DARK_GREEN + "]" + ChatColor.WHITE + ": " + message); } } diff --git a/src/main/java/co/skyclient/scc/utils/IconLoader.java b/src/main/java/co/skyclient/scc/utils/IconLoader.java index 8a27b25..e62da2e 100644 --- a/src/main/java/co/skyclient/scc/utils/IconLoader.java +++ b/src/main/java/co/skyclient/scc/utils/IconLoader.java @@ -1,6 +1,6 @@ package co.skyclient.scc.utils; -import gg.essential.universal.UDesktop; +import cc.polyfrost.oneconfig.libs.universal.UDesktop; import javax.imageio.ImageIO; import java.awt.*; diff --git a/src/main/java/co/skyclient/scc/utils/MixinHook.java b/src/main/java/co/skyclient/scc/utils/MixinHook.java new file mode 100644 index 0000000..ca0a03d --- /dev/null +++ b/src/main/java/co/skyclient/scc/utils/MixinHook.java @@ -0,0 +1,10 @@ +package co.skyclient.scc.utils; + +import co.skyclient.scc.SkyclientCosmetics; +import gg.essential.api.EssentialAPI; + +public class MixinHook { + public static boolean hasEssentialAcceptedTOS() { + return !SkyclientCosmetics.isEssential || (EssentialAPI.getOnboardingData().hasAcceptedEssentialTOS() || EssentialAPI.getOnboardingData().hasDeniedEssentialTOS()); + } +} diff --git a/src/main/java/co/skyclient/scc/utils/TickDelay.java b/src/main/java/co/skyclient/scc/utils/TickDelay.java deleted file mode 100644 index fc73485..0000000 --- a/src/main/java/co/skyclient/scc/utils/TickDelay.java +++ /dev/null @@ -1,27 +0,0 @@ -package co.skyclient.scc.utils; - -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; - -public class TickDelay { - private int ticks; - private final Runnable runnable; - - public TickDelay(int ticks, Runnable runnable) { - MinecraftForge.EVENT_BUS.register(this); - this.ticks = ticks; - this.runnable = runnable; - } - - @SubscribeEvent - public void onTick(TickEvent.ClientTickEvent event) { - if (event.phase == TickEvent.Phase.START) { - if (ticks < 1) { - runnable.run(); - MinecraftForge.EVENT_BUS.unregister(this); - } - ticks--; - } - } -} diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/DiscordSlide.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/DiscordSlide.kt index 02f4741..b802293 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/DiscordSlide.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/DiscordSlide.kt @@ -1,12 +1,12 @@ package co.skyclient.scc.gui.greeting import co.skyclient.scc.gui.greeting.components.GreetingSlide -import gg.essential.elementa.components.UIWrappedText -import gg.essential.elementa.constraints.CenterConstraint -import gg.essential.elementa.dsl.* -import gg.essential.universal.ChatColor -import gg.essential.universal.UDesktop -import gg.essential.vigilance.utils.onLeftClick +import cc.polyfrost.oneconfig.libs.elementa.components.UIWrappedText +import cc.polyfrost.oneconfig.libs.elementa.constraints.CenterConstraint +import cc.polyfrost.oneconfig.libs.elementa.dsl.* +import cc.polyfrost.oneconfig.libs.universal.ChatColor +import cc.polyfrost.oneconfig.libs.universal.UDesktop +import co.skyclient.scc.gui.greeting.components.onLeftClick import java.net.URI class DiscordSlide : GreetingSlide(ImportSlide::class.java) { diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/EndSlide.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/EndSlide.kt index 6e30637..348de5f 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/EndSlide.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/EndSlide.kt @@ -1,9 +1,9 @@ package co.skyclient.scc.gui.greeting -import gg.essential.elementa.components.UIText -import gg.essential.elementa.constraints.CenterConstraint -import gg.essential.elementa.constraints.SiblingConstraint -import gg.essential.elementa.dsl.* +import cc.polyfrost.oneconfig.libs.elementa.components.UIText +import cc.polyfrost.oneconfig.libs.elementa.constraints.CenterConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.SiblingConstraint +import cc.polyfrost.oneconfig.libs.elementa.dsl.* import co.skyclient.scc.gui.greeting.components.GreetingSlide import co.skyclient.scc.utils.Files import net.minecraft.client.gui.GuiMainMenu diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/HUDChachySlide.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/HUDChachySlide.kt index 9ac044b..80134fa 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/HUDChachySlide.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/HUDChachySlide.kt @@ -1,15 +1,15 @@ package co.skyclient.scc.gui.greeting import club.sk1er.patcher.config.PatcherConfig -import gg.essential.elementa.components.UIWrappedText -import gg.essential.elementa.constraints.CenterConstraint -import gg.essential.elementa.constraints.SiblingConstraint -import gg.essential.elementa.dsl.* -import gg.essential.universal.ChatColor -import gg.essential.vigilance.gui.settings.ButtonComponent +import cc.polyfrost.oneconfig.libs.elementa.components.UIWrappedText +import cc.polyfrost.oneconfig.libs.elementa.constraints.CenterConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.SiblingConstraint +import cc.polyfrost.oneconfig.libs.elementa.dsl.* +import cc.polyfrost.oneconfig.libs.universal.ChatColor import co.skyclient.scc.gui.greeting.components.CorrectOutsidePixelConstraint import co.skyclient.scc.gui.greeting.components.GreetingSlide import co.skyclient.scc.SkyclientCosmetics +import co.skyclient.scc.gui.greeting.components.ButtonComponent class HUDChachySlide : GreetingSlide(EndSlide::class.java) { init { diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/ImportSlide.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/ImportSlide.kt index 1f35b4a..8e11085 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/ImportSlide.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/ImportSlide.kt @@ -1,15 +1,15 @@ package co.skyclient.scc.gui.greeting -import gg.essential.api.utils.Multithreading -import gg.essential.api.utils.WebUtil -import gg.essential.elementa.components.UIText -import gg.essential.elementa.components.UIWrappedText -import gg.essential.elementa.components.Window -import gg.essential.elementa.constraints.CenterConstraint -import gg.essential.elementa.constraints.SiblingConstraint -import gg.essential.elementa.dsl.* -import gg.essential.universal.ChatColor -import gg.essential.vigilance.gui.settings.ButtonComponent +import cc.polyfrost.oneconfig.libs.elementa.components.UIText +import cc.polyfrost.oneconfig.libs.elementa.components.UIWrappedText +import cc.polyfrost.oneconfig.libs.elementa.components.Window +import cc.polyfrost.oneconfig.libs.elementa.constraints.CenterConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.SiblingConstraint +import cc.polyfrost.oneconfig.libs.elementa.dsl.* +import cc.polyfrost.oneconfig.libs.universal.ChatColor +import cc.polyfrost.oneconfig.utils.Multithreading +import cc.polyfrost.oneconfig.utils.NetworkUtils +import co.skyclient.scc.gui.greeting.components.ButtonComponent import co.skyclient.scc.gui.greeting.components.CorrectOutsidePixelConstraint import co.skyclient.scc.gui.greeting.components.GreetingSlide import com.google.gson.JsonParser @@ -70,7 +70,7 @@ class ImportSlide : GreetingSlide(OptimizationSlide::class.ja progressText.setText("Downloading config locations...") val configLocations = arrayListOf() try { - JsonParser().parse(WebUtil.fetchString("https://raw.githubusercontent.com/SkyblockClient/SkyblockClient-REPO/main/files/config_locations.json")).asJsonArray.forEach { + NetworkUtils.getJsonElement("https://raw.githubusercontent.com/SkyblockClient/SkyblockClient-REPO/main/files/config_locations.json").asJsonArray.forEach { configLocations.add(it.asString) } } catch (e: Exception) { diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/IntroductionGreetingSlide.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/IntroductionGreetingSlide.kt index 923904b..a8a73ad 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/IntroductionGreetingSlide.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/IntroductionGreetingSlide.kt @@ -1,10 +1,10 @@ package co.skyclient.scc.gui.greeting -import gg.essential.elementa.components.UIText -import gg.essential.elementa.constraints.CenterConstraint -import gg.essential.elementa.constraints.SiblingConstraint -import gg.essential.elementa.dsl.* -import gg.essential.universal.UGraphics +import cc.polyfrost.oneconfig.libs.elementa.components.UIText +import cc.polyfrost.oneconfig.libs.elementa.constraints.CenterConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.SiblingConstraint +import cc.polyfrost.oneconfig.libs.elementa.dsl.* +import cc.polyfrost.oneconfig.libs.universal.UGraphics import co.skyclient.scc.gui.greeting.components.GreetingSlide import java.awt.Color diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/OptimizationSlide.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/OptimizationSlide.kt index d3d39e9..e8406df 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/OptimizationSlide.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/OptimizationSlide.kt @@ -5,19 +5,19 @@ import co.skyclient.scc.SkyclientCosmetics import co.skyclient.scc.gui.greeting.components.CorrectOutsidePixelConstraint import co.skyclient.scc.gui.greeting.components.GreetingSlide import co.skyclient.scc.utils.Files -import co.skyclient.scc.utils.TickDelay -import gg.essential.api.EssentialAPI -import gg.essential.api.utils.Multithreading -import gg.essential.elementa.components.UIText -import gg.essential.elementa.components.UIWrappedText -import gg.essential.elementa.components.Window -import gg.essential.elementa.constraints.CenterConstraint -import gg.essential.elementa.constraints.SiblingConstraint -import gg.essential.elementa.dsl.* -import gg.essential.universal.ChatColor -import gg.essential.universal.UDesktop -import gg.essential.vigilance.gui.settings.ButtonComponent -import gg.essential.vigilance.utils.onLeftClick +import cc.polyfrost.oneconfig.libs.elementa.components.UIText +import cc.polyfrost.oneconfig.libs.elementa.components.UIWrappedText +import cc.polyfrost.oneconfig.libs.elementa.components.Window +import cc.polyfrost.oneconfig.libs.elementa.constraints.CenterConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.SiblingConstraint +import cc.polyfrost.oneconfig.libs.elementa.dsl.* +import cc.polyfrost.oneconfig.libs.universal.ChatColor +import cc.polyfrost.oneconfig.libs.universal.UDesktop +import cc.polyfrost.oneconfig.utils.Multithreading +import cc.polyfrost.oneconfig.utils.Notifications +import cc.polyfrost.oneconfig.utils.dsl.tick +import co.skyclient.scc.gui.greeting.components.ButtonComponent +import co.skyclient.scc.gui.greeting.components.onLeftClick import net.minecraft.client.Minecraft import net.minecraft.client.gui.GuiMainMenu import net.minecraft.client.settings.GameSettings @@ -61,7 +61,7 @@ class OptimizationSlide : GreetingSlide(HUDChachySlide::class.ja val yesButton by ButtonComponent("${ChatColor.GREEN}Yes") { progressText.setText("Applying optimized settings... This might take a while...") - TickDelay(2) { + tick(2) { if (isOptifineLoaded()) { try { val settingsClass: Class = mc.gameSettings.javaClass @@ -146,7 +146,7 @@ class OptimizationSlide : GreetingSlide(HUDChachySlide::class.ja mc.gameSettings.loadOptions() mc.refreshResources() mc.renderGlobal.loadRenderers() - TickDelay(2) { + tick(2) { Window.enqueueRenderOperation { displayNextScreen() } } } @@ -180,7 +180,7 @@ class OptimizationSlide : GreetingSlide(HUDChachySlide::class.ja try { property.getInt(Minecraft.getMinecraft().gameSettings).let { if (it == 0 || it == 3) { - EssentialAPI.getNotifications().push("SkyClientCosmetics", "New versions of Patcher fixes the Connected Textures crash on Forge.\n\nClick here to enable Connected Textures!", duration = 10f, action = { + Notifications.INSTANCE.send("SkyClientCosmetics", "New versions of Patcher fixes the Connected Textures crash on Forge.\n\nClick here to enable Connected Textures!", 10000f, Runnable { if (Minecraft.getMinecraft().theWorld != null) { Minecraft.getMinecraft().theWorld.sendQuittingDisconnectingPacket() Minecraft.getMinecraft().loadWorld(null) @@ -195,7 +195,7 @@ class OptimizationSlide : GreetingSlide(HUDChachySlide::class.ja property.setInt(Minecraft.getMinecraft().gameSettings, 2) } catch (e: Exception) { e.printStackTrace() - EssentialAPI.getNotifications().push("SkyClientCosmetics", "Failed to enable Connected Textures! Enable it manually in Options -> Video Settings -> Quality -> Connected Textures.", duration = 10f) + Notifications.INSTANCE.send("SkyClientCosmetics", "Failed to enable Connected Textures! Enable it manually in Options -> Video Settings -> Quality -> Connected Textures.", 10000f) return@addScheduledTask } Minecraft.getMinecraft().gameSettings.saveOptions() diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/components/CorrectOutsidePixelConstraint.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/components/CorrectOutsidePixelConstraint.kt index a9cebde..21a2721 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/components/CorrectOutsidePixelConstraint.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/components/CorrectOutsidePixelConstraint.kt @@ -1,9 +1,9 @@ package co.skyclient.scc.gui.greeting.components -import gg.essential.elementa.UIComponent -import gg.essential.elementa.constraints.ConstraintType -import gg.essential.elementa.constraints.XConstraint -import gg.essential.elementa.constraints.resolution.ConstraintVisitor +import cc.polyfrost.oneconfig.libs.elementa.UIComponent +import cc.polyfrost.oneconfig.libs.elementa.constraints.ConstraintType +import cc.polyfrost.oneconfig.libs.elementa.constraints.XConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.resolution.ConstraintVisitor class CorrectOutsidePixelConstraint( private val value: Float diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/components/GreetingSlide.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/components/GreetingSlide.kt index 201365e..51fa12a 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/components/GreetingSlide.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/components/GreetingSlide.kt @@ -1,20 +1,18 @@ package co.skyclient.scc.gui.greeting.components -import gg.essential.api.utils.Multithreading -import gg.essential.elementa.ElementaVersion -import gg.essential.elementa.WindowScreen -import gg.essential.elementa.components.UIBlock -import gg.essential.elementa.components.UIImage -import gg.essential.elementa.components.UIText -import gg.essential.elementa.components.Window -import gg.essential.elementa.constraints.CenterConstraint -import gg.essential.elementa.constraints.animation.Animations -import gg.essential.elementa.dsl.* -import gg.essential.elementa.utils.withAlpha -import gg.essential.universal.GuiScale -import gg.essential.universal.UMatrixStack -import gg.essential.vigilance.gui.VigilancePalette -import gg.essential.vigilance.gui.settings.ButtonComponent +import cc.polyfrost.oneconfig.libs.elementa.ElementaVersion +import cc.polyfrost.oneconfig.libs.elementa.WindowScreen +import cc.polyfrost.oneconfig.libs.elementa.components.UIBlock +import cc.polyfrost.oneconfig.libs.elementa.components.UIImage +import cc.polyfrost.oneconfig.libs.elementa.components.UIText +import cc.polyfrost.oneconfig.libs.elementa.components.Window +import cc.polyfrost.oneconfig.libs.elementa.constraints.CenterConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.animation.Animations +import cc.polyfrost.oneconfig.libs.elementa.dsl.* +import cc.polyfrost.oneconfig.libs.elementa.utils.withAlpha +import cc.polyfrost.oneconfig.libs.universal.GuiScale +import cc.polyfrost.oneconfig.libs.universal.UMatrixStack +import cc.polyfrost.oneconfig.utils.Multithreading import net.minecraft.client.Minecraft import net.minecraft.client.gui.GuiScreen import java.awt.Color diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/components/HeightRelativeConstraint.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/components/HeightRelativeConstraint.kt index 9295dd9..013d63e 100644 --- a/src/main/kotlin/co/skyclient/scc/gui/greeting/components/HeightRelativeConstraint.kt +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/components/HeightRelativeConstraint.kt @@ -1,12 +1,12 @@ package co.skyclient.scc.gui.greeting.components -import gg.essential.elementa.UIComponent -import gg.essential.elementa.constraints.ConstraintType -import gg.essential.elementa.constraints.HeightConstraint -import gg.essential.elementa.constraints.WidthConstraint -import gg.essential.elementa.constraints.resolution.ConstraintVisitor -import gg.essential.elementa.state.BasicState -import gg.essential.elementa.state.State +import cc.polyfrost.oneconfig.libs.elementa.UIComponent +import cc.polyfrost.oneconfig.libs.elementa.constraints.ConstraintType +import cc.polyfrost.oneconfig.libs.elementa.constraints.HeightConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.WidthConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.resolution.ConstraintVisitor +import cc.polyfrost.oneconfig.libs.elementa.state.BasicState +import cc.polyfrost.oneconfig.libs.elementa.state.State class HeightRelativeConstraint(value: Float) : WidthConstraint, HeightConstraint { override var cachedValue = 0f diff --git a/src/main/kotlin/co/skyclient/scc/gui/greeting/components/VigilanceUtils.kt b/src/main/kotlin/co/skyclient/scc/gui/greeting/components/VigilanceUtils.kt new file mode 100644 index 0000000..54a3cef --- /dev/null +++ b/src/main/kotlin/co/skyclient/scc/gui/greeting/components/VigilanceUtils.kt @@ -0,0 +1,370 @@ +/** + * Taken from Vigilance under LGPL 3.0 + * https://github.com/EssentialGG/Vigilance/blob/master/LICENSE + */ + +package co.skyclient.scc.gui.greeting.components + +import cc.polyfrost.oneconfig.libs.elementa.UIComponent +import cc.polyfrost.oneconfig.libs.elementa.components.* +import cc.polyfrost.oneconfig.libs.elementa.constraints.CenterConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.ChildBasedSizeConstraint +import cc.polyfrost.oneconfig.libs.elementa.constraints.animation.Animations +import cc.polyfrost.oneconfig.libs.elementa.dsl.* +import cc.polyfrost.oneconfig.libs.elementa.effects.Effect +import cc.polyfrost.oneconfig.libs.elementa.effects.ScissorEffect +import cc.polyfrost.oneconfig.libs.elementa.events.UIClickEvent +import cc.polyfrost.oneconfig.libs.elementa.state.BasicState +import cc.polyfrost.oneconfig.libs.elementa.state.State +import cc.polyfrost.oneconfig.libs.elementa.state.toConstraint +import cc.polyfrost.oneconfig.libs.elementa.utils.withAlpha +import cc.polyfrost.oneconfig.libs.universal.UMatrixStack +import cc.polyfrost.oneconfig.libs.universal.USound +import java.awt.Color +import kotlin.math.max +import kotlin.math.pow +import kotlin.math.sqrt + +inline fun UIComponent.onLeftClick(crossinline method: UIComponent.(event: UIClickEvent) -> Unit) = onMouseClick { + if (it.mouseButton == 0) { + this.method(it) + } +} + +class ExpandingClickEffect @JvmOverloads constructor( + private val color: Color, + private val animationTime: Float = 0.2f, + private val scissorBoundingBox: UIComponent? = null +) : Effect() { + + private var state = State.NotActive + private var targetRadius = -1f + private var radiusDelta = -1f + private lateinit var scissorEffect: ScissorEffect + private lateinit var lastClick: UIClickEvent + + private var circle = UICircle(color = color) + + override fun setup() { + scissorEffect = ScissorEffect(scissorBoundingBox ?: boundComponent) + circle effect scissorEffect + Window.enqueueRenderOperation { + circle childOf Window.of(boundComponent) + circle.hide(true) + } + + fun onClickHandler(clickEvent: UIClickEvent) { + lastClick = clickEvent + circle.unhide() + state = State.Expanding + + val left = boundComponent.getLeft() + val top = boundComponent.getTop() + val right = boundComponent.getRight() + val bottom = boundComponent.getBottom() + + val center = clickEvent.absoluteX to clickEvent.absoluteY + targetRadius = max( + max( + distance(center, left to top), distance(center, left to bottom) + ), max( + distance(center, right to top), distance(center, right to bottom) + ) + ) + 2f + radiusDelta = targetRadius / animationTime / Window.of(boundComponent).animationFPS + + circle.constrain { + x = clickEvent.absoluteX.pixels + y = clickEvent.absoluteY.pixels + color = this@ExpandingClickEffect.color.toConstraint() + radius = 0.pixels + } + } + + boundComponent.onLeftClick { onClickHandler(it) } + + circle.onLeftClick { + onClickHandler(it) + } + } + + override fun animationFrame() { + when (state) { + State.NotActive -> {} + State.Expanding -> { + val newRadius = circle.getRadius() + radiusDelta + if (newRadius >= targetRadius) { + state = State.Expanded + } else { + circle.setRadius(newRadius.pixels) + } + } + + State.Expanded -> { + val currentColor = circle.getColor() + val alpha = currentColor.alpha - 2 + if (alpha <= 0) { + state = State.NotActive + targetRadius = -1f + radiusDelta = -1f + circle.hide(true) + } else { + circle.setColor(currentColor.withAlpha(alpha).toConstraint()) + } + } + } + } + + override fun beforeDraw(matrixStack: UMatrixStack) { + if (state != State.NotActive) circle.draw(matrixStack) + } + + enum class State { + NotActive, Expanding, Expanded, + } + + companion object { + private fun distance(p1: Pair, p2: Pair) = + sqrt((p1.first - p2.first).pow(2f) + (p1.second - p2.second).pow(2f)) + } +} + +abstract class SettingComponent : UIContainer() { + + private var onValueChange: (Any?) -> Unit = {} + private var lastValue: Any? = null + + init { + constrain { + x = (13f + 10f).pixels(alignOpposite = true) + y = CenterConstraint() + } + } + + fun onValueChange(listener: (Any?) -> Unit) { + this.onValueChange = listener + } + + fun changeValue(newValue: Any?, callListener: Boolean = true) { + if (newValue != lastValue) { + lastValue = newValue + this.onValueChange(newValue) + } + } + + open fun closePopups(instantly: Boolean = false) {} + + open fun setupParentListeners(parent: UIComponent) {} + + companion object { + const val DOWN_ARROW_PNG = "/vigilance/arrow-down.png" + const val UP_ARROW_PNG = "/vigilance/arrow-up.png" + } +} + +class ButtonComponent(placeholder: String? = null, private val callback: () -> Unit) : SettingComponent() { + + private var textState: State = BasicState(placeholder.orEmpty().ifEmpty { "Activate" }) + private var listener: () -> Unit = textState.onSetValue { + text.setText(textState.get()) + } + + private val container by UIBlock(VigilancePalette.button).constrain { + width = ChildBasedSizeConstraint() + 14.pixels + height = ChildBasedSizeConstraint() + 8.pixels + } childOf this + + private val text by UIWrappedText( + textState.get(), + trimText = true, + shadowColor = VigilancePalette.getTextShadow() + ).constrain { + x = CenterConstraint() + y = CenterConstraint() + width = width.coerceAtMost(300.pixels) + height = 10.pixels + color = VigilancePalette.text.toConstraint() + } childOf container + + init { + constrain { + width = ChildBasedSizeConstraint() + height = ChildBasedSizeConstraint() + } + + enableEffect(ExpandingClickEffect(VigilancePalette.getPrimary().withAlpha(0.5f), scissorBoundingBox = container)) + + container.onMouseEnter { + container.animate { + setColorAnimation(Animations.OUT_EXP, 0.5f, VigilancePalette.buttonHighlight.toConstraint()) + } + }.onMouseLeave { + container.animate { + setColorAnimation(Animations.OUT_EXP, 0.5f, VigilancePalette.button.toConstraint()) + } + }.onLeftClick { + USound.playButtonPress() + callback() + } + } + + fun bindText(newTextState: State) = apply { + listener() + textState = newTextState + text.bindText(textState) + + listener = textState.onSetValue { + text.setText(textState.get()) + } + } + + fun getText() = textState.get() + fun setText(text: String) = apply { textState.set(text) } +} + +object VigilancePalette { + fun getPrimary(): Color = primary.get() + fun getBackground(): Color = backgroundState.get() + fun getButton(): Color = button.get() + fun getButtonHighlight(): Color = buttonHighlight.get() + fun getText(): Color = text.get() + fun getTextHighlight(): Color = textHighlight.get() + fun getTextShadow(): Color = textShadow.get() + fun getTextDisabled(): Color = textDisabled.get() + fun getComponentBackground(): Color = componentBackground.get() + + // These are marked as internal because ideally the user is only changing the colours in the settings gui + // Old + internal val brightDividerState = BasicState(Color.BLACK) + internal val dividerState = BasicState(Color.BLACK) + internal val darkDividerState = BasicState(Color.BLACK) + internal val outlineState = BasicState(Color.BLACK) + internal val scrollBarState = BasicState(Color.BLACK) + internal val brightHighlightState = BasicState(Color.BLACK) + internal val highlightState = BasicState(Color.BLACK) + internal val darkHighlightState = BasicState(Color.BLACK) + internal val lightBackgroundState = BasicState(Color.BLACK) + internal val backgroundState = BasicState(Color.BLACK) + internal val darkBackgroundState = BasicState(Color.BLACK) + internal val searchBarBackgroundState = BasicState(Color.BLACK) + internal val brightTextState = BasicState(Color.BLACK) + internal val midTextState = BasicState(Color.BLACK) + internal val darkTextState = BasicState(Color.BLACK) + internal val modalBackgroundState = BasicState(Color.BLACK) + internal val warningState = BasicState(Color.BLACK) + internal val accentState = BasicState(Color.BLACK) + internal val successState = BasicState(Color.BLACK) + internal val transparentState = BasicState(Color.BLACK) + internal val disabledState = BasicState(Color.BLACK) + internal val bgNoAlpha = BasicState(Color.BLACK) + + internal val primary = BasicState(Color.BLACK) + internal val button = BasicState(Color.BLACK) + internal val buttonHighlight = BasicState(Color.BLACK) + internal val text = BasicState(Color.BLACK) + internal val textHighlight = BasicState(Color.WHITE) + internal val textShadow = BasicState(Color.BLACK) + internal val textDisabled = BasicState(Color.BLACK) + internal val componentBackground = BasicState(Color.BLACK) + + // Old + private var brightDivider = Color(151, 151, 151) + private var divider = Color(80, 80, 80) + private var darkDivider = Color(50, 50, 50) + private var outline = Color(48, 48, 49) + private var scrollBar = Color(45, 45, 45) + private var brightHighlight = Color(50, 50, 50) + private var highlight = Color(33, 34, 38) + private var darkHighlight = Color(27, 28, 33) + private var lightBackground = Color(32, 32, 33) + private var background = Color(22, 22, 24) + private var darkBackground = Color(10, 10, 11) + private var searchBarBackground = Color(27, 28, 33) + private var brightText = Color(255, 255, 255) + private var midText = Color(187, 187, 187) + private var darkText = Color(119, 119, 121) + private var modalBackground = Color(0, 0, 0, 100) + private var warning = Color(239, 83, 80) + private var accent = Color(1, 165, 82) + private var success = Color(1, 165, 82) + private var transparent = Color(0, 0, 0, 0) + private var disabled = Color(80, 80, 80) + + private var primaryA = Color(0x2997FF) + private var buttonA = Color(0x323232) + private var buttonHighlightA = Color(0x474747) + private var textA = Color(0xBBBBBB) + private var textHighlightA = Color(0xFFFFFF) + private var textShadowA = Color(0x161618) + private var textDisabledA = Color(0x6A6A6A) + private var componentBackgroundA = Color(0x232323) + + init { + setAllInPalette() + } + + internal fun setAllInPalette() { + brightDividerState.set(brightDivider) + dividerState.set(divider) + darkDividerState.set(darkDivider) + outlineState.set(outline) + scrollBarState.set(scrollBar) + brightHighlightState.set(brightHighlight) + highlightState.set(highlight) + darkHighlightState.set(darkHighlight) + lightBackgroundState.set(lightBackground) + backgroundState.set(background) + darkBackgroundState.set(darkBackground) + searchBarBackgroundState.set(searchBarBackground) + brightTextState.set(brightText) + midTextState.set(midText) + darkTextState.set(darkText) + modalBackgroundState.set(modalBackground) + warningState.set(warning) + accentState.set(accent) + successState.set(success) + transparentState.set(transparent) + disabledState.set(disabled) + bgNoAlpha.set(background.withAlpha(0)) + + primary.set(primaryA) + button.set(buttonA) + buttonHighlight.set(buttonHighlightA) + text.set(textA) + textHighlight.set(textHighlightA) + textShadow.set(textShadowA) + textDisabled.set(textDisabledA) + componentBackground.set(componentBackgroundA) + } + + /* Utilities for colors */ + internal fun getTextColor(hovered: State, enabled: State): State { + return hovered.zip(enabled).map { (hovered, enabled) -> + if (enabled) { + if (hovered) { + getTextHighlight() + } else { + getText() + } + } else { + getTextDisabled() + } + } + } + + internal fun getTextColor(hovered: State): State = getTextColor(hovered, BasicState(true)) + + internal fun getButtonColor(hovered: State, enabled: State): State { + return hovered.zip(enabled).map { (hovered, enabled) -> + if (enabled) { + if (hovered) { + getButtonHighlight() + } else { + getButton() + } + } else { + getComponentBackground() + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/scc/SkyClient.png b/src/main/resources/assets/scc/SkyClient.png new file mode 100644 index 0000000..0defde5 Binary files /dev/null and b/src/main/resources/assets/scc/SkyClient.png differ diff --git a/versions/mainProject b/versions/mainProject new file mode 100644 index 0000000..dd1433e --- /dev/null +++ b/versions/mainProject @@ -0,0 +1 @@ +1.8.9-forge \ No newline at end of file