From 7bca358c4b4c4326559759d1d41ff1d0dba948d0 Mon Sep 17 00:00:00 2001 From: brachy84 Date: Mon, 27 Jan 2025 10:36:47 +0100 Subject: [PATCH] update mui to 2.5 rc3 --- build.gradle | 294 +++++++++++++++++- dependencies.gradle | 2 +- .../bogosorter/common/config/ConfigGui.java | 155 +++++---- 3 files changed, 358 insertions(+), 93 deletions(-) diff --git a/build.gradle b/build.gradle index 8ea7b057..892add04 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1707682661 +//version: 1723428048 /* * DO NOT CHANGE THIS FILE! * Also, you may replace this file at any time if there is an update available. @@ -7,14 +7,24 @@ */ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.gtnewhorizons.retrofuturagradle.MinecraftExtension +import com.gtnewhorizons.retrofuturagradle.mcp.MCPTasks +import com.gtnewhorizons.retrofuturagradle.minecraft.MinecraftTasks import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar +import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask +import com.gtnewhorizons.retrofuturagradle.util.Distribution import com.modrinth.minotaur.dependencies.ModDependency import com.modrinth.minotaur.dependencies.VersionDependency +import de.undercouch.gradle.tasks.download.DownloadExtension +import org.apache.commons.io.FileUtils +import org.gradle.api.internal.artifacts.configurations.DefaultUnlockedConfiguration import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent import org.gradle.internal.logging.text.StyledTextOutputFactory import org.jetbrains.gradle.ext.Gradle +import javax.inject.Inject + import static org.gradle.internal.logging.text.StyledTextOutput.Style plugins { @@ -23,9 +33,9 @@ plugins { id 'base' id 'eclipse' id 'maven-publish' - id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.7' - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.33' - id 'net.darkhax.curseforgegradle' version '1.1.18' apply false + id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.8' + id 'com.gtnewhorizons.retrofuturagradle' version '1.4.0' + id 'net.darkhax.curseforgegradle' version '1.1.24' apply false id 'com.modrinth.minotaur' version '2.8.7' apply false id 'com.diffplug.spotless' version '6.13.0' apply false id 'com.palantir.git-version' version '3.0.0' apply false @@ -33,6 +43,7 @@ plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false + id 'de.undercouch.download' version '5.6.0' apply false } def out = services.get(StyledTextOutputFactory).create('an-output') @@ -58,6 +69,8 @@ propertyDefaultIfUnset("includeMCVersionJar", false) propertyDefaultIfUnset("autoUpdateBuildScript", false) propertyDefaultIfUnset("modArchivesBaseName", project.modId) propertyDefaultIfUnsetWithEnvVar("developmentEnvironmentUserName", "Developer", "DEV_USERNAME") +propertyDefaultIfUnset("additionalJavaArguments", "") +propertyDefaultIfUnset("enableJava17RunTasks", false) propertyDefaultIfUnset("generateGradleTokenClass", "") propertyDefaultIfUnset("gradleTokenModId", "") propertyDefaultIfUnset("gradleTokenModName", "") @@ -65,8 +78,10 @@ propertyDefaultIfUnset("gradleTokenVersion", "") propertyDefaultIfUnset("useSrcApiPath", false) propertyDefaultIfUnset("includeWellKnownRepositories", true) propertyDefaultIfUnset("includeCommonDevEnvMods", true) +propertyDefaultIfUnset("stripForgeRequirements", false) propertyDefaultIfUnset("noPublishedSources", false) propertyDefaultIfUnset("forceEnableMixins", false) +propertyDefaultIfUnset("mixinConfigRefmap", "mixins.${project.modId}.refmap.json") propertyDefaultIfUnsetWithEnvVar("enableCoreModDebug", false, "CORE_MOD_DEBUG") propertyDefaultIfUnset("generateMixinConfig", true) propertyDefaultIfUnset("usesShadowedDependencies", false) @@ -107,7 +122,7 @@ if (!getFile(targetPackageJava).exists() && !getFile(targetPackageScala).exists( if (apiPackage) { final String endApiPath = modGroupPath + '/' + apiPackagePath - if (useSrcApiPath) { + if (useSrcApiPath.toBoolean()) { targetPackageJava = 'src/api/java/' + endApiPath targetPackageScala = 'src/api/scala/' + endApiPath targetPackageKotlin = 'src/api/kotlin/' + endApiPath @@ -369,6 +384,14 @@ minecraft { '-Dlegacy.debugClassLoadingSave=true' ]) } + + if (additionalJavaArguments.size() != 0) { + extraRunJvmArguments.addAll(additionalJavaArguments.split(';')) + } + + if (enableJava17RunTasks.toBoolean()) { + lwjgl3Version = "3.3.2" + } } if (coreModClass) { @@ -504,7 +527,7 @@ dependencies { // should use 2.8.6 but 2.8.9+ has a vulnerability fix annotationProcessor 'com.google.code.gson:gson:2.8.9' - mixinProviderSpec = modUtils.enableMixins(mixinProviderSpec, "mixins.${modId}.refmap.json") + mixinProviderSpec = modUtils.enableMixins(mixinProviderSpec, mixinConfigRefmap) api (mixinProviderSpec) { transitive = false } @@ -546,6 +569,10 @@ dependencies { transitive = false } + if ((usesMixins.toBoolean() || forceEnableMixins.toBoolean()) && stripForgeRequirements.toBoolean()) { + runtimeOnlyNonPublishable 'com.cleanroommc:strip-latest-forge-requirements:1.0' + } + if (includeCommonDevEnvMods.toBoolean()) { if (!(modId.equals('jei'))) { implementation 'mezz.jei:jei_1.12.2:4.16.1.302' @@ -679,7 +706,6 @@ tasks.register('generateAssets') { if (usesMixins.toBoolean() && generateMixinConfig.toBoolean()) { def mixinConfigFile = getFile("src/main/resources/mixins.${modId}.json") if (!mixinConfigFile.exists()) { - def mixinConfigRefmap = "mixins.${modId}.refmap.json" mixinConfigFile.text = """{ "package": "${modGroup}.${mixinsPackage}", @@ -820,6 +846,218 @@ def getManifestAttributes() { } +// LWJGL3ify setup +if (enableJava17RunTasks.toBoolean()) { + + apply plugin: 'de.undercouch.download' + + ext.java17Toolchain = (JavaToolchainSpec spec) -> { + spec.languageVersion.set(JavaLanguageVersion.of(17)) + spec.vendor.set(JvmVendorSpec.matching("jetbrains")) + } + ext.java21Toolchain = (JavaToolchainSpec spec) -> { + spec.languageVersion.set(JavaLanguageVersion.of(21)) + spec.vendor.set(JvmVendorSpec.matching("jetbrains")) + } + + ext.java17DependenciesCfg = (DefaultUnlockedConfiguration) configurations.create("java17Dependencies") { + extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution + canBeConsumed = false + } + ext.java17PatchDependenciesCfg = (DefaultUnlockedConfiguration) configurations.create("java17PatchDependencies") { + canBeConsumed = false + } + + dependencies { + if (modId != 'lwjgl3ify') { + java17Dependencies("io.github.twilightflower:lwjgl3ify:1.0.0") + } + java17PatchDependencies("io.github.twilightflower:lwjgl3ify:1.0.0:forgePatches") { + transitive = false + } + } + + ext.java17JvmArgs = [ + "-Dfile.encoding=UTF-8", + "-Djava.system.class.loader=com.gtnewhorizons.retrofuturabootstrap.RfbSystemClassLoader", + "-Djava.security.manager=allow", + "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", + "--add-opens", "java.base/java.net=ALL-UNNAMED", + "--add-opens", "java.base/java.nio=ALL-UNNAMED", + "--add-opens", "java.base/java.io=ALL-UNNAMED", + "--add-opens", "java.base/java.lang=ALL-UNNAMED", + "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", + "--add-opens", "java.base/java.text=ALL-UNNAMED", + "--add-opens", "java.base/java.util=ALL-UNNAMED", + "--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED", + "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", + "--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming", + "--add-opens", "java.desktop/sun.awt=ALL-UNNAMED", + "--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED", + "--add-opens", "java.desktop/com.sun.imageio.plugins.png=ALL-UNNAMED", + "--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED", + "--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED" + ] + + ext.hotswapJvmArgs = [ + // DCEVM advanced hot reload + "-XX:+AllowEnhancedClassRedefinition", + "-XX:HotswapAgent=fatjar" + ] + + ext.setupHotswapAgent17 = tasks.register("setupHotswapAgent17", SetupHotswapAgentTask, t -> { + t.setTargetForToolchain(java17Toolchain) + }) + + ext.setupHotswapAgent21 = tasks.register("setupHotswapAgent21", SetupHotswapAgentTask, t -> { + t.setTargetForToolchain(java21Toolchain) + }) + + def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") + runClient17Task.configure { + dependsOn(setupHotswapAgent17) + setup(project) + javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) + } + + def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") + runServer17Task.configure { + dependsOn(setupHotswapAgent17) + setup(project) + javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) + } + + def runClient21Task = tasks.register("runClient21", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") + runClient21Task.configure { + dependsOn(setupHotswapAgent21) + setup(project) + javaLauncher = project.javaToolchains.launcherFor(project.java21Toolchain) + } + + def runServer21Task = tasks.register("runServer21", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") + runServer21Task.configure { + dependsOn(setupHotswapAgent21) + setup(project) + javaLauncher = project.javaToolchains.launcherFor(project.java21Toolchain) + } +} + +abstract class RunHotswappableMinecraftTask extends RunMinecraftTask { + + // IntelliJ doesn't seem to allow pre-set commandline arguments, so we also support an env variable + private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP")) + + public final Distribution side + public final String superTask + + @Input + boolean getEnableHotswap() { + return enableHotswap + } + + @Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger") + boolean setEnableHotswap(boolean enable) { + enableHotswap = enable + } + + @Inject + RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) { + super(side, gradle) + + this.side = side + this.superTask = superTask + setGroup("Modded Minecraft") + setDescription("Runs the modded " + side.name().toLowerCase(Locale.ROOT) + " using modern Java and lwjgl3ify") + this.getLwjglVersion().set(3) + } + + void setup(Project project) { + final MinecraftExtension minecraft = project.getExtensions().getByType(MinecraftExtension.class) + final MCPTasks mcpTasks = project.getExtensions().getByType(MCPTasks.class) + final MinecraftTasks mcTasks = project.getExtensions().getByType(MinecraftTasks.class) + + this.getExtraJvmArgs().addAll((List) project.property("java17JvmArgs")) + if (getEnableHotswap()) { + this.getExtraJvmArgs().addAll((List) project.property("hotswapJvmArgs")) + } + + this.classpath(project.property("java17PatchDependenciesCfg")) + this.classpath(mcpTasks.getTaskPackageMcLauncher()) + this.classpath(mcpTasks.getTaskPackagePatchedMc()) + this.classpath(mcpTasks.getPatchedConfiguration()) + this.classpath(project.getTasks().named("jar")) + this.classpath(project.property("java17DependenciesCfg")) + + super.setup(project) + + dependsOn( + mcpTasks.getLauncherSources().getClassesTaskName(), + mcTasks.getTaskDownloadVanillaAssets(), + mcpTasks.getTaskPackagePatchedMc(), + "jar" + ) + + getMainClass().set((side == Distribution.CLIENT) ? "GradleStart" : "GradleStartServer") + getUsername().set(minecraft.getUsername()) + getUserUUID().set(minecraft.getUserUUID()) + if (side == Distribution.DEDICATED_SERVER) { + getExtraArgs().add("nogui") + } + + systemProperty("gradlestart.bouncerClient", "com.gtnewhorizons.retrofuturabootstrap.Main") + systemProperty("gradlestart.bouncerServer", "com.gtnewhorizons.retrofuturabootstrap.Main") + + if (project.usesMixins.toBoolean()) { + this.extraJvmArgs.addAll(project.provider(() -> { + def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec)) + mixinCfg.canBeConsumed = false + mixinCfg.canBeResolved = true + mixinCfg.transitive = false + enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : [] + })) + } + } +} + +abstract class SetupHotswapAgentTask extends DefaultTask { + + @OutputFile + abstract RegularFileProperty getTargetFile() + + void setTargetForToolchain(Action spec) { + getTargetFile().set(project.javaToolchains.launcherFor(spec).map { + it.metadata.installationPath.file("lib/hotswap/hotswap-agent.jar") + }) + } + + @Inject + SetupHotswapAgentTask() { + setGroup("GT Buildscript") + setDescription("Installs a recent version of HotSwapAgent into the Java runtime directory") + onlyIf("Run only if not already installed", t -> !((SetupHotswapAgentTask) t).getTargetFile().getAsFile().get().exists()) + } + + @TaskAction + void installHSA() { + final String url = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar' + final File target = getTargetFile().getAsFile().get() + final File parent = target.getParentFile() + FileUtils.forceMkdir(parent) + final DownloadExtension download = getProject().getExtensions().findByType(DownloadExtension.class) + download.run(ds -> { + try { + ds.src(url) + } catch (MalformedURLException e) { + throw new RuntimeException(e) + } + ds.dest(target) + ds.overwrite(false) + ds.tempAndMove(true) + }) + } +} + + // IDE Configuration eclipse { @@ -844,9 +1082,25 @@ idea { '2. Run Client'(Gradle) { taskNames = ['runClient'] } + if (enableJava17RunTasks.toBoolean()) { + '2a. Run Client (Java 17)'(Gradle) { + taskNames = ['runClient17'] + } + '2b. Run Client (Java 21)'(Gradle) { + taskNames = ['runClient21'] + } + } '3. Run Server'(Gradle) { taskNames = ['runServer'] } + if (enableJava17RunTasks.toBoolean()) { + '3a. Run Server (Java 17)'(Gradle) { + taskNames = ['runServer17'] + } + '3b. Run Server (Java 21)'(Gradle) { + taskNames = ['runServer21'] + } + } '4. Run Obfuscated Client'(Gradle) { taskNames = ['runObfClient'] } @@ -983,6 +1237,30 @@ if (cfApiKey.isPresent() || deploymentDebug.toBoolean()) { additionalFile.changelog = changelogRaw } } + doLast { + // No File IDs in Debug Mode + if (!deploymentDebug.toBoolean()) { + def list = [] + for (def artifact : tasks.curseforge.getUploadArtifacts()) { + list.add(artifact) + for (def additionalArtifact : artifact.getAdditionalArtifacts()) { + list.add(additionalArtifact) + } + } + def summary = "## CurseForge Build Summary (Mod ${modName} | Project ID ${curseForgeProjectId})" + for (def artifact : list) { + def fileId = artifact.getCurseFileId() + def fileName = artifact.getArtifact().getSingleFile().name + println("Uploaded File ${fileName}, With File ID: ${fileId}") + summary = summary + "\n - File: ${fileName} | File ID: ${fileId}" + } + println(summary) + def stepSummary = providers.environmentVariable("GITHUB_STEP_SUMMARY") + if (stepSummary.isPresent()) { + file(stepSummary.get()).write(summary) + } + } + } } tasks.curseforge.dependsOn(build) tasks.curseforge.dependsOn('generateChangelog') @@ -1113,7 +1391,7 @@ def getChangelog() { // Buildscript updating -def buildscriptGradleVersion = '8.5' +def buildscriptGradleVersion = '8.9' tasks.named('wrapper', Wrapper).configure { gradleVersion = buildscriptGradleVersion diff --git a/dependencies.gradle b/dependencies.gradle index ad00570a..cc37a4fe 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -38,7 +38,7 @@ * For more details, see https://docs.gradle.org/8.4/userguide/java_library_plugin.html#sec:java_library_configurations_graph */ dependencies { - implementation("com.cleanroommc:modularui:2.4.2") { transitive false } + implementation("com.cleanroommc:modularui:2.5.0-rc3") { transitive false } //implementation files('libs/modularui-2.2.3-dev.jar') // for testing purpose compileOnly rfg.deobf('curse.maven:iron_chests-228756:2747935') compileOnly rfg.deobf('curse.maven:cofh_core-69162:2920433') diff --git a/src/main/java/com/cleanroommc/bogosorter/common/config/ConfigGui.java b/src/main/java/com/cleanroommc/bogosorter/common/config/ConfigGui.java index afa7fab6..3fe54634 100644 --- a/src/main/java/com/cleanroommc/bogosorter/common/config/ConfigGui.java +++ b/src/main/java/com/cleanroommc/bogosorter/common/config/ConfigGui.java @@ -7,6 +7,7 @@ import com.cleanroommc.bogosorter.common.HotbarSwap; import com.cleanroommc.bogosorter.common.SortConfigChangeEvent; import com.cleanroommc.bogosorter.common.sort.NbtSortRule; +import com.cleanroommc.modularui.api.IPanelHandler; import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.api.widget.IWidget; @@ -17,12 +18,15 @@ import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.ModularScreen; import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.screen.viewport.ModularGuiContext; import com.cleanroommc.modularui.theme.Theme; +import com.cleanroommc.modularui.theme.ThemeAPI; import com.cleanroommc.modularui.utils.Alignment; import com.cleanroommc.modularui.utils.Color; import com.cleanroommc.modularui.value.BoolValue; import com.cleanroommc.modularui.value.IntValue; import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widget.Widget; import com.cleanroommc.modularui.widgets.*; import com.cleanroommc.modularui.widgets.layout.Grid; import com.cleanroommc.modularui.widgets.layout.Row; @@ -63,7 +67,7 @@ public ConfigGui(GuiScreen old) { } @Override - public @NotNull ModularPanel buildUI(GuiContext guiContext) { + public @NotNull ModularPanel buildUI(ModularGuiContext context) { this.availableElements = new Object2ObjectOpenHashMap<>(); this.availableElementsNbt = new Object2ObjectOpenHashMap<>(); ModularPanel panel = new ModularPanel("bogo_config") { @@ -87,8 +91,8 @@ public boolean shouldAnimate() { .controller(controller) .left(4).right(4) .top(35).bottom(4) - .addPage(createGeneralConfigUI(guiContext)) - .addPage(createProfilesConfig(guiContext))) + .addPage(createGeneralConfigUI(panel, context)) + .addPage(createProfilesConfig(panel, context))) .child(new Row() .left(4).right(4) .height(16).top(18) @@ -103,7 +107,7 @@ public boolean shouldAnimate() { return panel; } - public IWidget createGeneralConfigUI(GuiContext context) { + public IWidget createGeneralConfigUI(ModularPanel mainPanel, ModularGuiContext context) { Row row = new Row(); return new ListWidget<>() .left(5).right(5).top(2).bottom(2) @@ -116,7 +120,7 @@ public IWidget createGeneralConfigUI(GuiContext context) { .margin(0, 2) .child(new CycleButtonWidget() .value(new BoolValue.Dynamic(() -> PlayerConfig.getClient().enableAutoRefill, val -> PlayerConfig.getClient().enableAutoRefill = val)) - .texture(TOGGLE_BUTTON) + .stateOverlay(TOGGLE_BUTTON) .disableHoverBackground() .size(14, 14) .margin(8, 0) @@ -146,11 +150,10 @@ public IWidget createGeneralConfigUI(GuiContext context) { .margin(0, 2) .child(new CycleButtonWidget() .value(new BoolValue.Dynamic(HotbarSwap::isEnabled, HotbarSwap::setEnabled)) - .texture(TOGGLE_BUTTON) + .stateOverlay(TOGGLE_BUTTON) .disableHoverBackground() .addTooltipLine(IKey.lang("bogosort.gui.hotbar_scrolling.tooltip")) .tooltipShowUpTimer(10) - .excludeTooltipArea(row.getArea()) .size(14, 14) .margin(8, 0) .background(IDrawable.EMPTY)) @@ -158,11 +161,11 @@ public IWidget createGeneralConfigUI(GuiContext context) { .marginLeft(10) .height(14) .addTooltipLine(IKey.lang("bogosort.gui.hotbar_scrolling.tooltip")) - .tooltipShowUpTimer(10) - .excludeTooltipArea(row.getArea()))); + .tooltipShowUpTimer(10))); + } - public IWidget createProfilesConfig(GuiContext context) { + public IWidget createProfilesConfig(ModularPanel mainPanel, ModularGuiContext context) { PagedWidget.Controller controller = new PagedWidget.Controller(); return new ParentWidget<>() .widthRel(1f).top(2).bottom(0) @@ -194,13 +197,40 @@ public IWidget createProfilesConfig(GuiContext context) { .controller(controller) .left(90).right(0) .top(16).bottom(0) - .addPage(createItemSortConfigUI(context)) - .addPage(createNbtSortConfigUI(context))); + .addPage(createItemSortConfigUI(mainPanel, context)) + .addPage(createNbtSortConfigUI(mainPanel, context))); } - public IWidget createItemSortConfigUI(GuiContext context) { + private static > Map> getSortListItemMap(Iterable it) { + final Map> items = new Object2ObjectOpenHashMap<>(); + for (T sortRule : it) { + items.put(sortRule, new SortableListWidget.Item<>(sortRule).child(item -> new Row() + .child(new Widget<>() + .addTooltipLine(IKey.lang(sortRule.getDescriptionLangKey())) + .widgetTheme(Theme.BUTTON) + //.background(GuiTextures.BUTTON_CLEAN) + .overlay(IKey.lang(sortRule.getNameLangKey())) + .expanded().heightRel(1f)) + .child(new CycleButtonWidget() + .value(new BoolValue.Dynamic(sortRule::isInverted, sortRule::setInverted)) + .stateOverlay(ARROW_DOWN_UP) + .addTooltip(0, IKey.lang("bogosort.gui.descending")) + .addTooltip(1, IKey.lang("bogosort.gui.ascending")) + .heightRel(1f).width(14)) + .child(new ButtonWidget<>() + .onMousePressed(button -> item.removeSelfFromList()) + .overlay(GuiTextures.CROSS_TINY.asIcon().size(10)) + .width(10).heightRel(1f)))); + } + return items; + } + + public IWidget createItemSortConfigUI(ModularPanel mainPanel, ModularGuiContext context) { List> allValues = BogoSortAPI.INSTANCE.getItemSortRuleList(); - AtomicReference, SortListItem>>> ref = new AtomicReference<>(null); + final Map, SortableListWidget.Item>> items = getSortListItemMap(allValues); + SortableListWidget> sortableListWidget = new SortableListWidget>() + .children(BogoSorterConfig.sortRules, items::get) + .debugName("sortable item list"); List> availableMatrix = Grid.mapToMatrix(2, allValues, (index, value) -> { AvailableElement availableElement = new AvailableElement() .overlay(IKey.lang(value.getNameLangKey())) @@ -208,7 +238,7 @@ public IWidget createItemSortConfigUI(GuiContext context) { .size(80, 14) .onMousePressed(mouseButton1 -> { if (this.availableElements.get(value).available) { - ref.get().add(value, -1); + sortableListWidget.child(items.get(value)); this.availableElements.get(value).available = false; } return true; @@ -220,14 +250,15 @@ public IWidget createItemSortConfigUI(GuiContext context) { this.availableElements.get(value).available = !BogoSorterConfig.sortRules.contains(value); } - SortableListWidget, SortListItem>> sortableListWidget = SortableListWidget.sortableBuilder(allValues, BogoSorterConfig.sortRules, s -> { - TextWidget ruleText = IKey.lang(s.getNameLangKey()).asWidget().widgetTheme(Theme.BUTTON); - return new SortListItem<>(s, ruleText - .paddingLeft(7) - .background(GuiTextures.MC_BUTTON) - .tooltip(tooltip -> tooltip.addLine(IKey.lang(s.getDescriptionLangKey())).showUpTimer(10).excludeArea(ruleText.getArea()))); - }); - ref.set(sortableListWidget); + IPanelHandler secPanel = IPanelHandler.simple(mainPanel, (parentPanel, player) -> { + ModularPanel panel = ModularPanel.defaultPanel("choose_item_rules", 200, 140); + return panel.child(ButtonWidget.panelCloseButton()) + .child(new Grid() + .matrix(availableMatrix) + .scrollable() + .pos(7, 7).right(17).bottom(7)); + }, true); + return new ParentWidget<>() .sizeRel(1f, 1f) .child(sortableListWidget @@ -243,29 +274,17 @@ public IWidget createItemSortConfigUI(GuiContext context) { .bottom(7).size(12, 12).leftRel(0.5f) .overlay(GuiTextures.ADD) .onMousePressed(mouseButton -> { - if (!isPanelOpen("choose_item_rules")) { - ModularPanel panel1 = ModularPanel.defaultPanel("choose_item_rules", 200, 140); - openPanel(panel1 - .child(new ButtonWidget<>() - .size(8, 8) - .top(4).right(4) - .overlay(GuiTextures.CLOSE) - .onMousePressed(mouseButton1 -> { - panel1.animateClose(); - return true; - })) - .child(new Grid() - .matrix(availableMatrix) - .scrollable() - .pos(7, 7).right(17).bottom(7))); - } + secPanel.openPanel(); return true; })); } - public IWidget createNbtSortConfigUI(GuiContext context) { + public IWidget createNbtSortConfigUI(ModularPanel mainPanel, ModularGuiContext context) { List allValues = BogoSortAPI.INSTANCE.getNbtSortRuleList(); - AtomicReference>> ref = new AtomicReference<>(null); + final Map> items = getSortListItemMap(allValues); + SortableListWidget sortableListWidget = new SortableListWidget() + .children(BogoSorterConfig.nbtSortRules, items::get) + .debugName("sortable nbt list"); List> availableMatrix = Grid.mapToMatrix(2, allValues, (index, value) -> { AvailableElement availableElement = new AvailableElement() .overlay(IKey.lang(value.getNameLangKey())) @@ -273,7 +292,7 @@ public IWidget createNbtSortConfigUI(GuiContext context) { .size(80, 14) .onMousePressed(mouseButton1 -> { if (this.availableElementsNbt.get(value).available) { - ref.get().add(value, -1); + sortableListWidget.child(items.get(value)); this.availableElementsNbt.get(value).available = false; } return true; @@ -285,14 +304,15 @@ public IWidget createNbtSortConfigUI(GuiContext context) { this.availableElementsNbt.get(value).available = !BogoSorterConfig.nbtSortRules.contains(value); } - SortableListWidget> sortableListWidget = SortableListWidget.sortableBuilder(allValues, BogoSorterConfig.nbtSortRules, s -> { - TextWidget ruleText = IKey.lang(s.getNameLangKey()).asWidget().widgetTheme(Theme.BUTTON); - return new SortListItem<>(s, ruleText - .paddingLeft(7) - .background(GuiTextures.MC_BUTTON) - .tooltip(tooltip -> tooltip.addLine(IKey.lang(s.getDescriptionLangKey())).showUpTimer(10).excludeArea(ruleText.getArea()))); - }); - ref.set(sortableListWidget); + IPanelHandler secPanel = IPanelHandler.simple(mainPanel, (parentPanel, player) -> { + ModularPanel panel = ModularPanel.defaultPanel("choose_nbt_rules", 200, 140); + return panel.child(ButtonWidget.panelCloseButton()) + .child(new Grid() + .matrix(availableMatrix) + .scrollable() + .pos(7, 7).right(17).bottom(7)); + }, true); + return new ParentWidget<>() .sizeRel(1f, 1f) .child(sortableListWidget @@ -308,22 +328,7 @@ public IWidget createNbtSortConfigUI(GuiContext context) { .bottom(7).size(12, 12).leftRel(0.5f) .overlay(GuiTextures.ADD) .onMousePressed(mouseButton -> { - if (!isPanelOpen("choose_nbt_rules")) { - ModularPanel panel1 = ModularPanel.defaultPanel("choose_nbt_rules", 200, 140); - openPanel(panel1 - .child(new ButtonWidget<>() - .size(8, 8) - .top(4).right(4) - .overlay(GuiTextures.CLOSE) - .onMousePressed(mouseButton1 -> { - panel1.animateClose(); - return true; - })) - .child(new Grid() - .matrix(availableMatrix) - .scrollable() - .pos(7, 7).right(17).bottom(7))); - } + secPanel.openPanel(); return true; })); } @@ -341,24 +346,6 @@ public void onClose() { } } - private static class SortListItem> extends SortableListWidget.Item { - - private final IWidget ascendingToggle; - - public SortListItem(T value, IWidget content) { - super(value, content); - this.ascendingToggle = new CycleButtonWidget() - .value(new BoolValue.Dynamic(getWidgetValue()::isInverted, getWidgetValue()::setInverted)) - .texture(ARROW_DOWN_UP) - .addTooltip(0, IKey.lang("bogosort.gui.descending")) - .addTooltip(1, IKey.lang("bogosort.gui.ascending")) - .heightRel(1f).width(14).pos(0, 0); - content.flex().left(14).right(10); - removeable(buttonWidget -> buttonWidget.background(GuiTextures.MC_BUTTON).overlay(GuiTextures.CLOSE.asIcon().size(8, 8))); - getChildren().add(this.ascendingToggle); - } - } - private static class AvailableElement extends ButtonWidget { private boolean available = true;