diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c7d542..db34967 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,8 @@ jobs: # Check out current repository - name: Fetch Sources uses: actions/checkout@v2.4.0 + with: + submodules: 'true' # Validate wrapper - name: Gradle Wrapper Validation diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 087eeb5..70ac9ed 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,6 +15,7 @@ jobs: - name: Fetch Sources uses: actions/checkout@v2.4.0 with: + submodules: 'true' ref: ${{ github.event.release.tag_name }} # Setup Java 17 environment for the next steps diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0291a6c..5d54d4c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,8 @@ jobs: steps: - name: checkout repository uses: actions/checkout@v2 + with: + submodules: 'true' - name: validate gradle wrapper uses: gradle/wrapper-validation-action@v1 - name: setup jdk 17 @@ -16,7 +18,10 @@ jobs: - name: make gradle wrapper executable run: chmod +x ./gradlew - name: test - run: ./gradlew test + run: | + mkdir -p core/run + mkdir -p run + ./gradlew test - name: Publish Unit Test Results uses: EnricoMi/publish-unit-test-result-action@v1 if: always() diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b0f9584 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "core"] + path = core + url = https://github.com/ModManagerMC/core.git diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 71397c4..0000000 --- a/build.gradle +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//file:noinspection GroovyAssignabilityCheck -//file:noinspection GroovyAccessibility -plugins { - id "fabric-loom" version "0.10-SNAPSHOT" - id "com.modrinth.minotaur" version "1.2.1" - id "org.jetbrains.kotlin.jvm" version "1.5.30" - id "org.jetbrains.changelog" version "1.3.1" - id "org.jetbrains.kotlin.plugin.serialization" version "1.5.30" -} - -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 - -archivesBaseName = project.archives_base_name -version = project.mod_version -group = project.maven_group - -repositories { - maven { - name = "TerraformersMC" - url = "https://maven.terraformersmc.com/releases/" - } - mavenCentral() -} - -dependencies { - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - - modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}" - modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}" - - testImplementation 'org.jetbrains.kotlin:kotlin-test:1.5.31' -} - -processResources { - inputs.property "version", project.version - inputs.property "releaseTarget", project.release_target - inputs.property "modmenu_version", project.modmenu_version - - filesMatching("fabric.mod.json") { - expand project.properties - } - filesMatching("build.info") { - expand project.properties - } -} - -test { - useJUnitPlatform() -} - -tasks.withType(JavaCompile).configureEach { - it.options.encoding = "UTF-8" - // Minecraft 1.17 (21w19a) upwards uses Java 16. - it.options.release = 16 -} - -compileKotlin { - kotlinOptions.jvmTarget = "16" - kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" -} - -compileTestKotlin { - kotlinOptions.jvmTarget = "16" - kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" -} - -java { - withSourcesJar() -} - -jar { - from("LICENSE") { - rename { "${it}_${project.archivesBaseName}" } - } -} - -task zip(type: Zip, dependsOn: remapJar) { - from remapJar -} -build.finalizedBy(zip) - - -import com.modrinth.minotaur.TaskModrinthUpload -import com.modrinth.minotaur.request.Dependency -import com.modrinth.minotaur.request.VersionType - -task publishModrinth(type: TaskModrinthUpload, dependsOn: remapJar) { - onlyIf { - System.getenv("MODRINTH") - } - - token = System.getenv("MODRINTH") - projectId = "6kq7BzRK" - versionNumber = version - uploadFile = remapJar - versionType = VersionType.RELEASE - addGameVersion(project.release_target) - addLoader("fabric") - addDependency("JPP6w2U1", Dependency.DependencyType.REQUIRED) // Mod Menu - addDependency("1qsZV7U7", Dependency.DependencyType.REQUIRED) // fabric-language-kotlin - changelog = this.changelog.getUnreleased().withHeader(false).toText() -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..372e95b --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,58 @@ +plugins { + kotlin("jvm") + kotlin("plugin.serialization") + id("fabric-loom") +} + +group = "net.modmanagermc" +version = "2.0.0" + +repositories { + maven("https://maven.fabricmc.net") { + name = "Fabric" + } + maven("https://maven.terraformersmc.com/") { + name = "Terraformers" + } + mavenCentral() +} + +val minecraftVersion: String by project +val yarnMappings: String by project +val loaderVersion: String by project +val fabricKotlinVersion: String by project + +dependencies { + minecraft("com.mojang:minecraft:$minecraftVersion") + mappings("net.fabricmc:yarn:$yarnMappings:v2") + + modImplementation("net.fabricmc:fabric-loader:${loaderVersion}") + modImplementation("com.terraformersmc:modmenu:3.2.1") + includeMod("net.fabricmc:fabric-language-kotlin:${fabricKotlinVersion}") + includeProject(project(":core")) +} + +fun DependencyHandler.includeMod(dependencyNotation: Any) { + modImplementation(dependencyNotation) + include(dependencyNotation) +} + +fun DependencyHandler.includeProject(dependencyNotation: Any) { + implementation(dependencyNotation) + include(dependencyNotation) +} + +tasks.getByName("processResources") { + filesMatching("fabric.mod.json") { + expand( + mutableMapOf( + "version" to version, + "fabricKotlinVersion" to fabricKotlinVersion + ) + ) + } +} + +tasks.withType { + kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" +} \ No newline at end of file diff --git a/core b/core new file mode 160000 index 0000000..85ab0c8 --- /dev/null +++ b/core @@ -0,0 +1 @@ +Subproject commit 85ab0c81e00d0cd9862d9485818d83a4ac4f9952 diff --git a/gradle.properties b/gradle.properties index f12b923..6014fd9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,30 +1,10 @@ -# -# Copyright 2021 DeathsGun -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -org.gradle.jvmargs=-Xms2G -Xmx4G -# Fabric Properties -# check this on https://modmuss50.me/fabric.html -release_target=1.18 -minecraft_version=1.18.1 -yarn_mappings=1.18.1+build.17 -loader_version=0.12.12 -# Mod Properties -mod_version=1.2.3+1.18 -maven_group=xyz.deathsgun -archives_base_name=modmanager -# Dependencies -modmenu_version=3.0.0 -# Kotlin -fabric_kotlin_version=1.6.4+kotlin.1.5.30 \ No newline at end of file +kotlin.code.style=official +org.gradle.jvmargs=-Xmx2G + +loomVersion=0.12-SNAPSHOT +minecraftVersion=1.18.2 +yarnMappings=1.18.2+build.3 +loaderVersion=0.14.9 +fabricKotlinVersion=1.8.2+kotlin.1.7.10 + +kotlinVersion=1.7.10 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180..41d9927 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e750102..41dfb87 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.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index c6f3882..0000000 --- a/settings.gradle +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -pluginManagement { - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - gradlePluginPortal() - } -} -rootProject.name = "modmanager" diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..5416987 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + maven("https://maven.fabricmc.net") { + name = "Fabric" + } + gradlePluginPortal() + } + val kotlinVersion: String by settings + val loomVersion: String by settings + plugins { + kotlin("jvm") version kotlinVersion + kotlin("plugin.serialization") version kotlinVersion + id("fabric-loom") version loomVersion + } +} +rootProject.name = "modmanager" + +include("core") diff --git a/src/main/java/net/modmanagermc/modmanager/mixin/MinecraftClientMixin.java b/src/main/java/net/modmanagermc/modmanager/mixin/MinecraftClientMixin.java new file mode 100644 index 0000000..9e9fe11 --- /dev/null +++ b/src/main/java/net/modmanagermc/modmanager/mixin/MinecraftClientMixin.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.mixin; + +import net.minecraft.client.MinecraftClient; +import net.modmanagermc.core.task.TaskManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin { + + @Inject(method = "render", at = {@At("HEAD")}) + public void onRender(boolean tick, CallbackInfo ci) { + TaskManager.INSTANCE.executeTasks(); + } + +} diff --git a/src/main/java/net/modmanagermc/modmanager/mixin/ModMenuTexturedButtonWidgetMixin.java b/src/main/java/net/modmanagermc/modmanager/mixin/ModMenuTexturedButtonWidgetMixin.java new file mode 100644 index 0000000..df85193 --- /dev/null +++ b/src/main/java/net/modmanagermc/modmanager/mixin/ModMenuTexturedButtonWidgetMixin.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.mixin; + +import com.terraformersmc.modmenu.gui.widget.ModMenuTexturedButtonWidget; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * Remove modget's button from ModsScreen + */ +@Mixin(ModMenuTexturedButtonWidget.class) +public abstract class ModMenuTexturedButtonWidgetMixin extends ButtonWidget { + + @Shadow + @Final + private Identifier texture; + + public ModMenuTexturedButtonWidgetMixin(int x, int y, int width, int height, Text message, PressAction onPress) { + super(x, y, width, height, message, onPress); + } + + @Inject(method = "renderButton", at = @At("HEAD"), cancellable = true) + public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (texture.equals(new Identifier("modget", "textures/gui/install_button.png"))) { + ci.cancel(); + } + } + + @Override + public void onPress() { + if (texture.equals(new Identifier("modget", "textures/gui/install_button.png"))) { + return; + } + super.onPress(); + } +} diff --git a/src/main/java/net/modmanagermc/modmanager/mixin/ModsScreenMixin.java b/src/main/java/net/modmanagermc/modmanager/mixin/ModsScreenMixin.java new file mode 100644 index 0000000..2b6a920 --- /dev/null +++ b/src/main/java/net/modmanagermc/modmanager/mixin/ModsScreenMixin.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.mixin; + +import com.terraformersmc.modmenu.gui.ModsScreen; +import com.terraformersmc.modmenu.gui.widget.ModMenuTexturedButtonWidget; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Identifier; +import net.modmanagermc.modmanager.gui.ModManagerListScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Objects; + +@Mixin(ModsScreen.class) +public abstract class ModsScreenMixin extends Screen { + + private static final Identifier MODMANAGER_BUTTON_LOCATION = new Identifier("modmanager", "textures/gui/install_button.png"); + private static final TranslatableText MODMANAGER_BUTTON_OPTIONS = new TranslatableText("modmanager.button.open"); + @Shadow + private int paneWidth; + + @Shadow + protected abstract void setTooltip(Text tooltip); + + protected ModsScreenMixin(Text title) { + super(title); + } + + @Inject(method = "init", at = @At("TAIL")) + public void onInit(CallbackInfo ci) { + int searchBoxWidth = paneWidth - 32 - 22; + + this.addDrawableChild(new ModMenuTexturedButtonWidget(paneWidth / 2 + searchBoxWidth / 2 - 20 / 2 + 2 + 22, 22, 20, 20, + 0, 0, MODMANAGER_BUTTON_LOCATION, 32, 64, + button -> Objects.requireNonNull(client).setScreen(new ModManagerListScreen(this)), MODMANAGER_BUTTON_OPTIONS, + (buttonWidget, matrices, mouseX, mouseY) -> { + ModMenuTexturedButtonWidget button = (ModMenuTexturedButtonWidget) buttonWidget; + if (button.isJustHovered()) { + this.renderTooltip(matrices, MODMANAGER_BUTTON_OPTIONS, mouseX, mouseY); + } else if (button.isFocusedButNotHovered()) { + this.renderTooltip(matrices, MODMANAGER_BUTTON_OPTIONS, button.x, button.y); + } + })); + } + +} diff --git a/src/main/java/xyz/deathsgun/modmanager/ModMenuEntrypoint.java b/src/main/java/xyz/deathsgun/modmanager/ModMenuEntrypoint.java deleted file mode 100644 index 9133635..0000000 --- a/src/main/java/xyz/deathsgun/modmanager/ModMenuEntrypoint.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager; - -import com.terraformersmc.modmenu.api.ConfigScreenFactory; -import com.terraformersmc.modmenu.api.ModMenuApi; -import xyz.deathsgun.modmanager.gui.ConfigScreen; - -public class ModMenuEntrypoint implements ModMenuApi { - @Override - public ConfigScreenFactory getModConfigScreenFactory() { - return ConfigScreen::new; - } -} diff --git a/src/main/java/xyz/deathsgun/modmanager/mixin/ModsScreenMixin.java b/src/main/java/xyz/deathsgun/modmanager/mixin/ModsScreenMixin.java deleted file mode 100644 index c40634a..0000000 --- a/src/main/java/xyz/deathsgun/modmanager/mixin/ModsScreenMixin.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.mixin; - -import com.terraformersmc.modmenu.gui.ModsScreen; -import com.terraformersmc.modmenu.gui.widget.ModMenuTexturedButtonWidget; -import com.terraformersmc.modmenu.gui.widget.entries.ModListEntry; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import xyz.deathsgun.modmanager.ModManager; -import xyz.deathsgun.modmanager.config.Config; -import xyz.deathsgun.modmanager.gui.ModsOverviewScreen; -import xyz.deathsgun.modmanager.gui.widget.TexturedButton; - -import java.util.Map; - -@Mixin(ModsScreen.class) -public abstract class ModsScreenMixin extends Screen { - - private static final Identifier MODMANAGER_BUTTON_LOCATION = new Identifier("modmanager", "textures/gui/install_button.png"); - private static final Identifier MODMANAGER_HIDE_BUTTON = new Identifier("modmanager", "textures/gui/hide_button.png"); - private static final Identifier MODMANAGER_SHOW_BUTTON = new Identifier("modmanager", "textures/gui/show_button.png"); - @Shadow - private int paneWidth; - @Shadow - private int paneY; - - @Shadow - private ModListEntry selected; - - @Shadow - public abstract Map getModHasConfigScreen(); - - private TexturedButton hideButton; - - protected ModsScreenMixin(Text title) { - super(title); - } - - @Inject(method = "init", at = @At("TAIL")) - public void onInit(CallbackInfo ci) { - int searchBoxWidth = this.paneWidth - 32 - 22; - this.addDrawableChild(new ModMenuTexturedButtonWidget(this.paneWidth / 2 + searchBoxWidth / 2 + 14, - 22, 20, 20, 0, 0, MODMANAGER_BUTTON_LOCATION, 32, 64, - button -> MinecraftClient.getInstance().setScreen(new ModsOverviewScreen(this)), LiteralText.EMPTY, - (button, matrices, mouseX, mouseY) -> { - if (!button.isHovered()) { - return; - } - this.renderTooltip(matrices, new TranslatableText("modmanager.button.open"), mouseX, mouseY); - })); - this.hideButton = this.addDrawableChild(new TexturedButton(width - 24 - 22, paneY, 20, 20, 0, - 0, MODMANAGER_HIDE_BUTTON, 32, 64, button -> { - if (ModManager.modManager.getConfig().getHidden().contains(selected.getMod().getId())) { - ModManager.modManager.getConfig().getHidden().remove(selected.getMod().getId()); - } else { - ModManager.modManager.getConfig().getHidden().add(selected.getMod().getId()); - } - Config.Companion.saveConfig(ModManager.modManager.getConfig()); - }, ((button, matrices, mouseX, mouseY) -> { - if (!hideButton.isJustHovered() || !button.isHovered()) { - return; - } - TranslatableText text = new TranslatableText("modmanager.button.hide"); - if (ModManager.modManager.getConfig().getHidden().contains(selected.getMod().getId())) { - text = new TranslatableText("modmanager.button.show"); - } - this.renderTooltip(matrices, text, mouseX, mouseY); - }))); - } - - @Inject(method = "tick", at = @At("HEAD")) - public void onTick(CallbackInfo ci) { - this.hideButton.visible = ModManager.modManager.getUpdate().getUpdates() - .stream().anyMatch(it -> it.getFabricId().equalsIgnoreCase(selected.mod.getId())); - if (ModManager.modManager.getConfig().getHidden().contains(selected.getMod().getId())) { - this.hideButton.setImage(MODMANAGER_SHOW_BUTTON); - } else { - this.hideButton.setImage(MODMANAGER_HIDE_BUTTON); - } - this.hideButton.x = getModHasConfigScreen().getOrDefault(selected.getMod().getId(), false) ? width - 24 - 22 : width - 24; - } - -} diff --git a/src/main/kotlin/net/modmanagermc/modmanager/ModManagerEntrypoint.kt b/src/main/kotlin/net/modmanagermc/modmanager/ModManagerEntrypoint.kt new file mode 100644 index 0000000..40528c2 --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/ModManagerEntrypoint.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021-2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager + +import net.fabricmc.api.ClientModInitializer +import net.minecraft.util.Language +import net.modmanagermc.core.Core +import net.modmanagermc.core.update.IUpdateService +import net.modmanagermc.modmanager.icon.IconCache + +object ModManagerEntrypoint : ClientModInitializer { + override fun onInitializeClient() { + Core.init() + Core.di.bind { IconCache() } + val cache: IconCache by Core.di + cache.cleanupCache() + val updateService: IUpdateService by Core.di + updateService.checkUpdate() + } +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ErrorScreen.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/ErrorScreen.kt similarity index 70% rename from src/main/kotlin/xyz/deathsgun/modmanager/gui/ErrorScreen.kt rename to src/main/kotlin/net/modmanagermc/modmanager/gui/ErrorScreen.kt index 002709c..186f940 100644 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ErrorScreen.kt +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/ErrorScreen.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 DeathsGun + * Copyright (c) 2021-2022 DeathsGun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package xyz.deathsgun.modmanager.gui +package net.modmanagermc.modmanager.gui import net.minecraft.client.font.MultilineText import net.minecraft.client.gui.DrawableHelper @@ -22,20 +22,19 @@ import net.minecraft.client.gui.screen.Screen import net.minecraft.client.gui.screen.ScreenTexts import net.minecraft.client.gui.widget.ButtonWidget import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.LiteralText +import net.minecraft.text.Text import net.minecraft.text.TranslatableText import net.minecraft.util.math.MathHelper +import net.modmanagermc.core.exceptions.ModManagerException -class ErrorScreen( - private val previousScreen: Screen, - private val actionScreen: Screen, - private val error: TranslatableText -) : - Screen(TranslatableText("modmanager.error.title")) { +class ErrorScreen(private val parenScreen: Screen, private val exception: Exception) : Screen(TranslatableText("modmanager.error.title")) { private lateinit var text: MultilineText override fun init() { - this.text = MultilineText.create(this.textRenderer, this.error, this.width - 50) + exception.printStackTrace() + this.text = MultilineText.create(this.textRenderer, this.exception.toErrorMessage(), this.width - 50) val linesHeight = this.text.count() * 9 val bottom = MathHelper.clamp(90 + linesHeight + 12, this.height / 6 + 69, this.height - 24) addDrawableChild( @@ -46,7 +45,7 @@ class ErrorScreen( 20, ScreenTexts.BACK ) { - client!!.setScreen(previousScreen) + client!!.setScreen(parenScreen) } ) addDrawableChild( @@ -57,20 +56,32 @@ class ErrorScreen( 20, TranslatableText("modmanager.button.tryAgain") ) { - client!!.setScreen(actionScreen) + //TODO: Try again action + client!!.setScreen(parenScreen) } ) } override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { - super.renderBackground(matrices) + renderBackgroundTexture(0) DrawableHelper.drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 70, 16777215) this.text.drawCenterWithShadow(matrices, this.width / 2, 90) super.render(matrices, mouseX, mouseY, delta) } + override fun close() { + client!!.setScreen(parenScreen) + } + override fun shouldCloseOnEsc(): Boolean { return false } + private fun Exception.toErrorMessage(): Text { + if (this !is ModManagerException) { + return LiteralText(exception.message) + } + return TranslatableText(this.translationId, this.args) + } + } \ No newline at end of file diff --git a/src/main/kotlin/net/modmanagermc/modmanager/gui/ModInfoScreen.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/ModInfoScreen.kt new file mode 100644 index 0000000..f74f057 --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/ModInfoScreen.kt @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021-2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.gui + +import com.mojang.blaze3d.systems.RenderSystem +import com.terraformersmc.modmenu.util.DrawingUtil +import net.minecraft.client.MinecraftClient +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.screen.ScreenTexts +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.* +import net.modmanagermc.core.Core +import net.modmanagermc.core.controller.ModInfoController +import net.modmanagermc.core.model.Category +import net.modmanagermc.core.model.Mod +import net.modmanagermc.core.screen.IListScreen +import net.modmanagermc.core.task.TaskManager +import net.modmanagermc.modmanager.gui.widgets.DescriptionWidget +import net.modmanagermc.modmanager.gui.widgets.ProgressWidget +import net.modmanagermc.modmanager.icon.IconCache +import net.modmanagermc.modmanager.md.Markdown +import kotlin.math.roundToInt + +class ModInfoScreen(private val parentScreen: Screen, mod: Mod) : Screen(LiteralText.EMPTY), ModInfoController.View, + IListScreen { + + private val iconCache: IconCache by Core.di + private val controller = ModInfoController(mod, this) + private lateinit var loadingBar: ProgressWidget + private lateinit var actionButton: ButtonWidget + private lateinit var descriptionWidget: DescriptionWidget + + override fun init() { + loadingBar = ProgressWidget( + client!!, + width / 8, + (height * 0.5).roundToInt(), + (width * 0.75).roundToInt(), + 5, + TranslatableText("modmanager.details.loading", controller.mod.name), + true, + ) + loadingBar.visible = true + + val buttonX = width / 8 + actionButton = addDrawableChild(ButtonWidget( + this.width - buttonX - 150, + this.height - 28, + 150, + 20, + TranslatableText("modmanager.button.install") + ) { + controller.doAction() + }) + controller.init() + + descriptionWidget = addSelectableChild( + DescriptionWidget( + client!!, + width - 20, + height - 34, + 79, + height - 30, + textRenderer.fontHeight, + this, + controller.mod.fullDescription ?: controller.mod.description + ) + ) + descriptionWidget.setLeftPos(10) + addDrawableChild(ButtonWidget(buttonX, height - 28, 150, 20, ScreenTexts.BACK) { + client!!.setScreen(parentScreen) + }) + } + + override fun render(matrices: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) { + renderBackgroundTexture(0) + if (loadingBar.visible) { + loadingBar.render(matrices, mouseX, mouseY, delta) + return + } + descriptionWidget.render(matrices, mouseX, mouseY, delta) + + val iconSize = 64 + iconCache.bindIcon(controller.mod) + RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f) + RenderSystem.enableBlend() + drawTexture(matrices, 20, 10, 0.0f, 0.0f, iconSize, iconSize, iconSize, iconSize) + RenderSystem.disableBlend() + + val font = client!!.textRenderer + + var trimmedTitle: MutableText = LiteralText(font.trimToWidth(controller.mod.name, width - 200)) + trimmedTitle = trimmedTitle.setStyle(Style.EMPTY.withBold(true)) + + var detailsY = 15F + var textX = 20 + iconSize + 5F + + font.draw(matrices, trimmedTitle, textX, detailsY, 0xFFFFFF) + + detailsY += 12 + DrawingUtil.drawBadge( + matrices, textX.toInt(), detailsY.toInt(), + font.getWidth(controller.mod.license) + 6, + Text.of(controller.mod.license).asOrderedText(), + -0x909396, -0xcecfd1, 0xCACACA + ) + + for (category in controller.mod.categories) { + val textWidth: Int = font.getWidth(category.text()) + 6 + DrawingUtil.drawBadge( + matrices, + textX.toInt(), + (detailsY + 14).toInt(), + textWidth, + category.text().asOrderedText(), + -0x909396, + -0xcecfd1, + 0xCACACA + ) + textX += textWidth + 4 + } + super.render(matrices, mouseX, mouseY, delta) + } + + override fun tick() { + if (controller.mod.fullDescription != null && descriptionWidget.text == controller.mod.description) { + descriptionWidget.updateText(controller.mod.fullDescription ?: controller.mod.description) + } + loadingBar.tick() + controller.tick() + } + + override fun close() { + client!!.setScreen(parentScreen) + } + + override fun updateSelectedEntry(widget: Any, entry: E?) { + } + + override fun updateMultipleEntries(widget: Any, entries: ArrayList) { + } + + override fun updateActionText(translationId: String) { + actionButton.message = TranslatableText(translationId) + } + + override fun error(e: Exception) = TaskManager.add { + client!!.setScreen(ErrorScreen(parentScreen, e)) + } + + override fun setLoading(loading: Boolean) { + loadingBar.visible = loading + } + + private fun Category.text(): TranslatableText { + return TranslatableText(translationId) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/modmanagermc/modmanager/gui/ModManagerListScreen.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/ModManagerListScreen.kt new file mode 100644 index 0000000..3e5adb4 --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/ModManagerListScreen.kt @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2021-2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.gui + +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.screen.ScreenTexts +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.client.gui.widget.TextFieldWidget +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.LiteralText +import net.minecraft.text.TranslatableText +import net.modmanagermc.core.Core +import net.modmanagermc.core.controller.ModListController +import net.modmanagermc.core.model.Category +import net.modmanagermc.core.model.Mod +import net.modmanagermc.core.screen.IListScreen +import net.modmanagermc.core.store.Sort +import net.modmanagermc.core.task.TaskManager +import net.modmanagermc.modmanager.gui.widgets.CategoryListWidget +import net.modmanagermc.modmanager.gui.widgets.CyclingButtonWidget +import net.modmanagermc.modmanager.gui.widgets.ModListWidget +import net.modmanagermc.modmanager.gui.widgets.ProgressWidget +import net.modmanagermc.modmanager.icon.IconCache +import kotlin.math.roundToInt + +class ModManagerListScreen(private val parentScreen: Screen) : Screen(LiteralText.EMPTY), IListScreen, + ModListController.View { + + private val cache: IconCache by Core.di + private val controller = ModListController(this) + private lateinit var modList: ModListWidget + private lateinit var categoryList: CategoryListWidget + private lateinit var searchField: TextFieldWidget + private lateinit var nextPage: ButtonWidget + private lateinit var previousPage: ButtonWidget + private lateinit var sortingButtonWidget: CyclingButtonWidget + private lateinit var loadingBar: ProgressWidget + + override fun init() { + loadingBar = ProgressWidget( + client!!, + width / 8, + (height * 0.5).roundToInt(), + (width * 0.75).roundToInt(), + 5, + TranslatableText("modmanager.list.loading"), + true, + ) + loadingBar.visible = false + + client!!.keyboard.setRepeatEvents(true) + + searchField = addSelectableChild( + TextFieldWidget( + textRenderer, + 10, + 10, + 160, + 20, + TranslatableText("modmanager.field.search") + ) + ) + searchField.setChangedListener { controller.query = it } + + sortingButtonWidget = addDrawableChild( + CyclingButtonWidget( + 175, + 10, + 120, + 20, + "modmanager.sorting.sort", + Sort::translation, + Sort.values(), + Sort.DOWNLOADS + ) { sorting: Sort -> controller.sorting = sorting; controller.search() }) + + categoryList = addSelectableChild( + CategoryListWidget( + client!!, + 120, + height, + 35, + height - 30, + client!!.textRenderer.fontHeight + 4, + this, + ) + ) + categoryList.setLeftPos(10) + + modList = addSelectableChild(ModListWidget(client!!, width - 5 - 135, height, 35, height - 30, 36, this)) + modList.setLeftPos(135) + + addDrawableChild(ButtonWidget(10, height - 25, 120, 20, ScreenTexts.BACK) { + close() + }) + + val buttonWidth = (width - 135 - 10) / 2 + + previousPage = addDrawableChild( + ButtonWidget( + 135, + height - 25, + buttonWidth, + 20, + TranslatableText("modmanager.button.previous") + ) { + controller.previousPage() + modList.scrollAmount = 0.0 + }) + nextPage = addDrawableChild( + ButtonWidget( + 135 + buttonWidth + 5, + height - 25, + buttonWidth, + 20, + TranslatableText("modmanager.button.next") + ) { + controller.nextPage() + modList.scrollAmount = 0.0 + }) + + controller.init() + } + + override fun render(matrices: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) { + renderBackgroundTexture(0) + if (loadingBar.visible) { + loadingBar.render(matrices, mouseX, mouseY, delta) + return + } + modList.render(matrices, mouseX, mouseY, delta) + categoryList.render(matrices, mouseX, mouseY, delta) + searchField.render(matrices, mouseX, mouseY, delta) + super.render(matrices, mouseX, mouseY, delta) + } + + override fun tick() { + loadingBar.tick() + controller.tick() + nextPage.active = controller.nextPageAvailable + previousPage.active = controller.previousPageAvailable + controller.scrollAmount = modList.scrollAmount + } + + override fun close() { + cache.destroyAll() + controller.close() + client!!.setScreen(parentScreen) + } + + override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + if (controller.keyPressed(keyCode, scanCode, modifiers)) { + return true + } + return super.keyPressed(keyCode, scanCode, modifiers) + } + + override fun updateSelectedEntry(widget: Any, entry: E?) { + if (widget !is ModListWidget) { + return + } + if (entry == null) { + return + } + if (controller.selectedMod?.id == (entry as ModListWidget.Entry).id) { + if (controller.selectedCategories.any { it.id == "updatable" }) { + client!!.setScreen(UpdateInfoScreen(this, controller.selectedMod!!)) + return + } + client!!.setScreen(ModInfoScreen(this, controller.selectedMod!!)) + return + } + controller.selectedMod = (entry as ModListWidget.Entry).mod + } + + @Suppress("UNCHECKED_CAST") + override fun updateMultipleEntries(widget: Any, entries: ArrayList) { + if (widget is CategoryListWidget) { + controller.reset() + if (entries.isEmpty()) { + controller.selectedCategories = emptyList() + controller.search() + return + } + controller.selectedCategories = (entries as ArrayList).mapNotNull { + controller.categories.find { cat -> it.id == cat.id } + } + controller.search() + } + } + + override val searchFieldFocused: Boolean + get() = searchField.isFocused + + override fun setMods(mods: List) = modList.setMods(mods) + override fun error(e: Exception) = TaskManager.add { + client!!.setScreen(ErrorScreen(this, e)) + } + + override fun setCategories(categories: List) = categoryList.setCategories(categories) + override fun setScrollAmount(scrollAmount: Double) { + modList.scrollAmount = scrollAmount + } + + override fun setLoading(loading: Boolean) { + loadingBar.visible = loading + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/modmanagermc/modmanager/gui/UpdateInfoScreen.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/UpdateInfoScreen.kt new file mode 100644 index 0000000..796a1d2 --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/UpdateInfoScreen.kt @@ -0,0 +1,134 @@ +package net.modmanagermc.modmanager.gui + +import com.mojang.blaze3d.systems.RenderSystem +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.screen.ScreenTexts +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.* +import net.modmanagermc.core.Core +import net.modmanagermc.core.controller.UpdateScreenController +import net.modmanagermc.core.model.Mod +import net.modmanagermc.core.screen.IListScreen +import net.modmanagermc.modmanager.gui.widgets.DescriptionWidget +import net.modmanagermc.modmanager.gui.widgets.ProgressWidget +import net.modmanagermc.modmanager.icon.IconCache +import kotlin.math.roundToInt + +class UpdateInfoScreen(private val parentScreen: Screen, mod: Mod) : Screen(Text.of("")), UpdateScreenController.View, + IListScreen { + + private val iconCache: IconCache by Core.di + private val controller = UpdateScreenController(mod, this) + private lateinit var loadingBar: ProgressWidget + private lateinit var actionButton: ButtonWidget + private lateinit var descriptionWidget: DescriptionWidget + + override fun init() { + loadingBar = ProgressWidget( + client!!, + width / 8, + (height * 0.5).roundToInt(), + (width * 0.75).roundToInt(), + 5, + TranslatableText("modmanager.details.loading", controller.mod.name), + true, + ) + loadingBar.visible = true + + val buttonX = width / 8 + actionButton = addDrawableChild(ButtonWidget( + this.width - buttonX - 150, + this.height - 28, + 150, + 20, + TranslatableText("modmanager.button.update") + ) { + }) + + descriptionWidget = addSelectableChild( + DescriptionWidget( + client!!, + width - 20, + height - 34, + 79, + height - 30, + textRenderer.fontHeight, + this, + "" + ) + ) + descriptionWidget.setLeftPos(10) + addDrawableChild(ButtonWidget(buttonX, height - 28, 150, 20, ScreenTexts.BACK) { + client!!.setScreen(parentScreen) + }) + + controller.init() + } + + override fun render(matrices: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) { + renderBackgroundTexture(0) + if (loadingBar.visible) { + loadingBar.render(matrices, mouseX, mouseY, delta) + return + } + + descriptionWidget.render(matrices, mouseX, mouseY, delta) + + val iconSize = 64 + iconCache.bindIcon(controller.mod) + RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f) + RenderSystem.enableBlend() + drawTexture(matrices, 20, 10, 0.0f, 0.0f, iconSize, iconSize, iconSize, iconSize) + RenderSystem.disableBlend() + + val font = client!!.textRenderer + + var trimmedTitle: MutableText = LiteralText(font.trimToWidth(controller.mod.name, width - 200)) + trimmedTitle = trimmedTitle.setStyle(Style.EMPTY.withBold(true)) + + var detailsY = 15F + val textX = 20 + iconSize + 5F + + font.draw(matrices, trimmedTitle, textX, detailsY, 0xFFFFFF) + + detailsY += 12 + font.draw( + matrices, + TranslatableText("modmanager.details.version", controller.metadata.version, controller.update.version.version), + textX, detailsY, 0xFFFFFF + ) + + super.render(matrices, mouseX, mouseY, delta) + } + + override fun tick() { + loadingBar.tick() + } + + override fun close() { + client!!.setScreen(parentScreen) + } + + override fun error(e: Exception) { + client!!.setScreen(ErrorScreen(parentScreen, e)) + } + + override fun setLoading(loading: Boolean) { + loadingBar.visible = loading + } + + override fun setDescription(text: String) { + this.descriptionWidget.updateText(text) + } + + override fun updateSelectedEntry(widget: Any, entry: E?) { + TODO("Not yet implemented") + } + + override fun updateMultipleEntries(widget: Any, entries: ArrayList) { + TODO("Not yet implemented") + } + + +} \ No newline at end of file diff --git a/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/CategoryListWidget.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/CategoryListWidget.kt new file mode 100644 index 0000000..4f61372 --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/CategoryListWidget.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021-2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.gui.widgets + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.OrderedText +import net.minecraft.text.Text +import net.minecraft.text.TranslatableText +import net.minecraft.util.Language +import net.modmanagermc.core.model.Category +import net.modmanagermc.core.screen.IListScreen + +class CategoryListWidget( + client: MinecraftClient, + width: Int, + height: Int, + top: Int, + bottom: Int, + itemHeight: Int, + parentScreen: IListScreen +) : MultiSelectListWidget( + client, + width, + height, + top, + bottom, + itemHeight, + parentScreen +) { + + fun setCategories(categories: List) { + clearEntries() + for (category in categories) { + addEntry(CategoryListEntry(this, category)) + } + } + + class CategoryListEntry(list: CategoryListWidget, private val category: Category) : + Entry(list, category.id) { + + override fun render( + matrices: MatrixStack?, + index: Int, + y: Int, + x: Int, + entryWidth: Int, + entryHeight: Int, + mouseX: Int, + mouseY: Int, + hovered: Boolean, + tickDelta: Float + ) { + val font = MinecraftClient.getInstance().textRenderer + var text: Text = TranslatableText(category.translationId) + if (list.isSelectedEntry(this)) { + text = text.getWithStyle(text.style.withBold(true))[0] + } + val trimmedText: OrderedText = Language.getInstance().reorder(font.trimToWidth(text, entryWidth - 10)) + font.draw(matrices, trimmedText, (x + 3).toFloat(), (y + 1).toFloat(), 0xFFFFFF) + } + + override fun getNarration(): Text { + return TranslatableText(category.translationId) + } + + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/CyclingButtonWidget.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/CyclingButtonWidget.kt new file mode 100644 index 0000000..61ebac8 --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/CyclingButtonWidget.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.gui.widgets + +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.text.TranslatableText +import kotlin.reflect.KFunction1 + +class CyclingButtonWidget( + x: Int, + y: Int, + width: Int, + height: Int, + private val text: String, + private val translator: KFunction1, + private val items: Array, + defaultValue: T, + val action: (T) -> Unit +) : ButtonWidget(x, y, width, height, TranslatableText(text), null) { + + private var index = items.indexOf(defaultValue) + + init { + updateText() + } + + override fun onPress() { + index++ + if (index >= items.size) { + index = 0 + } + updateText() + action(items[index]) + } + + private fun updateText() { + message = TranslatableText(text).append(": ").append(TranslatableText(translator.invoke(items[index]))) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/DescriptionWidget.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/DescriptionWidget.kt similarity index 92% rename from src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/DescriptionWidget.kt rename to src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/DescriptionWidget.kt index e220173..7c0c90d 100644 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/DescriptionWidget.kt +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/DescriptionWidget.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 DeathsGun + * Copyright (c) 2022 DeathsGun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,14 @@ * limitations under the License. */ -package xyz.deathsgun.modmanager.gui.widget +package net.modmanagermc.modmanager.gui.widgets import net.minecraft.client.MinecraftClient import net.minecraft.client.util.math.MatrixStack import net.minecraft.text.* import net.minecraft.util.Util -import xyz.deathsgun.modmanager.api.gui.list.IListScreen -import xyz.deathsgun.modmanager.api.gui.list.ListWidget -import xyz.deathsgun.modmanager.md.Markdown - +import net.modmanagermc.core.screen.IListScreen +import net.modmanagermc.modmanager.md.Markdown class DescriptionWidget( client: MinecraftClient, @@ -38,20 +36,9 @@ class DescriptionWidget( private val textRenderer = MinecraftClient.getInstance().textRenderer - fun init() { + init { renderOutline = false - val lines = Markdown(text).toText() - for (line in lines) { - if (textRenderer.getWidth(line) >= width - 10) { - val texts: List = textRenderer.wrapLines(line, width - 10) - for (wrappedLine in texts) { - addEntry(Entry(this, getText(wrappedLine))) - } - continue - } - addEntry(Entry(this, line)) - } - addEntry(Entry(this, LiteralText(""))) + updateText(text) } override fun getSelectedOrNull(): Entry? { @@ -82,6 +69,22 @@ class DescriptionWidget( return LiteralText(text).apply { this.style = style } } + fun updateText(text: String) { + clearEntries() + val lines = Markdown(text).toText() + for (line in lines) { + if (textRenderer.getWidth(line) >= width - 10) { + val texts: List = textRenderer.wrapLines(line, width - 10) + for (wrappedLine in texts) { + addEntry(Entry(this, getText(wrappedLine))) + } + continue + } + addEntry(Entry(this, line)) + } + addEntry(Entry(this, LiteralText.EMPTY)) + } + class Entry(list: ListWidget, val text: Text) : ListWidget.Entry(list, text.string) { private val textRenderer = MinecraftClient.getInstance().textRenderer diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/ListWidget.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ListWidget.kt similarity index 96% rename from src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/ListWidget.kt rename to src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ListWidget.kt index 86ff6b3..95cec85 100644 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/ListWidget.kt +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ListWidget.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 DeathsGun + * Copyright (c) 2021-2022 DeathsGun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package xyz.deathsgun.modmanager.api.gui.list +package net.modmanagermc.modmanager.gui.widgets import com.mojang.blaze3d.systems.RenderSystem import net.minecraft.client.MinecraftClient @@ -26,6 +26,7 @@ import net.minecraft.client.render.VertexFormat import net.minecraft.client.render.VertexFormats import net.minecraft.client.util.math.MatrixStack import net.minecraft.util.math.MathHelper +import net.modmanagermc.core.screen.IListScreen import java.util.* import kotlin.math.max @@ -41,7 +42,7 @@ abstract class ListWidget>( top: Int, var bottom: Int, itemHeight: Int, - protected val parent: IListScreen + protected val parent: IListScreen? ) : AlwaysSelectedEntryListWidget(client, width, height, top, bottom, itemHeight) { var renderOutline: Boolean = true @@ -49,13 +50,13 @@ abstract class ListWidget>( private var scrolling = false override fun isFocused(): Boolean { - return parent.getFocused() == this + return parent?.getFocused() == this } override fun setSelected(entry: E?) { super.setSelected(entry) selectedId = entry?.id - parent.updateSelectedEntry(this, selectedOrNull) + parent?.updateSelectedEntry(this, selectedOrNull) } override fun isSelectedEntry(index: Int): Boolean { diff --git a/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ModListWidget.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ModListWidget.kt new file mode 100644 index 0000000..a771cfa --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ModListWidget.kt @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021-2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.gui.widgets + +import com.mojang.blaze3d.systems.RenderSystem +import com.terraformersmc.modmenu.util.DrawingUtil +import net.minecraft.client.MinecraftClient +import net.minecraft.client.gui.DrawableHelper +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.* +import net.minecraft.util.Language +import net.modmanagermc.core.Core +import net.modmanagermc.core.mod.IModService +import net.modmanagermc.core.mod.State +import net.modmanagermc.core.model.Mod +import net.modmanagermc.core.screen.IListScreen +import net.modmanagermc.modmanager.icon.IconCache + +class ModListWidget( + client: MinecraftClient, + width: Int, + height: Int, + top: Int, + bottom: Int, + itemHeight: Int, + parent: IListScreen +) : ListWidget(client, width, height, top, bottom, itemHeight, parent) { + + fun setMods(list: List) { + replaceEntries(list.map { Entry(this, it) }) + } + + class Entry(list: ListWidget, val mod: Mod) : ListWidget.Entry(list, mod.id) { + + private val modService: IModService by Core.di + private val iconCache: IconCache by Core.di + + override fun render( + matrices: MatrixStack?, + index: Int, + y: Int, + x: Int, + entryWidth: Int, + entryHeight: Int, + mouseX: Int, + mouseY: Int, + hovered: Boolean, + tickDelta: Float + ) { + val client = MinecraftClient.getInstance() + val iconSize = 32 + RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f) + iconCache.bindIcon(mod) + RenderSystem.enableBlend() + DrawableHelper.drawTexture(matrices, x, y, 0.0f, 0.0f, iconSize, iconSize, iconSize, iconSize) + RenderSystem.disableBlend() + val name: Text = LiteralText(mod.name) + var trimmedName: StringVisitable = name + var maxNameWidth = entryWidth - iconSize - 3 + val font = client.textRenderer + var primaryColor = 0xFFFFFF + var secondaryColor = 0xFFFFFF + var badgeText: OrderedText? = null + val state = modService.getModState(mod.id) + if (state == State.INSTALLED) { + primaryColor = 0xff0e2a55.toInt() + secondaryColor = 0xff2b4b7c.toInt() + badgeText = TranslatableText("modmanager.badge.installed").asOrderedText() + maxNameWidth -= font.getWidth(badgeText) + 6 + } else if (state == State.OUTDATED) { + primaryColor = 0xff530C17.toInt() + secondaryColor = 0xff841426.toInt() + badgeText = TranslatableText("modmanager.badge.outdated").asOrderedText() + maxNameWidth -= font.getWidth(badgeText) + 6 + } + + val textWidth = font.getWidth(name) + if (textWidth > maxNameWidth) { + val ellipsis = StringVisitable.plain("...") + trimmedName = + StringVisitable.concat(font.trimToWidth(name, maxNameWidth - font.getWidth(ellipsis)), ellipsis) + } + font.draw( + matrices, + Language.getInstance().reorder(trimmedName), + (x + iconSize + 3).toFloat(), + (y + 1).toFloat(), + 0xFFFFFF + ) + if (badgeText != null) { + DrawingUtil.drawBadge( + matrices, + x + iconSize + 3 + textWidth + 3, + y + 1, + font.getWidth(badgeText) + 6, + badgeText, + secondaryColor, + primaryColor, + 0xFFFFFF + ) + } + + DrawingUtil.drawWrappedString( + matrices, + mod.description, + (x + iconSize + 3 + 4), + (y + client.textRenderer.fontHeight + 4), + entryWidth - iconSize - 7, + 2, + 0x808080 + ) + } + + override fun getNarration(): Text { + return LiteralText(mod.name) + } + + } +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/MultiSelectListWidget.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/MultiSelectListWidget.kt similarity index 91% rename from src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/MultiSelectListWidget.kt rename to src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/MultiSelectListWidget.kt index 485dbc2..2c9bd25 100644 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/MultiSelectListWidget.kt +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/MultiSelectListWidget.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 DeathsGun + * Copyright (c) 2021-2022 DeathsGun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,10 @@ * limitations under the License. */ -package xyz.deathsgun.modmanager.api.gui.list +package net.modmanagermc.modmanager.gui.widgets -import kotlinx.serialization.ExperimentalSerializationApi import net.minecraft.client.MinecraftClient +import net.modmanagermc.core.screen.IListScreen /** * Using ModMenu's implementation because the implementation from @@ -31,12 +31,11 @@ abstract class MultiSelectListWidget>( top: Int, bottom: Int, itemHeight: Int, - parent: IListScreen + parent: IListScreen? ) : ListWidget(client, width, height, top, bottom, itemHeight, parent) { private var selectedIds = ArrayList() - @OptIn(ExperimentalSerializationApi::class) override fun setSelected(entry: E?) { super.setSelected(entry) if (entry == null) { @@ -47,7 +46,7 @@ abstract class MultiSelectListWidget>( } else { selectedIds.add(entry.id) } - parent.updateMultipleEntries( + parent?.updateMultipleEntries( this, ArrayList(children().filter { selectedIds.contains(it.id) }.sortedBy { selectedIds.indexOf(it.id) }) ) diff --git a/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ProgressListWidget.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ProgressListWidget.kt new file mode 100644 index 0000000..a79c5fe --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ProgressListWidget.kt @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.gui.widgets + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.LiteralText +import net.minecraft.text.Text + +class ProgressListWidget( + client: MinecraftClient, + width: Int, + height: Int, + top: Int, + bottom: Int, + itemHeight: Int +) : ListWidget(client, width, height, top, bottom, itemHeight, null) { + + fun add( + id: String, + prefix: Text = LiteralText.EMPTY, + suffix: Text = LiteralText.EMPTY, + indeterminate: Boolean = false + ) { + addEntry(ProgressListEntry(this, id, prefix, suffix, indeterminate)) + } + + fun setProgress(id: String, progress: Double) { + if (progress !in 0.0..1.0) { + return + } + for (entry in children()) { + if (entry.id == id) { + entry.progressBar.percent = progress + } + } + } + + class ProgressListEntry( + list: ListWidget, + id: String, + private var prefix: Text = LiteralText.EMPTY, + private var suffix: Text = LiteralText.EMPTY, + indeterminate: Boolean = false, + ) : Entry(list, id) { + + private val textRenderer = MinecraftClient.getInstance().textRenderer + val progressBar: ProgressWidget = ProgressWidget( + MinecraftClient.getInstance(), + 0, + 0, + 0, + 0, + LiteralText.EMPTY, + indeterminate, + ) + + override fun render( + matrices: MatrixStack, + index: Int, + y: Int, + x: Int, + entryWidth: Int, + entryHeight: Int, + mouseX: Int, + mouseY: Int, + hovered: Boolean, + delta: Float + ) { + progressBar.x = x + progressBar.y = y + + var prefixLength = textRenderer.getWidth(prefix) + var suffixLength = textRenderer.getWidth(suffix) + + if (prefixLength > 0) { + prefixLength += 5 + 2 + progressBar.x += prefixLength + } + if (suffixLength > 0) { + suffixLength += 5 + 2 + } + + progressBar.width = entryWidth - prefixLength - suffixLength + progressBar.height = entryHeight + progressBar.render(matrices, mouseX, mouseY, delta) + + if (prefixLength > 0) { + textRenderer.draw( + matrices, + prefix, + (x + 2).toFloat(), + (y - (entryHeight / 2 - textRenderer.fontHeight)).toFloat(), + 0xFFFFFF, + ) + } + if (suffixLength > 0) { + textRenderer.draw( + matrices, + prefix, + (x + entryWidth - suffixLength + 5).toFloat(), + (y - (entryHeight / 2 - textRenderer.fontHeight)).toFloat(), + 0xFFFFFF, + ) + } + } + + override fun getNarration(): Text { + return LiteralText("").append(prefix).append(" ").append(suffix) + } + + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ProgressWidget.kt b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ProgressWidget.kt new file mode 100644 index 0000000..e1795eb --- /dev/null +++ b/src/main/kotlin/net/modmanagermc/modmanager/gui/widgets/ProgressWidget.kt @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2022 DeathsGun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.modmanagermc.modmanager.gui.widgets + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.gui.Drawable +import net.minecraft.client.gui.DrawableHelper +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.LiteralText +import net.minecraft.text.Text +import kotlin.math.roundToInt + +class ProgressWidget( + val client: MinecraftClient, + var x: Int, + var y: Int, + var width: Int, + var height: Int = 5, + var text: Text = LiteralText.EMPTY, + private val indeterminate: Boolean = false +) : DrawableHelper(), Drawable { + + private val color: Int = 0xFFFFFFFF.toInt() + var speed: Double = 0.02 + var visible: Boolean = true + var percent: Double = 0.0 + set(value) { + if (value in 0.0..1.0) { + field = value + } + } + + override fun render(matrices: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) { + if (!visible) { + return + } + + val textWidth = client.textRenderer.getWidth(text) + + if (textWidth > 0) { + client.textRenderer.draw( + matrices, text, (x + width / 2f) - textWidth / 2f, + y - height - client.textRenderer.fontHeight - 5f, color + ) + } + // Render outline + fill(matrices, x + 1, y - height, x + width - 1, y - height + 1, color) + fill(matrices, x + 1, y + height, x + width - 1, y + height - 1, color) + fill(matrices, x, y - height, x + 1, y + height, color) + fill(matrices, x + width, y - height, x + width - 1, y + height, color) + + if (indeterminate) { + renderIndeterminate(matrices) + return + } + fill(matrices, x + 2, y - height - 2, (x + width * percent).roundToInt(), y + height + 2, color) + } + + + private fun renderIndeterminate(matrices: MatrixStack) { + var barWidth = width * 0.4 + val overlap = (x + width * percent + barWidth) - (x + width) + 2 + if (overlap > 0) { + barWidth -= overlap + } + + fill( + matrices, + (x + 2 + width * percent).roundToInt(), + y - height + 2, + (x + barWidth + width * percent).roundToInt(), + y + height - 2, + color + ) + if (overlap > 0) { + fill( + matrices, + x + 2, + y - height + 2, + (x + overlap + 2).roundToInt(), + y + height - 2, + color + ) + } + } + + fun tick() { + if (percent > 1.0 - speed) { + percent = 0.0 + return + } + percent += speed + } + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/icon/IconCache.kt b/src/main/kotlin/net/modmanagermc/modmanager/icon/IconCache.kt similarity index 83% rename from src/main/kotlin/xyz/deathsgun/modmanager/icon/IconCache.kt rename to src/main/kotlin/net/modmanagermc/modmanager/icon/IconCache.kt index 774497c..ad14047 100644 --- a/src/main/kotlin/xyz/deathsgun/modmanager/icon/IconCache.kt +++ b/src/main/kotlin/net/modmanagermc/modmanager/icon/IconCache.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 DeathsGun + * Copyright (c) 2021-2022 DeathsGun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,11 @@ * limitations under the License. */ -package xyz.deathsgun.modmanager.icon +package net.modmanagermc.modmanager.icon import com.mojang.blaze3d.systems.RenderSystem import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import net.fabricmc.loader.api.FabricLoader @@ -25,14 +26,12 @@ import net.minecraft.client.MinecraftClient import net.minecraft.client.texture.NativeImage import net.minecraft.client.texture.NativeImageBackedTexture import net.minecraft.util.Identifier +import net.modmanagermc.core.model.Mod import org.apache.commons.io.FileUtils +import org.apache.http.client.methods.HttpGet +import org.apache.http.impl.client.HttpClients +import org.apache.http.util.EntityUtils import org.apache.logging.log4j.LogManager -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.mod.Mod -import java.net.URI -import java.net.http.HttpClient -import java.net.http.HttpRequest -import java.net.http.HttpResponse import java.nio.file.Files import java.util.stream.Collectors @@ -41,9 +40,9 @@ class IconCache { private val logger = LogManager.getLogger("IconCache") private val unknownIcon = Identifier("textures/misc/unknown_pack.png") private val loadingIcon = Identifier("modmanager", "textures/gui/loading.png") - private val iconsDir = FabricLoader.getInstance().gameDir.resolve(".icons") + private val iconsDir = FabricLoader.getInstance().configDir.resolve("modmanager").resolve("images").resolve("icons") private val state = HashMap() - private val http = HttpClient.newHttpClient() + private val http = HttpClients.createDefault() init { Files.createDirectories(iconsDir) @@ -53,7 +52,7 @@ class IconCache { fun bindIcon(mod: Mod) { val icon = when (this.state[mod.id] ?: IconState.NOT_FOUND) { IconState.NOT_FOUND -> { - GlobalScope.launch { + GlobalScope.launch(Dispatchers.IO) { downloadIcon(mod) } loadingIcon @@ -79,7 +78,7 @@ class IconCache { icon } catch (e: Exception) { this.state[mod.id] = IconState.ERRORED - logger.error("Error while loading icon for {}: {}", mod.slug, e.message) + logger.error("Error while loading icon for {}: {}", mod.id, e) unknownIcon } } @@ -93,20 +92,23 @@ class IconCache { if (iconState != IconState.NOT_FOUND) { return } + if (Files.exists(iconsDir.resolve(mod.id))) { + state[mod.id] = IconState.DOWNLOADED + return + } state[mod.id] = IconState.DOWNLOADING try { - val request = HttpRequest.newBuilder(URI.create(mod.iconUrl)).GET() - .setHeader("User-Agent", "ModMenu " + ModManager.getVersion()).build() - val response = http.send(request, HttpResponse.BodyHandlers.ofByteArray()) - if (response.statusCode() != 200) { + val response = http.execute(HttpGet(mod.iconUrl)) + if (response.statusLine.statusCode != 200) { state[mod.id] = IconState.ERRORED return } - Files.write(iconsDir.resolve(mod.id), response.body()) + Files.copy(response.entity.content, iconsDir.resolve(mod.id)) + EntityUtils.consume(response.entity) state[mod.id] = IconState.DOWNLOADED } catch (e: Exception) { state[mod.id] = IconState.ERRORED - logger.error("Error while downloading icon for {}: {}", mod.slug, e.message) + logger.error("Error while downloading icon for {}: {}", mod.id, e) } } diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/md/Markdown.kt b/src/main/kotlin/net/modmanagermc/modmanager/md/Markdown.kt similarity index 97% rename from src/main/kotlin/xyz/deathsgun/modmanager/md/Markdown.kt rename to src/main/kotlin/net/modmanagermc/modmanager/md/Markdown.kt index 44d2600..25232a6 100644 --- a/src/main/kotlin/xyz/deathsgun/modmanager/md/Markdown.kt +++ b/src/main/kotlin/net/modmanagermc/modmanager/md/Markdown.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 DeathsGun + * Copyright (c) 2021-2022 DeathsGun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package xyz.deathsgun.modmanager.md +package net.modmanagermc.modmanager.md import net.minecraft.text.ClickEvent import net.minecraft.text.LiteralText diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/ModManager.kt b/src/main/kotlin/xyz/deathsgun/modmanager/ModManager.kt deleted file mode 100644 index 50d300a..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/ModManager.kt +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager - -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import net.fabricmc.api.ClientModInitializer -import net.minecraft.SharedConstants -import xyz.deathsgun.modmanager.api.mod.State -import xyz.deathsgun.modmanager.api.provider.IModProvider -import xyz.deathsgun.modmanager.api.provider.IModUpdateProvider -import xyz.deathsgun.modmanager.config.Config -import xyz.deathsgun.modmanager.icon.IconCache -import xyz.deathsgun.modmanager.providers.modrinth.Modrinth -import xyz.deathsgun.modmanager.state.SavedState -import xyz.deathsgun.modmanager.update.UpdateManager -import java.util.* - -class ModManager : ClientModInitializer { - - private val states = ArrayList() - var config: Config = Config.loadConfig() - var changed: Boolean = false - val update: UpdateManager = UpdateManager() - val icons: IconCache = IconCache() - val provider: HashMap = HashMap() - val updateProvider: HashMap = HashMap() - - init { - val modrinth = Modrinth() - provider[modrinth.getName().lowercase()] = modrinth - updateProvider[modrinth.getName().lowercase()] = modrinth - } - - companion object { - private val properties = Properties().apply { - load(Companion::class.java.getResourceAsStream("/build.info")) - } - @JvmField - var shownUpdateNotification: Boolean = false - - @JvmStatic - lateinit var modManager: ModManager - - @JvmStatic - fun getVersion(): String { - return properties.getProperty("version") - } - - @JvmStatic - fun getMinecraftReleaseTarget(): String { - return properties.getProperty("releaseTarget") - } - - @JvmStatic - fun getMinecraftVersionId(): String { - return SharedConstants.RELEASE_TARGET - } - } - - @OptIn(DelicateCoroutinesApi::class) - override fun onInitializeClient() { - GlobalScope.launch { - icons.cleanupCache() - } - } - - fun setModState(fabricId: String, modId: String, state: State) { - this.states.removeAll { it.modId == modId || it.fabricId == fabricId } - this.states.add(SavedState(fabricId, modId, state)) - } - - fun getModState(id: String): State { - return this.states.find { it.modId == id || it.fabricId == id }?.state ?: State.DOWNLOADABLE - } - - fun getSelectedProvider(): IModProvider? { - return this.provider[config.defaultProvider] - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/PreLaunchHook.kt b/src/main/kotlin/xyz/deathsgun/modmanager/PreLaunchHook.kt deleted file mode 100644 index 316cbda..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/PreLaunchHook.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager - -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json -import net.fabricmc.loader.api.FabricLoader -import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint -import org.apache.logging.log4j.LogManager -import java.nio.file.Files -import kotlin.io.path.Path -import kotlin.io.path.deleteIfExists - -class PreLaunchHook : PreLaunchEntrypoint { - - private val logger = LogManager.getLogger("ModManager") - - @OptIn(DelicateCoroutinesApi::class) - override fun onPreLaunch() { - ModManager.modManager = ModManager() - GlobalScope.launch { - ModManager.modManager.update.checkUpdates() - } - val filesToDelete = try { - loadFiles() - } catch (e: Exception) { - ArrayList() - } - for (file in filesToDelete) { - logger.info("Deleting {}", file) - val path = Path(file) - try { - Files.delete(path) - } catch (e: Exception) { // Ignore it - } - } - } - - @OptIn(ExperimentalSerializationApi::class) - private fun loadFiles(): ArrayList { - val configFile = FabricLoader.getInstance().configDir.resolve(".modmanager.delete.json") - if (Files.notExists(configFile)) { - return ArrayList() - } - val data = Files.readString(configFile, Charsets.UTF_8) - configFile.deleteIfExists() - return Json.decodeFromString(data) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/ModInstallResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/ModInstallResult.kt deleted file mode 100644 index 00b3095..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/ModInstallResult.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api - -import net.minecraft.text.TranslatableText - -sealed class ModInstallResult { - - object Success : ModInstallResult() - data class Error(val text: TranslatableText, val cause: Exception? = null) : ModInstallResult() -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/ModRemoveResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/ModRemoveResult.kt deleted file mode 100644 index 6515c8a..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/ModRemoveResult.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api - -import net.minecraft.text.TranslatableText - -sealed class ModRemoveResult { - object Success : ModRemoveResult() - data class Error(val text: TranslatableText, val cause: Exception? = null) : ModRemoveResult() -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/ModUpdateResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/ModUpdateResult.kt deleted file mode 100644 index 2558317..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/ModUpdateResult.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api - -import net.minecraft.text.TranslatableText - -sealed class ModUpdateResult { - object Success : ModUpdateResult() - data class Error(val text: TranslatableText, val cause: Exception? = null) : ModUpdateResult() -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/IListScreen.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/IListScreen.kt deleted file mode 100644 index ddf3555..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/gui/list/IListScreen.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.gui.list - -import net.minecraft.client.gui.Element - -interface IListScreen { - - fun getFocused(): Element? - - fun updateSelectedEntry(widget: Any, entry: E?) - - fun updateMultipleEntries(widget: Any, entries: ArrayList) - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/CategoriesResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/http/CategoriesResult.kt deleted file mode 100644 index af1f3d1..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/CategoriesResult.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.http - -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.api.mod.Category - -sealed class CategoriesResult { - - data class Success(val categories: List) : CategoriesResult() - - data class Error(val text: TranslatableText, val cause: Exception? = null) : CategoriesResult() - -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/HttpClient.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/http/HttpClient.kt deleted file mode 100644 index 5c470e9..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/HttpClient.kt +++ /dev/null @@ -1,68 +0,0 @@ -package xyz.deathsgun.modmanager.api.http - -import java.io.ByteArrayInputStream -import java.io.InputStream -import java.net.HttpURLConnection -import java.net.URI -import java.net.URL -import java.nio.file.Files -import java.nio.file.Path -import kotlin.math.min - -object HttpClient { - - fun get(url: String): ByteArray { - return get(URI.create(url)) - } - - fun get(uri: URI): ByteArray { - val connection = uri.toURL().openConnection() as HttpURLConnection - connection.readTimeout = 10000 - connection.requestMethod = "GET" - connection.connect() - if (connection.responseCode != 200) { - connection.disconnect() - throw InvalidStatusCodeException(connection.responseCode) - } - val content = connection.inputStream.readBytes() - connection.disconnect() - return content - } - - fun getInputStream(url: String): InputStream { - return getInputStream(URI.create(url)) - } - - private fun getInputStream(uri: URI): InputStream { - return ByteArrayInputStream(get(uri)) - } - - fun download(url: String, path: Path, listener: ((Double) -> Unit)? = null) { - val output = Files.newOutputStream(path) - val connection = URL(url).openConnection() as HttpURLConnection - connection.readTimeout = 10000 - connection.requestMethod = "GET" - connection.connect() - if (connection.responseCode != 200) { - connection.disconnect() - throw InvalidStatusCodeException(connection.responseCode) - } - val size = connection.contentLength - var downloaded = 0 - while (true) { - val buffer = ByteArray(min(1024, size - downloaded)) - val read = connection.inputStream.read(buffer) - if (read == -1) { - break - } - output.write(buffer, 0, read) - downloaded += read - listener?.invoke((downloaded / size).toDouble()) - } - connection.disconnect() - output.flush() - output.close() - } - - class InvalidStatusCodeException(val statusCode: Int) : Exception("Received invalid status code: $statusCode") -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/ModResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/http/ModResult.kt deleted file mode 100644 index 02bd257..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/ModResult.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.http - -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.api.mod.Mod - -sealed class ModResult { - data class Success(val mod: Mod) : ModResult() - data class Error(val text: TranslatableText, val cause: Exception? = null) : ModResult() -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/ModsResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/http/ModsResult.kt deleted file mode 100644 index 3a7cbb3..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/ModsResult.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.http - -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.api.mod.Mod - -sealed class ModsResult { - data class Success(val mods: List) : ModsResult() - data class Error(val text: TranslatableText, val cause: Exception? = null) : ModsResult() -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/VersionResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/http/VersionResult.kt deleted file mode 100644 index 7450b65..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/http/VersionResult.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.http - -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.api.mod.Version - -sealed class VersionResult { - - data class Success(val versions: List) : VersionResult() - data class Error(val text: TranslatableText, val cause: Exception? = null) : VersionResult() - -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Asset.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Asset.kt deleted file mode 100644 index 6cc2da6..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Asset.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.mod - -data class Asset( - val url: String, - val filename: String, - val hashes: Map, - val primary: Boolean -) diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Category.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Category.kt deleted file mode 100644 index 94aafdf..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Category.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.mod - -import net.minecraft.text.TranslatableText - -data class Category( - val id: String, - val text: TranslatableText -) - diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Mod.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Mod.kt deleted file mode 100644 index 9dd0fac..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Mod.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.mod - -data class Mod( - val id: String, - val slug: String, - var author: String?, - val name: String, - var shortDescription: String, - val iconUrl: String?, - var description: String?, - val license: String?, - val categories: List, -) diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/State.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/State.kt deleted file mode 100644 index 0c6994b..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/State.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.mod - -enum class State { - - /** - * Returns this if the mod has been found in the current - * mod list - */ - INSTALLED, - - /** - * Returns this if the mod has been found and also has been - * checked for updates - */ - OUTDATED, - - /** - * Returns this if the mod was not found - */ - DOWNLOADABLE - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Version.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Version.kt deleted file mode 100644 index 403ac3e..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Version.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.mod - -import java.time.LocalDate - -data class Version( - val version: String, - val changelog: String, - val releaseDate: LocalDate, - val type: VersionType, - val gameVersions: List, - val assets: List -) diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/VersionType.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/VersionType.kt deleted file mode 100644 index 51b94dc..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/mod/VersionType.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.mod - -enum class VersionType { - ALPHA, BETA, RELEASE, UNKNOWN -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/IModProvider.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/IModProvider.kt deleted file mode 100644 index 39ff37c..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/IModProvider.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.provider - -import xyz.deathsgun.modmanager.api.http.CategoriesResult -import xyz.deathsgun.modmanager.api.http.ModResult -import xyz.deathsgun.modmanager.api.http.ModsResult -import xyz.deathsgun.modmanager.api.mod.Category -import xyz.deathsgun.modmanager.api.mod.Mod - -interface IModProvider : IModUpdateProvider { - - /** - * Returns a list of all possible mod categories also with an translatable text - * - * @return a list of all mod categories - */ - fun getCategories(): CategoriesResult - - /** - * Returns a limited number of [Mod]'s sorted - * in a given way. - * - * @param sorting the requested sorting of the mods - * @param page the requested from the UI starting at 1 - * @param limit to not overfill the ui and for shorter loading times the amount of returned mods needs to limited - * @return a list of sorted mods - */ - fun getMods(sorting: Sorting, page: Int, limit: Int): ModsResult - - /** - * Returns a limited number of [Mod]'s from the specified category - * - * @param categories the categories of the mods - * @param sorting the sorting order - * @param page the requested from the UI starting at 1 - * @param limit to not overfill the ui and for shorter loading times the amount of returned mods needs to limited - * @return a list of sorted mods - */ - fun getMods(categories: List, sorting: Sorting, page: Int, limit: Int): ModsResult - - /** - * Returns a limited number of [Mod]'s from a given search. - * - * @param query the search string - * @param categories the categories in which should be searched - * @param page the current requested page starts at 0 - * @param limit the amount of mods to return - * @return a list of mods matching the search term - */ - fun search(query: String, categories: List, sorting: Sorting, page: Int, limit: Int): ModsResult - - /** - * Returns a more detailed representation of the mod - * - * @param id the [Mod] id which is used to receive - * @return a more detailed representation of [Mod] - */ - fun getMod(id: String): ModResult -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/IModUpdateProvider.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/IModUpdateProvider.kt deleted file mode 100644 index 2e4837d..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/IModUpdateProvider.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.api.provider - -import xyz.deathsgun.modmanager.api.http.VersionResult - -interface IModUpdateProvider { - - /** - * Name of the provider. This will be shown - * in the GUI - * - * @return returns a user-friendly name of the mod provider implementation - */ - fun getName(): String - - /** - * Gets a list all versions that can be downloaded for the specified [id] - * @return a returns a [VersionResult] which can be an [VersionResult.Error] or [VersionResult.Success] - * which contains a list of [xyz.deathsgun.modmanager.api.mod.Version] - */ - fun getVersionsForMod(id: String): VersionResult - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/Sorting.kt b/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/Sorting.kt deleted file mode 100644 index 0ad2171..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/api/provider/Sorting.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package xyz.deathsgun.modmanager.api.provider - -import net.minecraft.text.Text -import net.minecraft.text.TranslatableText - -enum class Sorting { - RELEVANCE, DOWNLOADS, UPDATED, NEWEST; - - fun translations(): Text { - return TranslatableText(String.format("modmanager.sorting.%s", name.lowercase())) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/config/Config.kt b/src/main/kotlin/xyz/deathsgun/modmanager/config/Config.kt deleted file mode 100644 index 07addd5..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/config/Config.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.config - -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.Serializable -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import net.fabricmc.loader.api.FabricLoader -import net.minecraft.text.Text -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.api.mod.VersionType -import java.nio.charset.Charset -import java.nio.file.Files - -@Serializable -data class Config( - var defaultProvider: String = "modrinth", - var updateChannel: UpdateChannel = UpdateChannel.ALL, - var hidden: ArrayList = ArrayList() -) { - - companion object { - - private val json = Json { - prettyPrint = true - encodeDefaults = true - } - - @OptIn(ExperimentalSerializationApi::class) - fun loadConfig(): Config { - return try { - val file = FabricLoader.getInstance().configDir.resolve("modmanager.json") - Files.createDirectories(file.parent) - val data = Files.readString(file, Charset.forName("UTF-8")) - json.decodeFromString(data) - } catch (e: Exception) { - if (e !is NoSuchFileException) { - e.printStackTrace() - } - saveConfig(Config()) - } - } - - @OptIn(ExperimentalSerializationApi::class) - fun saveConfig(config: Config): Config { - try { - val file = FabricLoader.getInstance().configDir.resolve("modmanager.json") - val data = json.encodeToString(config) - Files.writeString(file, data, Charset.forName("UTF-8")) - } catch (ignored: Exception) { - } - return config - } - } - - enum class UpdateChannel { - ALL, STABLE, UNSTABLE; - - fun text(): Text { - return TranslatableText(String.format("modmanager.channel.%s", name.lowercase())) - } - - fun isReleaseAllowed(type: VersionType): Boolean { - if (this == ALL) { - return true - } - if (this == STABLE && type == VersionType.RELEASE) { - return true - } - return this == UNSTABLE - } - } -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ConfigScreen.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/ConfigScreen.kt deleted file mode 100644 index 09a27d6..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ConfigScreen.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui - -import net.minecraft.client.font.MultilineText -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.gui.screen.ScreenTexts -import net.minecraft.client.gui.widget.ButtonWidget -import net.minecraft.client.gui.widget.CyclingButtonWidget -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.LiteralText -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.config.Config - -class ConfigScreen(private val previousScreen: Screen) : Screen(LiteralText("Config")) { - - private lateinit var defaultProvider: CyclingButtonWidget - private lateinit var updateChannel: CyclingButtonWidget - private var config: Config = ModManager.modManager.config.copy() - - override fun init() { - defaultProvider = addDrawableChild(CyclingButtonWidget.builder { LiteralText(it) } - .values(ModManager.modManager.provider.keys.toList()) - .initially(config.defaultProvider) - .build(width - 220, 30, 200, 20, TranslatableText("modmanager.button.defaultProvider")) - { _: CyclingButtonWidget, s: String -> config.defaultProvider = s }) - defaultProvider.active = ModManager.modManager.provider.size > 1 - - updateChannel = addDrawableChild(CyclingButtonWidget.builder { it.text() } - .values(listOf(Config.UpdateChannel.ALL, Config.UpdateChannel.STABLE)) - .initially(config.updateChannel) - .build(width - 220, 60, 200, 20, TranslatableText("modmanager.button.updateChannel")) - { _: CyclingButtonWidget, channel: Config.UpdateChannel -> config.updateChannel = channel }) - - addDrawableChild(ButtonWidget( - width / 2 - 154, height - 28, 150, 20, ScreenTexts.CANCEL, - ) { - client!!.setScreen(previousScreen) - }) - addDrawableChild(ButtonWidget( - width / 2 + 4, height - 28, 150, 20, TranslatableText("modmanager.button.save") - ) { - ModManager.modManager.config = Config.saveConfig(this.config) - client!!.setScreen(previousScreen) - }) - - } - - override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { - super.renderBackground(matrices) - - MultilineText.create(textRenderer, TranslatableText("modmanager.provider.info"), width - 230) - .draw(matrices, 10, 35, textRenderer.fontHeight, 0xFFFFFF) - MultilineText.create(textRenderer, TranslatableText("modmanager.channel.info"), width - 230) - .draw(matrices, 10, 65, textRenderer.fontHeight, 0xFFFFFF) - super.render(matrices, mouseX, mouseY, delta) - } - - override fun onClose() { - client!!.setScreen(previousScreen) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModDetailScreen.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModDetailScreen.kt deleted file mode 100644 index 3fbd82e..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModDetailScreen.kt +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui - -import com.mojang.blaze3d.systems.RenderSystem -import com.terraformersmc.modmenu.util.DrawingUtil -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.gui.screen.ScreenTexts -import net.minecraft.client.gui.widget.ButtonWidget -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.* -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.ModRemoveResult -import xyz.deathsgun.modmanager.api.gui.list.IListScreen -import xyz.deathsgun.modmanager.api.http.ModResult -import xyz.deathsgun.modmanager.api.mod.Mod -import xyz.deathsgun.modmanager.api.mod.State -import xyz.deathsgun.modmanager.gui.widget.DescriptionWidget - - -class ModDetailScreen(private val previousScreen: Screen, var mod: Mod) : Screen(LiteralText(mod.name)), IListScreen { - - private lateinit var actionButton: ButtonWidget - private lateinit var descriptionWidget: DescriptionWidget - - init { - val provider = ModManager.modManager.getSelectedProvider() - if (provider != null) { - when (val result = provider.getMod(mod.id)) { - is ModResult.Error -> { - client!!.setScreen(ErrorScreen(previousScreen, this, result.text)) - } - is ModResult.Success -> { - val tmp = mod - mod = result.mod - mod.author = tmp.author - mod.shortDescription = tmp.shortDescription - } - } - } - } - - override fun init() { - val buttonX = width / 8 - descriptionWidget = addSelectableChild( - DescriptionWidget( - client!!, - width - 20, - height - 34, - 79, - height - 30, - textRenderer.fontHeight, - this, - mod.description!! - ) - ) - descriptionWidget.setLeftPos(10) - descriptionWidget.init() - addDrawableChild(ButtonWidget(buttonX, height - 28, 150, 20, ScreenTexts.BACK) { - client!!.setScreen(previousScreen) - }) - this.actionButton = addDrawableChild( - ButtonWidget( - this.width - buttonX - 150, - this.height - 28, - 150, - 20, - TranslatableText("modmanager.button.install") - ) { - when (ModManager.modManager.getModState(mod.id)) { - State.DOWNLOADABLE -> { - client!!.setScreen( - ModProgressScreen( - mod, - ModProgressScreen.Action.INSTALL, - previousScreen, - this - ) - ) - } - State.OUTDATED -> { - client!!.setScreen( - ModProgressScreen( - mod, - ModProgressScreen.Action.UPDATE, - previousScreen, - this - ) - ) - } - State.INSTALLED -> { - removeMod() - } - } - }) - } - - private fun removeMod() { - when (val result = ModManager.modManager.update.removeMod(mod)) { - is ModRemoveResult.Success -> client!!.setScreen(previousScreen) - is ModRemoveResult.Error -> client!!.setScreen(ErrorScreen(previousScreen, this, result.text)) - } - } - - override fun tick() { - actionButton.message = when (ModManager.modManager.getModState(mod.id)) { - State.INSTALLED -> TranslatableText("modmanager.button.remove") - State.DOWNLOADABLE -> TranslatableText("modmanager.button.install") - State.OUTDATED -> TranslatableText("modmanager.button.update") - } - } - - override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { - super.renderBackground(matrices) - descriptionWidget.render(matrices, mouseX, mouseY, delta) - - val iconSize = 64 - ModManager.modManager.icons.bindIcon(mod) - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f) - ModManager.modManager.icons.bindIcon(mod) - RenderSystem.enableBlend() - drawTexture(matrices, 20, 10, 0.0f, 0.0f, iconSize, iconSize, iconSize, iconSize) - RenderSystem.disableBlend() - - val font = client!!.textRenderer - - var trimmedTitle: MutableText = LiteralText(font.trimToWidth(mod.name, width - 200)) - trimmedTitle = trimmedTitle.setStyle(Style.EMPTY.withBold(true)) - - var detailsY = 15F - var textX = 20 + iconSize + 5F - - font.draw(matrices, trimmedTitle, textX, detailsY, 0xFFFFFF) - - detailsY += 12 - font.draw( - matrices, - TranslatableText("modmanager.details.author", mod.author), - textX, detailsY, 0xFFFFFF - ) - - detailsY += 12 - DrawingUtil.drawBadge( - matrices, textX.toInt(), detailsY.toInt(), - font.getWidth(mod.license) + 6, - Text.of(mod.license).asOrderedText(), - -0x909396, -0xcecfd1, 0xCACACA - ) - - for (category in mod.categories) { - val textWidth: Int = font.getWidth(category.text) + 6 - DrawingUtil.drawBadge( - matrices, - textX.toInt(), - (detailsY + 14).toInt(), - textWidth, - category.text.asOrderedText(), - -0x909396, - -0xcecfd1, - 0xCACACA - ) - textX += textWidth + 4 - } - super.render(matrices, mouseX, mouseY, delta) - } - - override fun onClose() { - client!!.setScreen(previousScreen) - } - - override fun updateSelectedEntry(widget: Any, entry: E?) { - } - - override fun updateMultipleEntries(widget: Any, entries: ArrayList) { - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModProgressScreen.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModProgressScreen.kt deleted file mode 100644 index a0c3c39..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModProgressScreen.kt +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui - -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import net.minecraft.client.MinecraftClient -import net.minecraft.client.font.MultilineText -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.gui.screen.ScreenTexts -import net.minecraft.client.gui.widget.ButtonWidget -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.LiteralText -import net.minecraft.text.Text -import net.minecraft.text.TranslatableText -import net.minecraft.util.math.MathHelper -import org.apache.logging.log4j.LogManager -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.ModInstallResult -import xyz.deathsgun.modmanager.api.ModUpdateResult -import xyz.deathsgun.modmanager.api.mod.Mod -import kotlin.math.roundToInt - -class ModProgressScreen( - val mod: Mod, - private val action: Action, - private val previousScreen: Screen, - private val infoScreen: Screen -) : - Screen(LiteralText("")) { - - private var status: MultilineText? = null - private lateinit var backButton: ButtonWidget - private var finished: Boolean = false - private var pos = 0 - private var rightEnd = 0 - private var leftEnd = 0 - - @OptIn(DelicateCoroutinesApi::class) - override fun init() { - backButton = addDrawableChild( - ButtonWidget( - width / 2 - 75, - (height * 0.6 + 40).roundToInt(), - 150, - 20, - ScreenTexts.BACK - ) { - client!!.setScreen(previousScreen) - }) - backButton.visible = false - GlobalScope.launch { - when (action) { - Action.UPDATE -> updateMod() - Action.INSTALL -> installMod() - } - } - } - - override fun tick() { - pos += 5 - } - - override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { - rightEnd = width - width / 8 - leftEnd = width / 8 - super.renderBackground(matrices) - - var y = (height * 0.60).roundToInt() - if (status != null) { - val linesHeight = this.status!!.count() * 9 - y = MathHelper.clamp(90 + linesHeight + 12, this.height / 6 + 69, this.height - 24) - status!!.drawCenterWithShadow(matrices, this.width / 2, 90) - } - if (!finished) { - renderProgressBar(matrices, width / 8, y - 5, rightEnd, y + 5) - } - - backButton.y = y + 10 - - super.render(matrices, mouseX, mouseY, delta) - } - - private fun renderProgressBar(matrices: MatrixStack?, minX: Int, minY: Int, maxX: Int, maxY: Int) { - val color = 0xFFFFFFFF.toInt() - var barWidth = width / 10 - val overlap = (minX + pos + barWidth) - maxX + 2 - if (overlap > 0) { - barWidth -= overlap - } - if ((minX + pos) - maxX + 2 > 0) { - pos = 0 - } - fill(matrices, minX + 2 + pos, minY + 2, minX + pos + barWidth, maxY - 2, color) - fill(matrices, minX + 1, minY, maxX - 1, minY + 1, color) - fill(matrices, minX + 1, maxY, maxX - 1, maxY - 1, color) - fill(matrices, minX, minY, minX + 1, maxY, color) - fill(matrices, maxX, minY, maxX - 1, maxY, color) - } - - - private fun installMod() { - setStatus(TranslatableText("modmanager.status.installing", mod.name)) - when (val result = ModManager.modManager.update.installMod(mod)) { - is ModInstallResult.Error -> { - LogManager.getLogger().error(result.text.key, result.cause) - client!!.send { - MinecraftClient.getInstance().setScreen(ErrorScreen(previousScreen, infoScreen, result.text)) - } - } - is ModInstallResult.Success -> { - finished = true - this.backButton.visible = true - setStatus(TranslatableText("modmanager.status.install.success", mod.name)) - } - } - } - - private fun updateMod() { - setStatus(TranslatableText("modmanager.status.updating", mod.name)) - val update = ModManager.modManager.update.getUpdateForMod(mod) ?: return - when (val result = ModManager.modManager.update.updateMod(update)) { - is ModUpdateResult.Error -> { - LogManager.getLogger().error(result.text.key, result.cause) - client!!.send { - MinecraftClient.getInstance().setScreen(ErrorScreen(previousScreen, infoScreen, result.text)) - } - } - is ModUpdateResult.Success -> { - finished = true - this.backButton.visible = true - setStatus(TranslatableText("modmanager.status.update.success", mod.name)) - } - } - } - - fun setStatus(text: Text) { - status = MultilineText.create(textRenderer, text, width - 2 * (width / 8)) - } - - override fun onClose() { - client!!.setScreen(previousScreen) - } - - enum class Action { - INSTALL, UPDATE - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModUpdateInfoScreen.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModUpdateInfoScreen.kt deleted file mode 100644 index 2affd3d..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModUpdateInfoScreen.kt +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui - -import com.mojang.blaze3d.systems.RenderSystem -import com.terraformersmc.modmenu.util.DrawingUtil -import net.minecraft.client.gui.DrawableHelper -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.gui.screen.ScreenTexts -import net.minecraft.client.gui.widget.ButtonWidget -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.* -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.gui.list.IListScreen -import xyz.deathsgun.modmanager.gui.widget.DescriptionWidget -import xyz.deathsgun.modmanager.update.Update - - -class ModUpdateInfoScreen(private val previousScreen: Screen, private val update: Update) : Screen(LiteralText.EMPTY), - IListScreen { - - private lateinit var descriptionWidget: DescriptionWidget - private lateinit var updateButtonWidget: ButtonWidget - - override fun init() { - descriptionWidget = addSelectableChild( - DescriptionWidget( - client!!, - width - 20, - height - 34, - 79, - height - 30, - textRenderer.fontHeight, - this, - update.version.changelog - ) - ) - descriptionWidget.init() - descriptionWidget.setLeftPos(10) - val buttonX = width / 8 - addDrawableChild(ButtonWidget(buttonX, height - 25, 150, 20, ScreenTexts.BACK) { - client?.setScreen(previousScreen) - }) - updateButtonWidget = addDrawableChild(ButtonWidget( - this.width - buttonX - 150, this.height - 25, 150, 20, TranslatableText("modmanager.button.update") - ) { - client!!.setScreen(ModProgressScreen(update.mod, ModProgressScreen.Action.UPDATE, previousScreen, this)) - }) - } - - override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { - renderBackground(matrices) - descriptionWidget.render(matrices, mouseX, mouseY, delta) - - val iconSize = 64 - ModManager.modManager.icons.bindIcon(update.mod) - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F) - ModManager.modManager.icons.bindIcon(update.mod) - RenderSystem.enableBlend() - DrawableHelper.drawTexture(matrices, 20, 10, 0.0F, 0.0F, iconSize, iconSize, iconSize, iconSize) - RenderSystem.disableBlend() - - val font = client!!.textRenderer - var trimmedTitle: MutableText = LiteralText(font.trimToWidth(update.mod.name, width - 200)) - trimmedTitle = trimmedTitle.setStyle(Style.EMPTY.withBold(true)) - - var detailsY = 15 - var textX = 20 + iconSize + 5 - - font.draw(matrices, trimmedTitle, textX.toFloat(), detailsY.toFloat(), 0xFFFFFF) - - if (update.mod.author != null) { - detailsY += 12 - font.draw( - matrices, - TranslatableText("modmanager.details.author", update.mod.author), - textX.toFloat(), - detailsY.toFloat(), - 0xFFFFFF - ) - } - - detailsY += 12 - font.draw( - matrices, - TranslatableText("modmanager.details.versioning", update.installedVersion, update.version.version), - textX.toFloat(), - detailsY.toFloat(), - 0xFFFFFF - ) - - if (update.mod.license != null) { - detailsY += 12 - DrawingUtil.drawBadge( - matrices, - textX, - detailsY, - font.getWidth(update.mod.license) + 6, - Text.of(update.mod.license).asOrderedText(), - -0x909396, - -0xcecfd1, - 0xCACACA - ) - } - - for (category in update.mod.categories) { - val textWidth: Int = font.getWidth(category.text) + 6 - DrawingUtil.drawBadge( - matrices, - textX, - detailsY + 14, - textWidth, - category.text.asOrderedText(), - -0x909396, - -0xcecfd1, - 0xCACACA - ) - textX += textWidth + 4 - } - - super.render(matrices, mouseX, mouseY, delta) - } - - override fun onClose() { - client?.setScreen(previousScreen) - } - - override fun updateSelectedEntry(widget: Any, entry: E?) { - } - - override fun updateMultipleEntries(widget: Any, entries: ArrayList) { - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModsOverviewScreen.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModsOverviewScreen.kt deleted file mode 100644 index 9ba8646..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/ModsOverviewScreen.kt +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui - -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import net.minecraft.client.gui.Element -import net.minecraft.client.gui.screen.ConfirmScreen -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.gui.screen.ScreenTexts -import net.minecraft.client.gui.widget.ButtonWidget -import net.minecraft.client.gui.widget.CyclingButtonWidget -import net.minecraft.client.gui.widget.TextFieldWidget -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.LiteralText -import net.minecraft.text.TranslatableText -import org.lwjgl.glfw.GLFW -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.gui.list.IListScreen -import xyz.deathsgun.modmanager.api.http.CategoriesResult -import xyz.deathsgun.modmanager.api.http.ModsResult -import xyz.deathsgun.modmanager.api.mod.Category -import xyz.deathsgun.modmanager.api.provider.Sorting -import xyz.deathsgun.modmanager.gui.widget.CategoryListEntry -import xyz.deathsgun.modmanager.gui.widget.CategoryListWidget -import xyz.deathsgun.modmanager.gui.widget.ModListEntry -import xyz.deathsgun.modmanager.gui.widget.ModListWidget -import kotlin.math.min - -class ModsOverviewScreen(private val previousScreen: Screen) : Screen(LiteralText.EMPTY), IListScreen { - - private var query: String = "" - private var selectedMod: ModListEntry? = null - private var selectedCategories: ArrayList = ArrayList() - private var page: Int = 0 - private var limit: Int = 20 - private var scrollPercentage: Double = 0.0 - private lateinit var searchField: TextFieldWidget - private var error: TranslatableText? = null - private var sorting: Sorting = Sorting.RELEVANCE - private lateinit var sortingButtonWidget: CyclingButtonWidget - private lateinit var modList: ModListWidget - private lateinit var categoryList: CategoryListWidget - private lateinit var nextPage: ButtonWidget - private lateinit var previousPage: ButtonWidget - private lateinit var updateAll: ButtonWidget - - @OptIn(DelicateCoroutinesApi::class) - override fun init() { - client!!.keyboard.setRepeatEvents(true) - searchField = this.addSelectableChild( - TextFieldWidget( - textRenderer, - 10, - 10, - 160, - 20, - TranslatableText("modmanager.search") - ) - ) - searchField.setChangedListener { this.query = it } - - sortingButtonWidget = addDrawableChild( - CyclingButtonWidget.builder(Sorting::translations) - .values(Sorting.RELEVANCE, Sorting.DOWNLOADS, Sorting.NEWEST, Sorting.UPDATED) - .build(180, 10, 120, 20, TranslatableText("modmanager.sorting.sort")) - { _: CyclingButtonWidget, sorting: Sorting -> this.sorting = sorting; updateModList() } - ) - updateAll = addDrawableChild( - ButtonWidget(width - 100 - 10, 10, 100, 20, TranslatableText("modmanager.button.updateAll")) { - ModManager.modManager.icons.destroyAll() - client?.setScreen(UpdateAllScreen(this)) - } - ) - updateAll.visible = false - - categoryList = addSelectableChild( - CategoryListWidget( - client!!, - 120, - height, - 35, - height - 30, - client!!.textRenderer.fontHeight + 4, - this - ) - ) - categoryList.setLeftPos(10) - - modList = addSelectableChild(ModListWidget(client!!, width - 10 - 115, height, 35, height - 30, 36, this)) - modList.setLeftPos(135) - - addDrawableChild(ButtonWidget(10, height - 25, 120, 20, ScreenTexts.BACK) { - onClose() - }) - - val middle = (width - 135) / 2 - val buttonWidth = min((width - 135 - 20) / 2, 200) - - previousPage = addDrawableChild( - ButtonWidget( - middle - 5, - height - 25, - buttonWidth, - 20, - TranslatableText("modmanager.page.previous") - ) { showPreviousPage() }) - nextPage = addDrawableChild( - ButtonWidget( - middle + buttonWidth + 5, - height - 25, - buttonWidth, - 20, - TranslatableText("modmanager.page.next") - ) { showNextPage() }) - - GlobalScope.launch { - val provider = ModManager.modManager.getSelectedProvider() ?: return@launch - when (val result = provider.getCategories()) { - is CategoriesResult.Error -> { - error = result.text - return@launch - } - is CategoriesResult.Success -> { - categoryList.clear() - if (ModManager.modManager.update.getWhitelistedUpdates().isNotEmpty()) { - categoryList.add(Category("updatable", TranslatableText("modmanager.category.updatable"))) - } - categoryList.addCategories(result.categories) - modList.scrollAmount = scrollPercentage - } - } - if (selectedCategories.isNotEmpty()) { - if (selectedCategories.any { it.category.id == "updatable" } && ModManager.modManager.update.updates.isEmpty()) { - categoryList.setSelectedByIndex(0) - showModsByCategory() - return@launch - } - categoryList.setSelected(selectedCategories) - showModsByCategory() - modList.scrollAmount = scrollPercentage - return@launch - } - if (query.isNotEmpty()) { - showModsBySearch() - modList.scrollAmount = scrollPercentage - return@launch - } - showModsByCategory() - modList.scrollAmount = scrollPercentage - } - } - - private fun showNextPage() { - this.page++ - modList.scrollAmount = 0.0 - updateModList() - } - - private fun showPreviousPage() { - this.page-- - modList.scrollAmount = 0.0 - if (this.page < 0) { - page = 0 - } - updateModList() - } - - private fun updateModList() { - if (query.isNotBlank()) { - showModsBySearch() - return - } - showModsByCategory() - } - - private fun showModsByCategory() { - query = "" - val provider = ModManager.modManager.getSelectedProvider() ?: return - if (selectedCategories.any { it.id == "updatable" }) { - modList.clear() - ModManager.modManager.update.getWhitelistedUpdates().forEach { - modList.add(it.mod) - } - return - } - when (val result = provider.getMods(selectedCategories.map { it.category }, sorting, page, limit)) { - is ModsResult.Error -> { - error = result.text - } - is ModsResult.Success -> { - error = null - modList.setMods(result.mods) - } - } - } - - override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { - if (this.searchField.isFocused && keyCode == GLFW.GLFW_KEY_ENTER) { - page = 0 - this.modList.scrollAmount = 0.0 - showModsBySearch() - return true - } - return super.keyPressed(keyCode, scanCode, modifiers) - } - - private fun showModsBySearch() { - val provider = ModManager.modManager.getSelectedProvider() ?: return - when (val result = provider.search(this.query, selectedCategories.map { it.category }, sorting, page, limit)) { - is ModsResult.Error -> { - this.error = result.text - } - is ModsResult.Success -> { - this.error = null - this.modList.setMods(result.mods) - } - } - } - - override fun getFocused(): Element? { - return super.getFocused() - } - - override fun updateSelectedEntry(widget: Any, entry: E?) { - if (widget !is ModListWidget) { - return - } - if (entry == null) { - return - } - if (selectedMod == entry) { - if (selectedCategories.any { it.id == "updatable" } && query.isEmpty()) { - val update = ModManager.modManager.update.getUpdateForMod(selectedMod!!.mod) ?: return - client?.setScreen(ModUpdateInfoScreen(this, update)) - return - } - client?.setScreen(ModDetailScreen(this, selectedMod!!.mod)) - return - } - selectedMod = entry as ModListEntry - } - - override fun updateMultipleEntries(widget: Any, entries: ArrayList) { - if (widget !is CategoryListWidget) { - return - } - modList.scrollAmount = 0.0 - page = 0 - @Suppress("UNCHECKED_CAST") - selectedCategories = entries as ArrayList - query = "" - if (selectedCategories.any { it.id == "updatable" } && selectedCategories.size > 1) { - val last = selectedCategories.last() - if (last.id == "updatable") { - selectedCategories.removeIf { it.category.id != "updatable" } - } else { - selectedCategories.removeIf { it.category.id == "updatable" } - } - categoryList.setSelected(selectedCategories) - return - } - showModsByCategory() - } - - override fun tick() { - super.tick() - if (error != null) { - client!!.setScreen(ErrorScreen(previousScreen, this, error!!)) - } - this.scrollPercentage = modList.scrollAmount - this.searchField.tick() - this.previousPage.active = page > 0 - this.nextPage.active = this.modList.getElementCount() >= limit - this.updateAll.visible = this.selectedCategories.any { it.id == "updatable" } - } - - override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { - this.renderBackground(matrices) - this.categoryList.render(matrices, mouseX, mouseY, delta) - this.modList.render(matrices, mouseX, mouseY, delta) - this.searchField.render(matrices, mouseX, mouseY, delta) - super.render(matrices, mouseX, mouseY, delta) - } - - override fun onClose() { - ModManager.modManager.icons.destroyAll() - if (!ModManager.modManager.changed) { - client!!.setScreen(previousScreen) - return - } - client!!.setScreen( - ConfirmScreen( - { - if (it) { - client!!.scheduleStop() - return@ConfirmScreen - } - client!!.setScreen(previousScreen) - }, - TranslatableText("modmanager.changes.title"), - TranslatableText("modmanager.changes.message") - ) - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/UpdateAllScreen.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/UpdateAllScreen.kt deleted file mode 100644 index 9490e09..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/UpdateAllScreen.kt +++ /dev/null @@ -1,84 +0,0 @@ -package xyz.deathsgun.modmanager.gui - -import kotlinx.coroutines.DelicateCoroutinesApi -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.gui.screen.ScreenTexts -import net.minecraft.client.gui.widget.ButtonWidget -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.gui.list.IListScreen -import xyz.deathsgun.modmanager.gui.widget.UpdateProgressListWidget -import xyz.deathsgun.modmanager.update.Update -import kotlin.math.min - -class UpdateAllScreen(private val parentScreen: Screen) : Screen(TranslatableText("modmanager.title.updating")), - IListScreen { - - private lateinit var updateList: UpdateProgressListWidget - private lateinit var doneButton: ButtonWidget - private var updated = ArrayList() - - @OptIn(DelicateCoroutinesApi::class) - override fun init() { - updateList = UpdateProgressListWidget( - client!!, - width - 50, - height - 40, - 25, - height - 50, - textRenderer.fontHeight + 4, - this - ) - updateList.setLeftPos(25) - doneButton = addDrawableChild(ButtonWidget(width / 2 - 100, height - 30, 200, 20, ScreenTexts.DONE) { - onClose() - }) - doneButton.active = false - } - - override fun render(matrices: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) { - renderBackground(matrices) - updateList.render(matrices, mouseX, mouseY, delta) - textRenderer.draw(matrices, title, (width / 2 - textRenderer.getWidth(title) / 2).toFloat(), 10F, 0xFFFFFF) - super.render(matrices, mouseX, mouseY, delta) - } - - override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean { - return updateList.mouseScrolled(mouseX, mouseY, amount) - } - - override fun tick() { - updateList.tick() - val pendingUpdates = getPendingUpdates() - if (pendingUpdates.isEmpty()) { - doneButton.active = true - } - if (pendingUpdates.isEmpty() || !updateList.children().all { it.progress == 1.0 }) { - return - } - for (i in 0..min(1, pendingUpdates.size - 1)) { - val update = pendingUpdates[i] - updated.add(update.mod.id) - updateList.add(update) - updateList.scrollAmount = updateList.maxScroll.toDouble() - } - } - - private fun getPendingUpdates(): List { - return ModManager.modManager.update.getWhitelistedUpdates().filter { - !updated.contains(it.mod.id) - } - } - - override fun onClose() { - client?.setScreen(parentScreen) - } - - override fun updateSelectedEntry(widget: Any, entry: E?) { - } - - override fun updateMultipleEntries(widget: Any, entries: ArrayList) { - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/CategoryListEntry.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/CategoryListEntry.kt deleted file mode 100644 index fbd1fcc..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/CategoryListEntry.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui.widget - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.OrderedText -import net.minecraft.text.Text -import net.minecraft.util.Language -import xyz.deathsgun.modmanager.api.gui.list.MultiSelectListWidget -import xyz.deathsgun.modmanager.api.mod.Category - - -class CategoryListEntry(list: MultiSelectListWidget, val category: Category) : - MultiSelectListWidget.Entry(list, category.id) { - - override fun render( - matrices: MatrixStack?, - index: Int, - y: Int, - x: Int, - entryWidth: Int, - entryHeight: Int, - mouseX: Int, - mouseY: Int, - hovered: Boolean, - tickDelta: Float - ) { - val font = MinecraftClient.getInstance().textRenderer - var text: Text = category.text - if (list.isSelectedEntry(this)) { - text = text.getWithStyle(text.style.withBold(true))[0] - } - val trimmedText: OrderedText = Language.getInstance().reorder(font.trimToWidth(text, entryWidth - 10)) - font.draw(matrices, trimmedText, (x + 3).toFloat(), (y + 1).toFloat(), 0xFFFFFF) - } - - override fun getNarration(): Text { - return category.text - } - -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/CategoryListWidget.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/CategoryListWidget.kt deleted file mode 100644 index 80ba9fa..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/CategoryListWidget.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui.widget - -import net.minecraft.client.MinecraftClient -import xyz.deathsgun.modmanager.api.gui.list.IListScreen -import xyz.deathsgun.modmanager.api.gui.list.MultiSelectListWidget -import xyz.deathsgun.modmanager.api.mod.Category - -class CategoryListWidget( - client: MinecraftClient, - width: Int, - height: Int, - top: Int, - bottom: Int, - itemHeight: Int, - parent: IListScreen -) : MultiSelectListWidget(client, width, height, top, bottom, itemHeight, parent) { - - fun addCategories(categories: List) { - categories.forEach { - addEntry(CategoryListEntry(this, it)) - } - } - - fun setSelectedByIndex(index: Int) { - setSelected(getEntry(index)) - } - - fun clear() { - clearEntries() - } - - fun add(category: Category) { - addEntry(CategoryListEntry(this, category)) - } -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/ModListEntry.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/ModListEntry.kt deleted file mode 100644 index 9af9a8f..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/ModListEntry.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui.widget - -import com.mojang.blaze3d.systems.RenderSystem -import com.terraformersmc.modmenu.util.DrawingUtil -import net.minecraft.client.MinecraftClient -import net.minecraft.client.gui.DrawableHelper -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.* -import net.minecraft.util.Language -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.gui.list.ListWidget -import xyz.deathsgun.modmanager.api.mod.Mod -import xyz.deathsgun.modmanager.api.mod.State - - -class ModListEntry(private val client: MinecraftClient, override val list: ModListWidget, val mod: Mod) : - ListWidget.Entry(list, mod.id) { - - private val state = ModManager.modManager.getModState(mod.id) - - override fun render( - matrices: MatrixStack?, index: Int, y: Int, x: Int, entryWidth: Int, entryHeight: Int, - mouseX: Int, mouseY: Int, hovered: Boolean, tickDelta: Float - ) { - val iconSize = 32 - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f) - ModManager.modManager.icons.bindIcon(mod) - RenderSystem.enableBlend() - DrawableHelper.drawTexture(matrices, x, y, 0.0f, 0.0f, iconSize, iconSize, iconSize, iconSize) - RenderSystem.disableBlend() - val name: Text = LiteralText(mod.name) - var trimmedName: StringVisitable = name - var maxNameWidth = entryWidth - iconSize - 3 - val font = this.client.textRenderer - var primaryColor = 0xFFFFFF - var secondaryColor = 0xFFFFFF - var badgeText: OrderedText? = null - if (state == State.INSTALLED) { - primaryColor = 0xff0e2a55.toInt() - secondaryColor = 0xff2b4b7c.toInt() - badgeText = TranslatableText("modmanager.badge.installed").asOrderedText() - maxNameWidth -= font.getWidth(badgeText) + 6 - } else if (state == State.OUTDATED) { - primaryColor = 0xff530C17.toInt() - secondaryColor = 0xff841426.toInt() - badgeText = TranslatableText("modmanager.badge.outdated").asOrderedText() - maxNameWidth -= font.getWidth(badgeText) + 6 - } - - val textWidth = font.getWidth(name) - if (textWidth > maxNameWidth) { - val ellipsis = StringVisitable.plain("...") - trimmedName = - StringVisitable.concat(font.trimToWidth(name, maxNameWidth - font.getWidth(ellipsis)), ellipsis) - } - font.draw( - matrices, - Language.getInstance().reorder(trimmedName), - (x + iconSize + 3).toFloat(), - (y + 1).toFloat(), - 0xFFFFFF - ) - if (badgeText != null) { - DrawingUtil.drawBadge( - matrices, - x + iconSize + 3 + textWidth + 3, - y + 1, - font.getWidth(badgeText) + 6, - badgeText, - secondaryColor, - primaryColor, - 0xFFFFFF - ) - } - - DrawingUtil.drawWrappedString( - matrices, - mod.shortDescription, - (x + iconSize + 3 + 4), - (y + client.textRenderer.fontHeight + 4), - entryWidth - iconSize - 7, - 2, - 0x808080 - ) - } - - override fun getNarration(): Text { - return LiteralText(mod.name) - } - -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/ModListWidget.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/ModListWidget.kt deleted file mode 100644 index ef69e6e..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/ModListWidget.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui.widget - -import net.minecraft.client.MinecraftClient -import xyz.deathsgun.modmanager.api.gui.list.IListScreen -import xyz.deathsgun.modmanager.api.gui.list.ListWidget -import xyz.deathsgun.modmanager.api.mod.Mod - -class ModListWidget( - client: MinecraftClient, - width: Int, - height: Int, - top: Int, - bottom: Int, - itemHeight: Int, - parent: IListScreen -) : ListWidget(client, width, height, top, bottom, itemHeight, parent) { - - fun setMods(mods: List) { - this.clearEntries() - mods.forEach { - this.addEntry(ModListEntry(client, this, it)) - } - } - - fun clear() { - this.clearEntries() - } - - fun add(mod: Mod) { - this.addEntry(ModListEntry(client, this, mod)) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/TexturedButton.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/TexturedButton.kt deleted file mode 100644 index 0ed4c23..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/TexturedButton.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.gui.widget - -import com.mojang.blaze3d.systems.RenderSystem -import com.terraformersmc.modmenu.gui.widget.ModMenuTexturedButtonWidget -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.LiteralText -import net.minecraft.util.Identifier - -class TexturedButton( - x: Int, - y: Int, - width: Int, - height: Int, - private val u: Int, - private val v: Int, - texture: Identifier, - private val uWidth: Int, - private val vHeight: Int, - onPress: PressAction?, - tooltipSupplier: TooltipSupplier -) : ModMenuTexturedButtonWidget( - x, - y, - width, - height, - u, - v, - texture, - uWidth, - vHeight, - onPress, - LiteralText.EMPTY, - tooltipSupplier -) { - - var image: Identifier = texture - - override fun renderButton(matrices: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) { - RenderSystem.setShaderColor(1f, 1f, 1f, 1f) - RenderSystem.setShaderTexture(0, image) - RenderSystem.disableDepthTest() - var adjustedV = v - if (!active) { - adjustedV += height * 2 - } else if (this.isHovered) { - adjustedV += height - } - drawTexture( - matrices, - x, y, u.toFloat(), adjustedV.toFloat(), width, height, uWidth, vHeight - ) - RenderSystem.enableDepthTest() - if (this.isHovered) { - renderTooltip(matrices, mouseX, mouseY) - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/UpdateProgressListEntry.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/UpdateProgressListEntry.kt deleted file mode 100644 index 7836801..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/UpdateProgressListEntry.kt +++ /dev/null @@ -1,83 +0,0 @@ -package xyz.deathsgun.modmanager.gui.widget - -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import net.minecraft.client.MinecraftClient -import net.minecraft.client.gui.DrawableHelper -import net.minecraft.client.gui.screen.ScreenTexts -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.LiteralText -import net.minecraft.text.Text -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.gui.list.ListWidget -import xyz.deathsgun.modmanager.update.ProgressListener -import xyz.deathsgun.modmanager.update.Update - -@OptIn(DelicateCoroutinesApi::class) -class UpdateProgressListEntry(list: ListWidget, val update: Update) : - ListWidget.Entry(list, update.mod.id), ProgressListener { - - internal var progress = 0.0 - private var pos = 0 - - init { - GlobalScope.launch { - delay(200) - ModManager.modManager.update.updateMod(update) { this@UpdateProgressListEntry.progress = it } - } - } - - override fun render( - matrices: MatrixStack, - index: Int, - y: Int, - x: Int, - entryWidth: Int, - entryHeight: Int, - mouseX: Int, - mouseY: Int, - hovered: Boolean, - tickDelta: Float - ) { - val textRenderer = MinecraftClient.getInstance().textRenderer - val infoText = "${update.mod.name} v${update.installedVersion} to ${update.version.version}" - textRenderer.draw(matrices, infoText, x.toFloat(), y + 1f, 0xFFFFFF) - val infoTextWidth = textRenderer.getWidth(infoText) + 5 - if (progress == 1.0) { - textRenderer.draw(matrices, ScreenTexts.DONE, (x + entryWidth - textRenderer.getWidth(ScreenTexts.DONE)).toFloat(), y + 1f, 0xFFFFFF) - return - } - renderProgressBar(matrices, entryWidth - infoTextWidth, x + infoTextWidth, y, x + entryWidth, y + entryHeight) - } - - fun tick() { - pos += 5 - } - - override fun onProgress(progress: Double) { - this.progress = progress - } - - private fun renderProgressBar(matrices: MatrixStack, width: Int, minX: Int, minY: Int, maxX: Int, maxY: Int) { - val color = 0xFFFFFFFF.toInt() - var barWidth = width / 10 - val overlap = (minX + pos + barWidth) - maxX + 2 - if (overlap > 0) { - barWidth -= overlap - } - if ((minX + pos) - maxX + 2 > 0) { - pos = 0 - } - DrawableHelper.fill(matrices, minX + 2 + pos, minY + 2, minX + pos + barWidth, maxY - 2, color) - DrawableHelper.fill(matrices, minX + 1, minY, maxX - 1, minY + 1, color) - DrawableHelper.fill(matrices, minX + 1, maxY, maxX - 1, maxY - 1, color) - DrawableHelper.fill(matrices, minX, minY, minX + 1, maxY, color) - DrawableHelper.fill(matrices, maxX, minY, maxX - 1, maxY, color) - } - - override fun getNarration(): Text { - return LiteralText.EMPTY - } -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/UpdateProgressListWidget.kt b/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/UpdateProgressListWidget.kt deleted file mode 100644 index f390008..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/gui/widget/UpdateProgressListWidget.kt +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.deathsgun.modmanager.gui.widget - -import net.minecraft.client.MinecraftClient -import xyz.deathsgun.modmanager.api.gui.list.IListScreen -import xyz.deathsgun.modmanager.api.gui.list.ListWidget -import xyz.deathsgun.modmanager.update.Update - -class UpdateProgressListWidget( - client: MinecraftClient, - width: Int, - height: Int, - top: Int, - bottom: Int, - itemHeight: Int, - parent: IListScreen -) : ListWidget(client, width, height, top, bottom, itemHeight, parent) { - - override fun isSelectedEntry(entry: Entry): Boolean { - return false - } - - override fun isSelectedEntry(index: Int): Boolean { - return false - } - - fun tick() { - for (child in children()) { - child.tick() - } - } - - fun add(update: Update) { - addEntry(UpdateProgressListEntry(this, update)) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/models/FabricMetadata.kt b/src/main/kotlin/xyz/deathsgun/modmanager/models/FabricMetadata.kt deleted file mode 100644 index a4a252d..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/models/FabricMetadata.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.models - -import kotlinx.serialization.Serializable - -@Serializable -data class FabricMetadata( - val id: String, - val name: String, - val custom: Custom = Custom(emptyMap()) -) { - @Serializable - data class Custom( - val modmanager: Map = emptyMap() - ) -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/Modrinth.kt b/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/Modrinth.kt deleted file mode 100644 index ba03172..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/Modrinth.kt +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.providers.modrinth - -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json -import net.minecraft.text.TranslatableText -import org.apache.http.client.utils.URIBuilder -import org.apache.logging.log4j.LogManager -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.http.CategoriesResult -import xyz.deathsgun.modmanager.api.http.ModResult -import xyz.deathsgun.modmanager.api.http.ModsResult -import xyz.deathsgun.modmanager.api.http.VersionResult -import xyz.deathsgun.modmanager.api.mod.* -import xyz.deathsgun.modmanager.api.provider.IModProvider -import xyz.deathsgun.modmanager.api.provider.IModUpdateProvider -import xyz.deathsgun.modmanager.api.provider.Sorting -import xyz.deathsgun.modmanager.providers.modrinth.models.DetailedMod -import xyz.deathsgun.modmanager.providers.modrinth.models.ModrinthVersion -import xyz.deathsgun.modmanager.providers.modrinth.models.SearchResult -import java.net.URI -import java.net.http.HttpClient -import java.net.http.HttpRequest -import java.net.http.HttpResponse -import java.time.Duration -import java.time.Instant -import java.time.ZoneOffset - -@OptIn(ExperimentalSerializationApi::class) -class Modrinth : IModProvider, IModUpdateProvider { - - private val logger = LogManager.getLogger("Modrinth") - private val categories: ArrayList = ArrayList() - private val baseUri = "https://api.modrinth.com" - private val http = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build() - - - override fun getName(): String { - return "Modrinth" - } - - override fun getCategories(): CategoriesResult { - if (this.categories.isNotEmpty()) { - return CategoriesResult.Success(this.categories) - } - val request = HttpRequest.newBuilder().GET().setHeader("User-Agent", "ModManager " + ModManager.getVersion()) - .uri(URI.create("${baseUri}/api/v1/tag/category")).build() - return try { - val response = this.http.send(request, HttpResponse.BodyHandlers.ofString()) - val categories = json.decodeFromString>(response.body()) - for (category in categories) { - if (category == "fabric") { // Fabric is not really a category - continue - } - this.categories.add( - Category( - category, - TranslatableText(String.format("modmanager.category.%s", category)) - ) - ) - } - CategoriesResult.Success(this.categories) - } catch (e: Exception) { - logger.error("Error while getting categories: {}", e.message) - CategoriesResult.Error(TranslatableText("modmanager.error.failedToParse", e.message), e) - } - } - - override fun getMods(sorting: Sorting, page: Int, limit: Int): ModsResult { - val builder = URIBuilder("${baseUri}/api/v1/mod") - builder.addParameter("filters", "categories=\"fabric\" AND NOT client_side=\"unsupported\"") - return getMods(builder, sorting, page, limit) - } - - override fun getMods(categories: List, sorting: Sorting, page: Int, limit: Int): ModsResult { - val builder = URIBuilder("${baseUri}/api/v1/mod") - builder.addParameter( - "filters", - "categories=\"fabric\" AND NOT client_side=\"unsupported\"${filterFromCategories(categories)}" - ) - - return try { - getMods(builder, sorting, page, limit) - } catch (e: Exception) { - ModsResult.Error(TranslatableText("modmanager.error.unknown", e.message), e) - } - } - - override fun search( - query: String, - categories: List, - sorting: Sorting, - page: Int, - limit: Int - ): ModsResult { - val builder = URIBuilder("${baseUri}/api/v1/mod") - builder.addParameter("query", query) - builder.addParameter( - "filters", - "categories=\"fabric\" AND NOT client_side=\"unsupported\"${filterFromCategories(categories)}" - ) - return try { - getMods(builder, sorting, page, limit) - } catch (e: Exception) { - ModsResult.Error(TranslatableText("modmanager.error.unknown", e.message), e) - } - } - - private fun filterFromCategories(categories: List): String { - var categoriesFilter = "" - for (category in categories) { - categoriesFilter += "AND categories=\"${category.id}\"" - } - categoriesFilter = categoriesFilter.replaceFirst("AND ", " AND (") - if (categories.isNotEmpty()) { - categoriesFilter += ")" - } - return categoriesFilter - } - - private fun getMods(builder: URIBuilder, sorting: Sorting, page: Int, limit: Int): ModsResult { - builder.addParameter( - "version", - String.format( - "versions=\"%s\" OR versions=\"%s\"", - ModManager.getMinecraftReleaseTarget(), - ModManager.getMinecraftVersionId() - ) - ) - builder.addParameter("index", sorting.name.lowercase()) - builder.addParameter("offset", (page * limit).toString()) - builder.addParameter("limit", limit.toString()) - val request = HttpRequest.newBuilder().GET().setHeader("User-Agent", "ModManager " + ModManager.getVersion()) - .uri(builder.build()).build() - val response = this.http.send(request, HttpResponse.BodyHandlers.ofString()) - if (response.statusCode() != 200) { - return ModsResult.Error(TranslatableText("modmanager.error.invalidStatus", response.statusCode())) - } - return try { - val result = json.decodeFromString(response.body()) - ModsResult.Success(result.toList()) - } catch (e: Exception) { - logger.error("Error while requesting mods {}", e.message) - ModsResult.Error(TranslatableText("modmanager.error.failedToParse", e.message)) - } - } - - private val json = Json { - this.ignoreUnknownKeys = true - } - - override fun getMod(id: String): ModResult { - id.replaceFirst("local-", "") - val request = HttpRequest.newBuilder().GET() - .setHeader("User-Agent", "ModManager " + ModManager.getVersion()) - .uri(URI.create("${baseUri}/api/v1/mod/${id}")).build() - val response = try { - this.http.send(request, HttpResponse.BodyHandlers.ofString()) - } catch (e: Exception) { - logger.error("Error while getting mod {}", e.message) - return ModResult.Error(TranslatableText("modmanager.error.network", e.message), e) - } - if (response.statusCode() != 200) { - return ModResult.Error(TranslatableText("modmanager.error.invalidStatus", response.statusCode())) - } - return try { - val result = json.decodeFromString(response.body()) - val categoriesList = ArrayList() - result.categories.forEach { categoryId -> - categoriesList.add( - Category( - categoryId, - TranslatableText("modmanager.category.${categoryId}") - ) - ) - } - ModResult.Success( - Mod( - id = result.id.replaceFirst("local-", ""), - slug = result.slug, - author = null, - name = result.title, - shortDescription = result.description, - iconUrl = result.iconUrl, - description = result.body, - license = result.license.name, - categories = categoriesList - ) - ) - } catch (e: Exception) { - ModResult.Error(TranslatableText("modmanager.error.failedToParse", e.message), e) - } - } - - override fun getVersionsForMod(id: String): VersionResult { - val request = HttpRequest.newBuilder().GET() - .setHeader("User-Agent", "ModManager " + ModManager.getVersion()) - .uri(URI.create("${baseUri}/api/v1/mod/${id}/version")).build() - val response = try { - this.http.send(request, HttpResponse.BodyHandlers.ofString()) - } catch (e: Exception) { - logger.error("Error while getting mod {}", e.message) - return VersionResult.Error(TranslatableText("modmanager.error.network", e.message), e) - } - if (response.statusCode() != 200) { - return VersionResult.Error(TranslatableText("modmanager.error.invalidStatus", response.statusCode())) - } - return try { - val modrinthVersions = json.decodeFromString>(response.body()) - val versions = ArrayList() - for (modVersion in modrinthVersions) { - if (!modVersion.loaders.contains("fabric")) { - continue - } - val assets = ArrayList() - for (file in modVersion.files) { - assets.add(Asset(file.url, file.filename, file.hashes, file.primary)) - } - versions.add( - Version( - modVersion.version, - modVersion.changelog, - // 2021-09-03T10:56:59.402790Z - Instant.parse(modVersion.releaseDate).atOffset( - ZoneOffset.UTC - ).toLocalDate(), - getVersionType(modVersion.type), - modVersion.gameVersions, - assets - ) - ) - } - VersionResult.Success(versions) - } catch (e: Exception) { - VersionResult.Error(TranslatableText("modmanager.error.failedToParse", e.message), e) - } - } - - private fun getVersionType(id: String): VersionType { - return when (id) { - "release" -> VersionType.RELEASE - "alpha" -> VersionType.ALPHA - "beta" -> VersionType.BETA - else -> VersionType.UNKNOWN - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/DetailedMod.kt b/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/DetailedMod.kt deleted file mode 100644 index 13bd25f..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/DetailedMod.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.providers.modrinth.models - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class DetailedMod( - val id: String, - val slug: String, - val title: String, - val description: String, - val body: String, - val license: License, - val categories: List, - @SerialName("icon_url") - val iconUrl: String? -) { - @Serializable - data class License(val name: String) -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/ModResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/ModResult.kt deleted file mode 100644 index ad1e354..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/ModResult.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.providers.modrinth.models - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class ModResult( - @SerialName("mod_id") - val id: String, - val slug: String, - val author: String, - val title: String, - val description: String, - @SerialName("icon_url") - val iconUrl: String?, - val categories: ArrayList -) diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/ModrinthVersion.kt b/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/ModrinthVersion.kt deleted file mode 100644 index c0d4cf7..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/ModrinthVersion.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.providers.modrinth.models - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class ModrinthVersion( - @SerialName("version_number") - val version: String, - val changelog: String, - @SerialName("date_published") - val releaseDate: String, - @SerialName("version_type") - val type: String, - @SerialName("game_versions") - val gameVersions: List, - val files: List, - val loaders: List, -) { - @Serializable - data class File( - val hashes: Map, - val filename: String, - val url: String, - val primary: Boolean - ) -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/SearchResult.kt b/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/SearchResult.kt deleted file mode 100644 index e751e79..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/SearchResult.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.providers.modrinth.models - -import kotlinx.serialization.Serializable -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.api.mod.Category -import xyz.deathsgun.modmanager.api.mod.Mod - -@Serializable -data class SearchResult( - val hits: List -) { - fun toList(): List { - val mods = ArrayList() - for (mod in hits) { - val categoriesList = ArrayList() - mod.categories.forEach { categoryId -> - categoriesList.add( - Category( - categoryId, - TranslatableText("modmanager.category.${categoryId}") - ) - ) - } - mods.add( - Mod( - mod.id.replaceFirst("local-", ""), - mod.slug, - mod.author, - mod.title, - mod.description, - mod.iconUrl, - null, - null, - categoriesList, - ) - ) - } - return mods - } -} diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/state/SavedState.kt b/src/main/kotlin/xyz/deathsgun/modmanager/state/SavedState.kt deleted file mode 100644 index a3bdc4b..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/state/SavedState.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.state - -import xyz.deathsgun.modmanager.api.mod.State - -data class SavedState( - val fabricId: String, - val modId: String, - val state: State -) diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/update/ProgressListener.kt b/src/main/kotlin/xyz/deathsgun/modmanager/update/ProgressListener.kt deleted file mode 100644 index f79b78b..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/update/ProgressListener.kt +++ /dev/null @@ -1,7 +0,0 @@ -package xyz.deathsgun.modmanager.update - -interface ProgressListener { - - fun onProgress(progress: Double) - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/update/Update.kt b/src/main/kotlin/xyz/deathsgun/modmanager/update/Update.kt deleted file mode 100644 index e2fa239..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/update/Update.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.update - -import xyz.deathsgun.modmanager.api.mod.Mod -import xyz.deathsgun.modmanager.api.mod.Version - -data class Update(val mod: Mod, val fabricId: String, val installedVersion: String, val version: Version) diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/update/UpdateManager.kt b/src/main/kotlin/xyz/deathsgun/modmanager/update/UpdateManager.kt deleted file mode 100644 index 32c226d..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/update/UpdateManager.kt +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.update - -import com.terraformersmc.modmenu.util.mod.fabric.CustomValueUtil -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.runBlocking -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import net.fabricmc.loader.api.FabricLoader -import net.fabricmc.loader.api.metadata.ModMetadata -import net.minecraft.client.MinecraftClient -import net.minecraft.client.toast.SystemToast -import net.minecraft.text.TranslatableText -import org.apache.commons.io.FileUtils -import org.apache.logging.log4j.LogManager -import xyz.deathsgun.modmanager.ModManager -import xyz.deathsgun.modmanager.api.ModInstallResult -import xyz.deathsgun.modmanager.api.ModRemoveResult -import xyz.deathsgun.modmanager.api.ModUpdateResult -import xyz.deathsgun.modmanager.api.http.HttpClient -import xyz.deathsgun.modmanager.api.http.ModResult -import xyz.deathsgun.modmanager.api.http.ModsResult -import xyz.deathsgun.modmanager.api.http.VersionResult -import xyz.deathsgun.modmanager.api.mod.Mod -import xyz.deathsgun.modmanager.api.mod.State -import xyz.deathsgun.modmanager.api.mod.Version -import xyz.deathsgun.modmanager.api.provider.IModUpdateProvider -import xyz.deathsgun.modmanager.api.provider.Sorting -import xyz.deathsgun.modmanager.models.FabricMetadata -import java.io.File -import java.math.BigInteger -import java.net.URI -import java.nio.file.Files -import java.nio.file.Path -import java.security.MessageDigest -import java.util.zip.ZipFile -import kotlin.io.path.absolutePathString - - -class UpdateManager { - - private val logger = LogManager.getLogger("UpdateCheck") - private val blockedIds = arrayOf("java", "minecraft", "fabricloader") - private val deletableMods = ArrayList() - val updates = ArrayList() - var finishedUpdateCheck = false - - init { - Runtime.getRuntime().addShutdownHook(Thread(this::saveDeletableFiles)) - } - - //region Update Checking - - suspend fun checkUpdates() = runBlocking { - logger.info("Checking for mod updates...") - val mods = getCheckableMods() - mods.map { metadata -> - async { - if (findJarByModContainer(metadata) == null) { - logger.debug("Skipping update for {} because it has no jar in mods", metadata.id) - return@async - } - val configIds = getIdBy(metadata) - if (configIds == null) { - logger.debug("Searching for updates for {} using fallback method", metadata.id) - checkForUpdatesManually(metadata) - return@async - } - logger.debug("Searching for updates for {} using defined mod id", metadata.id) - checkForUpdates(metadata, configIds) - } - }.awaitAll() - finishedUpdateCheck = true - if (MinecraftClient.getInstance()?.currentScreen == null || updates.isEmpty()) { - return@runBlocking - } - MinecraftClient.getInstance().toastManager.add( - SystemToast( - SystemToast.Type.TUTORIAL_HINT, - TranslatableText("modmanager.toast.update.title"), - TranslatableText("modmanager.toast.update.description", getWhitelistedUpdates().size) - ) - ) - } - - private fun checkForUpdatesManually(metadata: ModMetadata) { - ModManager.modManager.setModState(metadata.id, metadata.id, State.INSTALLED) - val defaultProvider = ModManager.modManager.config.defaultProvider - val provider = ModManager.modManager.provider[defaultProvider] - if (provider == null) { - logger.warn("Default provider {} not found", defaultProvider) - return - } - val updateProvider = ModManager.modManager.updateProvider[defaultProvider] - if (updateProvider == null) { - logger.warn("Default update provider {} not found", defaultProvider) - return - } - var result = updateProvider.getVersionsForMod(metadata.id) - if (result is VersionResult.Success) { - val version = VersionFinder.findUpdate( - metadata.version.friendlyString, - ModManager.getMinecraftReleaseTarget(), - ModManager.getMinecraftVersionId(), - ModManager.modManager.config.updateChannel, - result.versions - ) - verifyUpdate(provider, version, metadata, metadata.id) - return - } - - val queryResult = provider.search(metadata.name, emptyList(), Sorting.RELEVANCE, 0, 10) - if (queryResult is ModsResult.Error) { - logger.warn( - "Error while searching for fallback id for mod {}: {}", - metadata.id, - queryResult.cause - ) - ModManager.modManager.setModState(metadata.id, metadata.id, State.INSTALLED) - return - } - val mod = - (queryResult as ModsResult.Success).mods.find { mod -> - mod.slug == metadata.id || mod.name.equals( - metadata.name, - true - ) - } - if (mod == null) { - logger.warn("Error while searching for fallback id for mod {}: No possible match found", metadata.id) - ModManager.modManager.setModState(metadata.id, metadata.id, State.INSTALLED) - return - } - result = updateProvider.getVersionsForMod(mod.id) - val versions = when (result) { - is VersionResult.Error -> { - logger.error("Error while getting versions for mod {}", metadata.id, result.cause) - ModManager.modManager.setModState(metadata.id, mod.id, State.INSTALLED) - return - } - is VersionResult.Success -> result.versions - } - val version = VersionFinder.findUpdate( - metadata.version.friendlyString, - ModManager.getMinecraftReleaseTarget(), - ModManager.getMinecraftVersionId(), - ModManager.modManager.config.updateChannel, - versions - ) - verifyUpdate(provider, version, metadata, mod.id) - } - - private fun checkForUpdates(metadata: ModMetadata, ids: Map) { - ModManager.modManager.setModState(metadata.id, metadata.id, State.INSTALLED) - var provider: IModUpdateProvider? = null - var id: String? = null - for ((provId, modId) in ids) { - val providerId = provId.lowercase() - if (!ModManager.modManager.updateProvider.containsKey(providerId)) { - logger.warn("Update provider {} for {} not found!", providerId, metadata.id) - continue - } - provider = ModManager.modManager.updateProvider[providerId]!! - id = modId - } - if (provider == null || id == null) { - logger.warn("No valid provider for {} found! Skipping", metadata.id) - ModManager.modManager.setModState(metadata.id, id ?: metadata.id, State.INSTALLED) - return - } - val versions = when (val result = provider.getVersionsForMod(id)) { - is VersionResult.Error -> { - logger.error("Error while getting versions for mod {}", metadata.id, result.cause) - ModManager.modManager.setModState(metadata.id, id, State.INSTALLED) - return - } - is VersionResult.Success -> result.versions - } - val version = VersionFinder.findUpdate( - metadata.version.friendlyString, - ModManager.getMinecraftReleaseTarget(), - ModManager.getMinecraftVersionId(), - ModManager.modManager.config.updateChannel, - versions - ) - verifyUpdate(provider, version, metadata, id) - } - - private fun verifyUpdate(provider: IModUpdateProvider, version: Version?, metadata: ModMetadata, modId: String) { - if (version == null) { - logger.info("No update for {} found!", metadata.id) - ModManager.modManager.setModState(metadata.id, modId, State.INSTALLED) - return - } - val hash = findJarByModContainer(metadata)?.sha512() - if (hash != null) { - for (asset in version.assets) { - if (hash == asset.hashes["sha512"]) { - logger.info("No update for {} found!", metadata.id) - ModManager.modManager.setModState(metadata.id, modId, State.INSTALLED) - return - } - } - } - when (val modResult = ModManager.modManager.provider[provider.getName().lowercase()]?.getMod(modId)) { - is ModResult.Success -> { - ModManager.modManager.setModState(metadata.id, modId, State.OUTDATED) - logger.info( - "Update for {} found [{} -> {}]", - metadata.id, - metadata.version.friendlyString, - version.version - ) - this.updates.add(Update(modResult.mod, metadata.id, metadata.version.friendlyString, version)) - } - is ModResult.Error -> { - logger.error("Failed to resolve mod {}: {}", modId, modResult.cause) - ModManager.modManager.setModState(metadata.id, modId, State.INSTALLED) - } - } - } - - fun getUpdateForMod(mod: Mod): Update? { - return this.updates.find { it.mod.id == mod.id || it.fabricId == mod.slug } - } - - fun getWhitelistedUpdates(): List { - return this.updates.filter { !ModManager.modManager.config.hidden.contains(it.fabricId) } - } - //endregion - - fun installMod(mod: Mod): ModInstallResult { - return try { - val provider = ModManager.modManager.getSelectedProvider() - ?: return ModInstallResult.Error( - TranslatableText( - "modmanager.error.noProviderSelected", - ModManager.modManager.config.defaultProvider - ) - ) - val versions = when (val result = provider.getVersionsForMod(mod.id)) { - is VersionResult.Error -> return ModInstallResult.Error(result.text, result.cause) - is VersionResult.Success -> result.versions - } - val version = VersionFinder.findUpdate( - "0.0.0.0", - ModManager.getMinecraftReleaseTarget(), - ModManager.getMinecraftVersionId(), - ModManager.modManager.config.updateChannel, - versions - ) ?: return ModInstallResult.Error(TranslatableText("modmanager.error.noCompatibleModVersionFound")) - - logger.info("Installing {} v{}", mod.name, version.version) - val dir = FabricLoader.getInstance().gameDir.resolve("mods") - when (val result = installVersion(mod, version, dir)) { - is ModUpdateResult.Success -> ModInstallResult.Success - is ModUpdateResult.Error -> ModInstallResult.Error(result.text, result.cause) - } - } catch (e: Exception) { - ModInstallResult.Error(TranslatableText("modmanager.error.unknown.update", e)) - } - } - - private fun installVersion( - mod: Mod, - version: Version, - dir: Path, - fabricId: String = mod.slug, - listener: ((Double) -> Unit)? = null - ): ModUpdateResult { - return try { - val assets = version.assets.filter { - (it.filename.endsWith(".jar") || it.primary) && !it.filename.contains("forge") - } - if (assets.isEmpty()) { - return ModUpdateResult.Error(TranslatableText("modmanager.error.update.noFabricJar")) - } - var asset = assets[0] - if (assets.size > 1) { - asset = assets.find { it.filename.contains(ModManager.getMinecraftReleaseTarget(), true) } - ?: return ModUpdateResult.Error(TranslatableText("modmanager.error.update.noFabricJar")) - } - val jar = dir.resolve(asset.filename) // Download into same directory where the old jar was - HttpClient.download(encodeURI(asset.url), jar, listener) - val expected = asset.hashes["sha512"] - val calculated = jar.sha512() - if (calculated != expected) { - logger.error("The SHA-512 hashes do not match expected {} but got {}", expected, calculated) - jar.delete() - logger.error("Deleting {}", jar.absolutePathString()) - return ModUpdateResult.Error( - TranslatableText( - "modmanager.error.invalidHash", - "SHA-512" - ) - ) - } - ModManager.modManager.setModState(fabricId, mod.id, State.INSTALLED) - this.updates.removeIf { it.fabricId == mod.slug || it.mod.id == mod.id } - ModManager.modManager.changed = true - ModUpdateResult.Success - } catch (e: Exception) { - if (e is HttpClient.InvalidStatusCodeException) { - ModUpdateResult.Error(TranslatableText("modmanager.error.invalidStatus", e.statusCode)) - } - e.printStackTrace() - ModUpdateResult.Error(TranslatableText("modmanager.error.unknown.update", e)) - } - } - - fun updateMod(update: Update, listener: ((Double) -> Unit)? = null): ModUpdateResult { - val oldUpdate = FabricLoader.getInstance().allMods.find { it.metadata.id == update.fabricId } - ?: return ModUpdateResult.Error(TranslatableText("modmanager.error.container.notFound")) - val oldJar = findJarByModContainer(oldUpdate.metadata) - ?: return ModUpdateResult.Error(TranslatableText("modmanager.error.jar.notFound")) - logger.info("Updating {}", update.mod.name) - try { - oldJar.delete() - } catch (e: Exception) { - return ModUpdateResult.Error(TranslatableText("modmanager.error.jar.failedDelete", e)) - } - return installVersion(update.mod, update.version, oldJar.parent, update.fabricId, listener) - } - - private val json = Json { - ignoreUnknownKeys = true - encodeDefaults = true - } - - @OptIn(ExperimentalSerializationApi::class) - fun findJarByModContainer(container: ModMetadata): Path? { - val jars = - FileUtils.listFiles(FabricLoader.getInstance().gameDir.resolve("mods").toFile(), arrayOf("jar"), true) - for (jar in jars) { - try { - val meta = openFabricMeta(jar) - if (meta.id == container.id) { - return jar.toPath() - } - } catch (e: Exception) { - continue - } - } - return null - } - - private fun findJarByMod(mod: Mod): Path? { - val jars = - FileUtils.listFiles(FabricLoader.getInstance().gameDir.resolve("mods").toFile(), arrayOf("jar"), true) - return try { - for (jar in jars) { - val meta = openFabricMeta(jar) - if (meta.id == mod.id || meta.id == mod.slug || meta.id == mod.slug.replace("-", "") || - meta.custom.modmanager[ModManager.modManager.config.defaultProvider] == mod.id || - meta.id.replace("_", "-") == mod.id || - meta.name.equals(mod.name, true) - ) { - return jar.toPath() - } - } - null - } catch (e: Exception) { - null - } - } - - @OptIn(ExperimentalSerializationApi::class) - private fun openFabricMeta(file: File): FabricMetadata { - val jarFile = ZipFile(file) - val fabricEntry = jarFile.getEntry("fabric.mod.json") - val data = jarFile.getInputStream(fabricEntry).bufferedReader().use { it.readText() } - val meta = json.decodeFromString(data) - jarFile.close() - return meta - } - - private fun getIdBy(metadata: ModMetadata): Map? { - if (!metadata.containsCustomValue("modmanager")) { - return null - } - val ids = HashMap() - val map = metadata.getCustomValue("modmanager").asObject - map.forEach { - ids[it.key] = it.value.asString - } - return ids - } - - @OptIn(ExperimentalSerializationApi::class) - private fun saveDeletableFiles() { - if (deletableMods.isEmpty()) { - return - } - logger.info("Deleting {} mods on the next start", deletableMods.size) - val configFile = FabricLoader.getInstance().configDir.resolve(".modmanager.delete.json") - val data = json.encodeToString(deletableMods) - Files.writeString(configFile, data, Charsets.UTF_8) - } - - - private fun getCheckableMods(): List { - return FabricLoader.getInstance().allMods.map { it.metadata }.filter { - !it.id.startsWith("fabric-") && - !CustomValueUtil.getBoolean("fabric-loom:generated", it).orElse(false) && - !hasDisabledUpdates(it) && - !blockedIds.contains(it.id) - } - } - - private fun hasDisabledUpdates(meta: ModMetadata): Boolean { - if (!meta.containsCustomValue("modmanager")) { - return false - } - val modmanager = meta.getCustomValue("modmanager").asObject - return modmanager.containsKey("disable-checking") && modmanager.get("disable-checking").asBoolean - } - - private fun Path.delete() { - try { - Files.delete(this) - } catch (e: Exception) { - logger.info("Error while deleting {} trying on restart again", this.absolutePathString()) - deletableMods.add(this.absolutePathString()) - } - } - - private fun Path.sha512(): String { - val md: MessageDigest = MessageDigest.getInstance("SHA-512") - val messageDigest = md.digest(Files.readAllBytes(this)) - val no = BigInteger(1, messageDigest) - var hashText: String = no.toString(16) - while (hashText.length < 128) { - hashText = "0$hashText" - } - return hashText - } - - fun removeMod(mod: Mod): ModRemoveResult { - val jar = findJarByMod(mod) - ?: return ModRemoveResult.Error(TranslatableText("modmanager.error.jar.notFound")) - return try { - jar.delete() - ModManager.modManager.setModState(mod.slug, mod.id, State.DOWNLOADABLE) - ModRemoveResult.Success - } catch (e: Exception) { - return ModRemoveResult.Error(TranslatableText("modmanager.error.jar.failedDelete", e)) - } - } - - private fun encodeURI(url: String): String { - return URI("dummy", url.replace("\t", ""), null).rawSchemeSpecificPart - } - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/deathsgun/modmanager/update/VersionFinder.kt b/src/main/kotlin/xyz/deathsgun/modmanager/update/VersionFinder.kt deleted file mode 100644 index 92d59df..0000000 --- a/src/main/kotlin/xyz/deathsgun/modmanager/update/VersionFinder.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.update - -import net.fabricmc.loader.api.SemanticVersion -import net.fabricmc.loader.api.VersionParsingException -import xyz.deathsgun.modmanager.api.mod.Version -import xyz.deathsgun.modmanager.config.Config - -object VersionFinder { - - fun findUpdateFallback( - installedVersion: String, - mcReleaseTarget: String, - mcVersion: String, - updateChannel: Config.UpdateChannel, - modVersions: List - ): Version? { - val versions = - modVersions.filter { updateChannel.isReleaseAllowed(it.type) } - .filter { it.gameVersions.any { it1 -> it1.startsWith(mcVersion) || it1.startsWith(mcReleaseTarget) } } - .sortedByDescending { it.releaseDate } - - val version = versions.firstOrNull() - if (version?.version == installedVersion) { - return null - } - return version - } - - internal fun findUpdateByVersion( - installedVersion: String, - mcReleaseTarget: String, - mcVersion: String, - channel: Config.UpdateChannel, - modVersions: List - ): Version? { - val versions = modVersions.filter { channel.isReleaseAllowed(it.type) } - .filter { it.gameVersions.any { it1 -> it1.startsWith(mcVersion) || it1.startsWith(mcReleaseTarget) } } - var latestVersion: Version? = null - var latestVer: SemanticVersion? = null - val installedVer = SemanticVersion.parse(installedVersion) - for (version in versions) { - val parsedVersion = SemanticVersion.parse(version.version) - if (latestVersion == null) { - latestVersion = version - latestVer = parsedVersion - continue - } - if (latestVer != null && parsedVersion > latestVer) { - latestVersion = version - latestVer = parsedVersion - } - } - if (installedVersion == latestVersion?.version || (latestVer != null && installedVer >= latestVer)) { - return null - } - return latestVersion - } - - fun findUpdate( - installedVersion: String, - mcReleaseTarget: String, - mcVersion: String, - channel: Config.UpdateChannel, - modVersions: List - ): Version? { - return try { - findUpdateByVersion(installedVersion, mcReleaseTarget, mcVersion, channel, modVersions) - } catch (e: VersionParsingException) { - findUpdateFallback(installedVersion, mcReleaseTarget, mcVersion, channel, modVersions) - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/en_us.json b/src/main/resources/assets/modmanager/lang/en_us.json deleted file mode 100644 index d6de41f..0000000 --- a/src/main/resources/assets/modmanager/lang/en_us.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Installed", - "modmanager.badge.outdated": "Outdated", - "modmanager.button.update": "Update", - "modmanager.button.install": "Install", - "modmanager.button.remove": "Remove", - "modmanager.button.updateAll": "Update all", - "modmanager.button.tryAgain": "Try again", - "modmanager.button.defaultProvider": "Default provider", - "modmanager.button.updateChannel": "Update channel", - "modmanager.button.save": "Save", - "modmanager.button.hide": "Hide updates", - "modmanager.button.show": "Show updates", - "modmanager.button.open": "Open ModManager", - "modmanager.categories": "Categories", - "modmanager.category.updatable": "Updatable mods", - "modmanager.category.technology": "Technology", - "modmanager.category.adventure": "Adventure", - "modmanager.category.magic": "Magic", - "modmanager.category.utility": "Utility", - "modmanager.category.decoration": "Decoration", - "modmanager.category.library": "Library", - "modmanager.category.cursed": "Cursed", - "modmanager.category.worldgen": "World Gen", - "modmanager.category.storage": "Storage", - "modmanager.category.search": "Search", - "modmanager.category.food": "Food", - "modmanager.category.equipment": "Equipment", - "modmanager.category.misc": "Miscellaneous", - "modmanager.changes.title": "§e§lChanges detected§r", - "modmanager.changes.message": "Changes will take effect after a relaunch.\nQuit Minecraft now?", - "modmanager.channel.info": "Switch between beta and stable versions", - "modmanager.channel.all": "All", - "modmanager.channel.stable": "Stable", - "modmanager.channel.unstable": "Unstable", - "modmanager.details.author": "By %s", - "modmanager.details.versioning": "From %s to %s", - "modmanager.error.title": "§b§4Error:§r", - "modmanager.error.container.notFound": "The mod you're trying to update has been unloaded in the meantime\nThis shouldn't be possible", - "modmanager.error.unknown": "Unknown error while retrieving data:\n %s", - "modmanager.error.unknown.install": "Unknown error during the installation process:\n %s", - "modmanager.error.unknown.update": "Unknown error during the update process:\n %s", - "modmanager.error.invalidStatus": "Received invalid status code:\n %d", - "modmanager.error.network": "Network error while retrieving data:\n %s", - "modmanager.error.failedToParse": "Failed to parse response:\n %s", - "modmanager.error.noCompatibleModVersionFound": "No compatible version found for your current channel!\nTry changing the channel in the Mod Manager settings!", - "modmanager.error.noProviderSelected": "The selected provider %s is not available!", - "modmanager.error.update.noFabricJar": "The mod author has marked a version compatible\nto fabric but does not provide a for it!", - "modmanager.error.jar.notFound": "Error, jar file not found. Is it part of another mod?", - "modmanager.error.jar.failedDelete": "Failed to delete mod:\n %s", - "modmanager.error.invalidHash": "Error, the downloaded file is probably broken as the %s hashes don't match\nTry checking your network or contact the mod author", - "modmanager.status.installing": "Installing %s...", - "modmanager.status.install.success": "Successfully installed %s!\nDo you want to go back?", - "modmanager.status.updating": "Updating %s...", - "modmanager.status.update.success": "Successfully updated %s!\nDo you want to go back?", - "modmanager.sorting.sort": "Sort by", - "modmanager.sorting.relevance": "Relevance", - "modmanager.sorting.downloads": "Downloads", - "modmanager.sorting.updated": "Updated", - "modmanager.sorting.newest": "Newest", - "modmanager.search": "Search...", - "modmanager.page.next": "Next Page", - "modmanager.page.previous": "Previous Page", - "modmanager.provider.info": "Allows you to change the default provider for browsing", - "modmanager.toast.update.title": "Updates Available!", - "modmanager.toast.update.description": "%d mods can be updated", - "modmanager.title.updating": "Updating all mods..." -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/es_ar.json b/src/main/resources/assets/modmanager/lang/es_ar.json deleted file mode 100644 index 9f91c18..0000000 --- a/src/main/resources/assets/modmanager/lang/es_ar.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Instalado", - "modmanager.badge.outdated": "Obsoleto", - "modmanager.button.update": "Actualizar", - "modmanager.button.install": "Instalar", - "modmanager.button.remove": "Desinstalar", - "modmanager.button.updateAll": "Actualizar todo", - "modmanager.button.tryAgain": "Reintentar", - "modmanager.button.defaultProvider": "Proveedor predeterminado", - "modmanager.button.updateChannel": "Canal de actualizaciones", - "modmanager.button.save": "Guardar", - "modmanager.button.hide": "Ocultar actualizaciones", - "modmanager.button.show": "Mostrar actualizaciones", - "modmanager.button.open": "Abrir ModManager", - "modmanager.categories": "Categorías", - "modmanager.category.updatable": "Mods con actualizaciones", - "modmanager.category.technology": "Tecnología", - "modmanager.category.adventure": "Aventura", - "modmanager.category.magic": "Magia", - "modmanager.category.utility": "Utilidad", - "modmanager.category.decoration": "Decoración", - "modmanager.category.library": "Librería", - "modmanager.category.cursed": "Cursed", - "modmanager.category.worldgen": "Gen. de Mundo", - "modmanager.category.storage": "Almacenaje", - "modmanager.category.search": "Buscar", - "modmanager.category.food": "Comida", - "modmanager.category.equipment": "Equipamento", - "modmanager.category.misc": "Misceláneo", - "modmanager.changes.title": "§e§lSe han detectado cambios§r", - "modmanager.changes.message": "Los cambios surtirán efecto tras reiniciar.\n¿Desear salir de Minecraft ahora?", - "modmanager.channel.info": "Cambia entre las versiones beta y estables", - "modmanager.channel.all": "Todo", - "modmanager.channel.stable": "Estable", - "modmanager.channel.unstable": "Inestable", - "modmanager.details.author": "Por %s", - "modmanager.details.versioning": "De %s a %s", - "modmanager.error.title": "§b§4Error:§r", - "modmanager.error.container.notFound": "El mod que estás intentando actualizar ha sido desactivado en el transcurso\nEsto no debería ser posible", - "modmanager.error.unknown": "Ha ocurrido un error desconocido al buscar la información:\n %s", - "modmanager.error.unknown.install": "Ha ocurrido un error desconocido durante la instalación:\n %s", - "modmanager.error.unknown.update": "Ha ocurrido un error desconocido durante la actualización:\n %s", - "modmanager.error.invalidStatus": "Se ha recibido un código de estado inválido:\n %d", - "modmanager.error.network": "Error de red al buscar la información:\n %s", - "modmanager.error.failedToParse": "No se ha podido procesar la respuesta:\n %s", - "modmanager.error.noCompatibleModVersionFound": "¡No se ha encontrado una versión compatible para tu canal actual!\nIntenta cambiar de canal en la configuración de Mod Manager", - "modmanager.error.noProviderSelected": "¡El proveedor seleccionado %s no está disponible!", - "modmanager.error.update.noFabricJar": "¡El autor del mod ha marcado a una versión compatible\ncon Fabric pero no ha proveído un archivo jar!", - "modmanager.error.jar.notFound": "El archivo jar no se ha encontrado. ¿Es parte de otro mod?", - "modmanager.error.jar.failedDelete": "No se ha podido eliminar el mod:\n %s", - "modmanager.error.invalidHash": "El archivo descargado probablemente esté roto ya que el hash no coincide\nIntenta checando tu red o contacta al autor del mod", - "modmanager.status.installing": "Instalando %s...", - "modmanager.status.install.success": "¡%s se ha instalado con éxito!\n¿Te gustaría regresar?", - "modmanager.status.updating": "Actualizando %s...", - "modmanager.status.update.success": "¡%s se ha actualizado con éxito!\n¿Te gustaría regresar?", - "modmanager.sorting.sort": "Ordenar por", - "modmanager.sorting.relevance": "Relevancia", - "modmanager.sorting.downloads": "Descargas", - "modmanager.sorting.updated": "Actualizados", - "modmanager.sorting.newest": "Nuevos", - "modmanager.search": "Buscar...", - "modmanager.page.next": "Siguiente página", - "modmanager.page.previous": "Página anterior", - "modmanager.provider.info": "Permite cambiar el proveedor predeterminado para buscar", - "modmanager.toast.update.title": "¡Actualizaciones disponibles!", - "modmanager.toast.update.description": "%d mods tienen actualizaciones", - "modmanager.title.updating": "Actualizando todos los mods..." -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/es_cl.json b/src/main/resources/assets/modmanager/lang/es_cl.json deleted file mode 100644 index 9f91c18..0000000 --- a/src/main/resources/assets/modmanager/lang/es_cl.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Instalado", - "modmanager.badge.outdated": "Obsoleto", - "modmanager.button.update": "Actualizar", - "modmanager.button.install": "Instalar", - "modmanager.button.remove": "Desinstalar", - "modmanager.button.updateAll": "Actualizar todo", - "modmanager.button.tryAgain": "Reintentar", - "modmanager.button.defaultProvider": "Proveedor predeterminado", - "modmanager.button.updateChannel": "Canal de actualizaciones", - "modmanager.button.save": "Guardar", - "modmanager.button.hide": "Ocultar actualizaciones", - "modmanager.button.show": "Mostrar actualizaciones", - "modmanager.button.open": "Abrir ModManager", - "modmanager.categories": "Categorías", - "modmanager.category.updatable": "Mods con actualizaciones", - "modmanager.category.technology": "Tecnología", - "modmanager.category.adventure": "Aventura", - "modmanager.category.magic": "Magia", - "modmanager.category.utility": "Utilidad", - "modmanager.category.decoration": "Decoración", - "modmanager.category.library": "Librería", - "modmanager.category.cursed": "Cursed", - "modmanager.category.worldgen": "Gen. de Mundo", - "modmanager.category.storage": "Almacenaje", - "modmanager.category.search": "Buscar", - "modmanager.category.food": "Comida", - "modmanager.category.equipment": "Equipamento", - "modmanager.category.misc": "Misceláneo", - "modmanager.changes.title": "§e§lSe han detectado cambios§r", - "modmanager.changes.message": "Los cambios surtirán efecto tras reiniciar.\n¿Desear salir de Minecraft ahora?", - "modmanager.channel.info": "Cambia entre las versiones beta y estables", - "modmanager.channel.all": "Todo", - "modmanager.channel.stable": "Estable", - "modmanager.channel.unstable": "Inestable", - "modmanager.details.author": "Por %s", - "modmanager.details.versioning": "De %s a %s", - "modmanager.error.title": "§b§4Error:§r", - "modmanager.error.container.notFound": "El mod que estás intentando actualizar ha sido desactivado en el transcurso\nEsto no debería ser posible", - "modmanager.error.unknown": "Ha ocurrido un error desconocido al buscar la información:\n %s", - "modmanager.error.unknown.install": "Ha ocurrido un error desconocido durante la instalación:\n %s", - "modmanager.error.unknown.update": "Ha ocurrido un error desconocido durante la actualización:\n %s", - "modmanager.error.invalidStatus": "Se ha recibido un código de estado inválido:\n %d", - "modmanager.error.network": "Error de red al buscar la información:\n %s", - "modmanager.error.failedToParse": "No se ha podido procesar la respuesta:\n %s", - "modmanager.error.noCompatibleModVersionFound": "¡No se ha encontrado una versión compatible para tu canal actual!\nIntenta cambiar de canal en la configuración de Mod Manager", - "modmanager.error.noProviderSelected": "¡El proveedor seleccionado %s no está disponible!", - "modmanager.error.update.noFabricJar": "¡El autor del mod ha marcado a una versión compatible\ncon Fabric pero no ha proveído un archivo jar!", - "modmanager.error.jar.notFound": "El archivo jar no se ha encontrado. ¿Es parte de otro mod?", - "modmanager.error.jar.failedDelete": "No se ha podido eliminar el mod:\n %s", - "modmanager.error.invalidHash": "El archivo descargado probablemente esté roto ya que el hash no coincide\nIntenta checando tu red o contacta al autor del mod", - "modmanager.status.installing": "Instalando %s...", - "modmanager.status.install.success": "¡%s se ha instalado con éxito!\n¿Te gustaría regresar?", - "modmanager.status.updating": "Actualizando %s...", - "modmanager.status.update.success": "¡%s se ha actualizado con éxito!\n¿Te gustaría regresar?", - "modmanager.sorting.sort": "Ordenar por", - "modmanager.sorting.relevance": "Relevancia", - "modmanager.sorting.downloads": "Descargas", - "modmanager.sorting.updated": "Actualizados", - "modmanager.sorting.newest": "Nuevos", - "modmanager.search": "Buscar...", - "modmanager.page.next": "Siguiente página", - "modmanager.page.previous": "Página anterior", - "modmanager.provider.info": "Permite cambiar el proveedor predeterminado para buscar", - "modmanager.toast.update.title": "¡Actualizaciones disponibles!", - "modmanager.toast.update.description": "%d mods tienen actualizaciones", - "modmanager.title.updating": "Actualizando todos los mods..." -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/es_ec.json b/src/main/resources/assets/modmanager/lang/es_ec.json deleted file mode 100644 index 9f91c18..0000000 --- a/src/main/resources/assets/modmanager/lang/es_ec.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Instalado", - "modmanager.badge.outdated": "Obsoleto", - "modmanager.button.update": "Actualizar", - "modmanager.button.install": "Instalar", - "modmanager.button.remove": "Desinstalar", - "modmanager.button.updateAll": "Actualizar todo", - "modmanager.button.tryAgain": "Reintentar", - "modmanager.button.defaultProvider": "Proveedor predeterminado", - "modmanager.button.updateChannel": "Canal de actualizaciones", - "modmanager.button.save": "Guardar", - "modmanager.button.hide": "Ocultar actualizaciones", - "modmanager.button.show": "Mostrar actualizaciones", - "modmanager.button.open": "Abrir ModManager", - "modmanager.categories": "Categorías", - "modmanager.category.updatable": "Mods con actualizaciones", - "modmanager.category.technology": "Tecnología", - "modmanager.category.adventure": "Aventura", - "modmanager.category.magic": "Magia", - "modmanager.category.utility": "Utilidad", - "modmanager.category.decoration": "Decoración", - "modmanager.category.library": "Librería", - "modmanager.category.cursed": "Cursed", - "modmanager.category.worldgen": "Gen. de Mundo", - "modmanager.category.storage": "Almacenaje", - "modmanager.category.search": "Buscar", - "modmanager.category.food": "Comida", - "modmanager.category.equipment": "Equipamento", - "modmanager.category.misc": "Misceláneo", - "modmanager.changes.title": "§e§lSe han detectado cambios§r", - "modmanager.changes.message": "Los cambios surtirán efecto tras reiniciar.\n¿Desear salir de Minecraft ahora?", - "modmanager.channel.info": "Cambia entre las versiones beta y estables", - "modmanager.channel.all": "Todo", - "modmanager.channel.stable": "Estable", - "modmanager.channel.unstable": "Inestable", - "modmanager.details.author": "Por %s", - "modmanager.details.versioning": "De %s a %s", - "modmanager.error.title": "§b§4Error:§r", - "modmanager.error.container.notFound": "El mod que estás intentando actualizar ha sido desactivado en el transcurso\nEsto no debería ser posible", - "modmanager.error.unknown": "Ha ocurrido un error desconocido al buscar la información:\n %s", - "modmanager.error.unknown.install": "Ha ocurrido un error desconocido durante la instalación:\n %s", - "modmanager.error.unknown.update": "Ha ocurrido un error desconocido durante la actualización:\n %s", - "modmanager.error.invalidStatus": "Se ha recibido un código de estado inválido:\n %d", - "modmanager.error.network": "Error de red al buscar la información:\n %s", - "modmanager.error.failedToParse": "No se ha podido procesar la respuesta:\n %s", - "modmanager.error.noCompatibleModVersionFound": "¡No se ha encontrado una versión compatible para tu canal actual!\nIntenta cambiar de canal en la configuración de Mod Manager", - "modmanager.error.noProviderSelected": "¡El proveedor seleccionado %s no está disponible!", - "modmanager.error.update.noFabricJar": "¡El autor del mod ha marcado a una versión compatible\ncon Fabric pero no ha proveído un archivo jar!", - "modmanager.error.jar.notFound": "El archivo jar no se ha encontrado. ¿Es parte de otro mod?", - "modmanager.error.jar.failedDelete": "No se ha podido eliminar el mod:\n %s", - "modmanager.error.invalidHash": "El archivo descargado probablemente esté roto ya que el hash no coincide\nIntenta checando tu red o contacta al autor del mod", - "modmanager.status.installing": "Instalando %s...", - "modmanager.status.install.success": "¡%s se ha instalado con éxito!\n¿Te gustaría regresar?", - "modmanager.status.updating": "Actualizando %s...", - "modmanager.status.update.success": "¡%s se ha actualizado con éxito!\n¿Te gustaría regresar?", - "modmanager.sorting.sort": "Ordenar por", - "modmanager.sorting.relevance": "Relevancia", - "modmanager.sorting.downloads": "Descargas", - "modmanager.sorting.updated": "Actualizados", - "modmanager.sorting.newest": "Nuevos", - "modmanager.search": "Buscar...", - "modmanager.page.next": "Siguiente página", - "modmanager.page.previous": "Página anterior", - "modmanager.provider.info": "Permite cambiar el proveedor predeterminado para buscar", - "modmanager.toast.update.title": "¡Actualizaciones disponibles!", - "modmanager.toast.update.description": "%d mods tienen actualizaciones", - "modmanager.title.updating": "Actualizando todos los mods..." -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/es_es.json b/src/main/resources/assets/modmanager/lang/es_es.json deleted file mode 100644 index 9f91c18..0000000 --- a/src/main/resources/assets/modmanager/lang/es_es.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Instalado", - "modmanager.badge.outdated": "Obsoleto", - "modmanager.button.update": "Actualizar", - "modmanager.button.install": "Instalar", - "modmanager.button.remove": "Desinstalar", - "modmanager.button.updateAll": "Actualizar todo", - "modmanager.button.tryAgain": "Reintentar", - "modmanager.button.defaultProvider": "Proveedor predeterminado", - "modmanager.button.updateChannel": "Canal de actualizaciones", - "modmanager.button.save": "Guardar", - "modmanager.button.hide": "Ocultar actualizaciones", - "modmanager.button.show": "Mostrar actualizaciones", - "modmanager.button.open": "Abrir ModManager", - "modmanager.categories": "Categorías", - "modmanager.category.updatable": "Mods con actualizaciones", - "modmanager.category.technology": "Tecnología", - "modmanager.category.adventure": "Aventura", - "modmanager.category.magic": "Magia", - "modmanager.category.utility": "Utilidad", - "modmanager.category.decoration": "Decoración", - "modmanager.category.library": "Librería", - "modmanager.category.cursed": "Cursed", - "modmanager.category.worldgen": "Gen. de Mundo", - "modmanager.category.storage": "Almacenaje", - "modmanager.category.search": "Buscar", - "modmanager.category.food": "Comida", - "modmanager.category.equipment": "Equipamento", - "modmanager.category.misc": "Misceláneo", - "modmanager.changes.title": "§e§lSe han detectado cambios§r", - "modmanager.changes.message": "Los cambios surtirán efecto tras reiniciar.\n¿Desear salir de Minecraft ahora?", - "modmanager.channel.info": "Cambia entre las versiones beta y estables", - "modmanager.channel.all": "Todo", - "modmanager.channel.stable": "Estable", - "modmanager.channel.unstable": "Inestable", - "modmanager.details.author": "Por %s", - "modmanager.details.versioning": "De %s a %s", - "modmanager.error.title": "§b§4Error:§r", - "modmanager.error.container.notFound": "El mod que estás intentando actualizar ha sido desactivado en el transcurso\nEsto no debería ser posible", - "modmanager.error.unknown": "Ha ocurrido un error desconocido al buscar la información:\n %s", - "modmanager.error.unknown.install": "Ha ocurrido un error desconocido durante la instalación:\n %s", - "modmanager.error.unknown.update": "Ha ocurrido un error desconocido durante la actualización:\n %s", - "modmanager.error.invalidStatus": "Se ha recibido un código de estado inválido:\n %d", - "modmanager.error.network": "Error de red al buscar la información:\n %s", - "modmanager.error.failedToParse": "No se ha podido procesar la respuesta:\n %s", - "modmanager.error.noCompatibleModVersionFound": "¡No se ha encontrado una versión compatible para tu canal actual!\nIntenta cambiar de canal en la configuración de Mod Manager", - "modmanager.error.noProviderSelected": "¡El proveedor seleccionado %s no está disponible!", - "modmanager.error.update.noFabricJar": "¡El autor del mod ha marcado a una versión compatible\ncon Fabric pero no ha proveído un archivo jar!", - "modmanager.error.jar.notFound": "El archivo jar no se ha encontrado. ¿Es parte de otro mod?", - "modmanager.error.jar.failedDelete": "No se ha podido eliminar el mod:\n %s", - "modmanager.error.invalidHash": "El archivo descargado probablemente esté roto ya que el hash no coincide\nIntenta checando tu red o contacta al autor del mod", - "modmanager.status.installing": "Instalando %s...", - "modmanager.status.install.success": "¡%s se ha instalado con éxito!\n¿Te gustaría regresar?", - "modmanager.status.updating": "Actualizando %s...", - "modmanager.status.update.success": "¡%s se ha actualizado con éxito!\n¿Te gustaría regresar?", - "modmanager.sorting.sort": "Ordenar por", - "modmanager.sorting.relevance": "Relevancia", - "modmanager.sorting.downloads": "Descargas", - "modmanager.sorting.updated": "Actualizados", - "modmanager.sorting.newest": "Nuevos", - "modmanager.search": "Buscar...", - "modmanager.page.next": "Siguiente página", - "modmanager.page.previous": "Página anterior", - "modmanager.provider.info": "Permite cambiar el proveedor predeterminado para buscar", - "modmanager.toast.update.title": "¡Actualizaciones disponibles!", - "modmanager.toast.update.description": "%d mods tienen actualizaciones", - "modmanager.title.updating": "Actualizando todos los mods..." -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/es_mx.json b/src/main/resources/assets/modmanager/lang/es_mx.json deleted file mode 100644 index 9f91c18..0000000 --- a/src/main/resources/assets/modmanager/lang/es_mx.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Instalado", - "modmanager.badge.outdated": "Obsoleto", - "modmanager.button.update": "Actualizar", - "modmanager.button.install": "Instalar", - "modmanager.button.remove": "Desinstalar", - "modmanager.button.updateAll": "Actualizar todo", - "modmanager.button.tryAgain": "Reintentar", - "modmanager.button.defaultProvider": "Proveedor predeterminado", - "modmanager.button.updateChannel": "Canal de actualizaciones", - "modmanager.button.save": "Guardar", - "modmanager.button.hide": "Ocultar actualizaciones", - "modmanager.button.show": "Mostrar actualizaciones", - "modmanager.button.open": "Abrir ModManager", - "modmanager.categories": "Categorías", - "modmanager.category.updatable": "Mods con actualizaciones", - "modmanager.category.technology": "Tecnología", - "modmanager.category.adventure": "Aventura", - "modmanager.category.magic": "Magia", - "modmanager.category.utility": "Utilidad", - "modmanager.category.decoration": "Decoración", - "modmanager.category.library": "Librería", - "modmanager.category.cursed": "Cursed", - "modmanager.category.worldgen": "Gen. de Mundo", - "modmanager.category.storage": "Almacenaje", - "modmanager.category.search": "Buscar", - "modmanager.category.food": "Comida", - "modmanager.category.equipment": "Equipamento", - "modmanager.category.misc": "Misceláneo", - "modmanager.changes.title": "§e§lSe han detectado cambios§r", - "modmanager.changes.message": "Los cambios surtirán efecto tras reiniciar.\n¿Desear salir de Minecraft ahora?", - "modmanager.channel.info": "Cambia entre las versiones beta y estables", - "modmanager.channel.all": "Todo", - "modmanager.channel.stable": "Estable", - "modmanager.channel.unstable": "Inestable", - "modmanager.details.author": "Por %s", - "modmanager.details.versioning": "De %s a %s", - "modmanager.error.title": "§b§4Error:§r", - "modmanager.error.container.notFound": "El mod que estás intentando actualizar ha sido desactivado en el transcurso\nEsto no debería ser posible", - "modmanager.error.unknown": "Ha ocurrido un error desconocido al buscar la información:\n %s", - "modmanager.error.unknown.install": "Ha ocurrido un error desconocido durante la instalación:\n %s", - "modmanager.error.unknown.update": "Ha ocurrido un error desconocido durante la actualización:\n %s", - "modmanager.error.invalidStatus": "Se ha recibido un código de estado inválido:\n %d", - "modmanager.error.network": "Error de red al buscar la información:\n %s", - "modmanager.error.failedToParse": "No se ha podido procesar la respuesta:\n %s", - "modmanager.error.noCompatibleModVersionFound": "¡No se ha encontrado una versión compatible para tu canal actual!\nIntenta cambiar de canal en la configuración de Mod Manager", - "modmanager.error.noProviderSelected": "¡El proveedor seleccionado %s no está disponible!", - "modmanager.error.update.noFabricJar": "¡El autor del mod ha marcado a una versión compatible\ncon Fabric pero no ha proveído un archivo jar!", - "modmanager.error.jar.notFound": "El archivo jar no se ha encontrado. ¿Es parte de otro mod?", - "modmanager.error.jar.failedDelete": "No se ha podido eliminar el mod:\n %s", - "modmanager.error.invalidHash": "El archivo descargado probablemente esté roto ya que el hash no coincide\nIntenta checando tu red o contacta al autor del mod", - "modmanager.status.installing": "Instalando %s...", - "modmanager.status.install.success": "¡%s se ha instalado con éxito!\n¿Te gustaría regresar?", - "modmanager.status.updating": "Actualizando %s...", - "modmanager.status.update.success": "¡%s se ha actualizado con éxito!\n¿Te gustaría regresar?", - "modmanager.sorting.sort": "Ordenar por", - "modmanager.sorting.relevance": "Relevancia", - "modmanager.sorting.downloads": "Descargas", - "modmanager.sorting.updated": "Actualizados", - "modmanager.sorting.newest": "Nuevos", - "modmanager.search": "Buscar...", - "modmanager.page.next": "Siguiente página", - "modmanager.page.previous": "Página anterior", - "modmanager.provider.info": "Permite cambiar el proveedor predeterminado para buscar", - "modmanager.toast.update.title": "¡Actualizaciones disponibles!", - "modmanager.toast.update.description": "%d mods tienen actualizaciones", - "modmanager.title.updating": "Actualizando todos los mods..." -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/es_uy.json b/src/main/resources/assets/modmanager/lang/es_uy.json deleted file mode 100644 index 9f91c18..0000000 --- a/src/main/resources/assets/modmanager/lang/es_uy.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Instalado", - "modmanager.badge.outdated": "Obsoleto", - "modmanager.button.update": "Actualizar", - "modmanager.button.install": "Instalar", - "modmanager.button.remove": "Desinstalar", - "modmanager.button.updateAll": "Actualizar todo", - "modmanager.button.tryAgain": "Reintentar", - "modmanager.button.defaultProvider": "Proveedor predeterminado", - "modmanager.button.updateChannel": "Canal de actualizaciones", - "modmanager.button.save": "Guardar", - "modmanager.button.hide": "Ocultar actualizaciones", - "modmanager.button.show": "Mostrar actualizaciones", - "modmanager.button.open": "Abrir ModManager", - "modmanager.categories": "Categorías", - "modmanager.category.updatable": "Mods con actualizaciones", - "modmanager.category.technology": "Tecnología", - "modmanager.category.adventure": "Aventura", - "modmanager.category.magic": "Magia", - "modmanager.category.utility": "Utilidad", - "modmanager.category.decoration": "Decoración", - "modmanager.category.library": "Librería", - "modmanager.category.cursed": "Cursed", - "modmanager.category.worldgen": "Gen. de Mundo", - "modmanager.category.storage": "Almacenaje", - "modmanager.category.search": "Buscar", - "modmanager.category.food": "Comida", - "modmanager.category.equipment": "Equipamento", - "modmanager.category.misc": "Misceláneo", - "modmanager.changes.title": "§e§lSe han detectado cambios§r", - "modmanager.changes.message": "Los cambios surtirán efecto tras reiniciar.\n¿Desear salir de Minecraft ahora?", - "modmanager.channel.info": "Cambia entre las versiones beta y estables", - "modmanager.channel.all": "Todo", - "modmanager.channel.stable": "Estable", - "modmanager.channel.unstable": "Inestable", - "modmanager.details.author": "Por %s", - "modmanager.details.versioning": "De %s a %s", - "modmanager.error.title": "§b§4Error:§r", - "modmanager.error.container.notFound": "El mod que estás intentando actualizar ha sido desactivado en el transcurso\nEsto no debería ser posible", - "modmanager.error.unknown": "Ha ocurrido un error desconocido al buscar la información:\n %s", - "modmanager.error.unknown.install": "Ha ocurrido un error desconocido durante la instalación:\n %s", - "modmanager.error.unknown.update": "Ha ocurrido un error desconocido durante la actualización:\n %s", - "modmanager.error.invalidStatus": "Se ha recibido un código de estado inválido:\n %d", - "modmanager.error.network": "Error de red al buscar la información:\n %s", - "modmanager.error.failedToParse": "No se ha podido procesar la respuesta:\n %s", - "modmanager.error.noCompatibleModVersionFound": "¡No se ha encontrado una versión compatible para tu canal actual!\nIntenta cambiar de canal en la configuración de Mod Manager", - "modmanager.error.noProviderSelected": "¡El proveedor seleccionado %s no está disponible!", - "modmanager.error.update.noFabricJar": "¡El autor del mod ha marcado a una versión compatible\ncon Fabric pero no ha proveído un archivo jar!", - "modmanager.error.jar.notFound": "El archivo jar no se ha encontrado. ¿Es parte de otro mod?", - "modmanager.error.jar.failedDelete": "No se ha podido eliminar el mod:\n %s", - "modmanager.error.invalidHash": "El archivo descargado probablemente esté roto ya que el hash no coincide\nIntenta checando tu red o contacta al autor del mod", - "modmanager.status.installing": "Instalando %s...", - "modmanager.status.install.success": "¡%s se ha instalado con éxito!\n¿Te gustaría regresar?", - "modmanager.status.updating": "Actualizando %s...", - "modmanager.status.update.success": "¡%s se ha actualizado con éxito!\n¿Te gustaría regresar?", - "modmanager.sorting.sort": "Ordenar por", - "modmanager.sorting.relevance": "Relevancia", - "modmanager.sorting.downloads": "Descargas", - "modmanager.sorting.updated": "Actualizados", - "modmanager.sorting.newest": "Nuevos", - "modmanager.search": "Buscar...", - "modmanager.page.next": "Siguiente página", - "modmanager.page.previous": "Página anterior", - "modmanager.provider.info": "Permite cambiar el proveedor predeterminado para buscar", - "modmanager.toast.update.title": "¡Actualizaciones disponibles!", - "modmanager.toast.update.description": "%d mods tienen actualizaciones", - "modmanager.title.updating": "Actualizando todos los mods..." -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/es_ve.json b/src/main/resources/assets/modmanager/lang/es_ve.json deleted file mode 100644 index 9f91c18..0000000 --- a/src/main/resources/assets/modmanager/lang/es_ve.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Instalado", - "modmanager.badge.outdated": "Obsoleto", - "modmanager.button.update": "Actualizar", - "modmanager.button.install": "Instalar", - "modmanager.button.remove": "Desinstalar", - "modmanager.button.updateAll": "Actualizar todo", - "modmanager.button.tryAgain": "Reintentar", - "modmanager.button.defaultProvider": "Proveedor predeterminado", - "modmanager.button.updateChannel": "Canal de actualizaciones", - "modmanager.button.save": "Guardar", - "modmanager.button.hide": "Ocultar actualizaciones", - "modmanager.button.show": "Mostrar actualizaciones", - "modmanager.button.open": "Abrir ModManager", - "modmanager.categories": "Categorías", - "modmanager.category.updatable": "Mods con actualizaciones", - "modmanager.category.technology": "Tecnología", - "modmanager.category.adventure": "Aventura", - "modmanager.category.magic": "Magia", - "modmanager.category.utility": "Utilidad", - "modmanager.category.decoration": "Decoración", - "modmanager.category.library": "Librería", - "modmanager.category.cursed": "Cursed", - "modmanager.category.worldgen": "Gen. de Mundo", - "modmanager.category.storage": "Almacenaje", - "modmanager.category.search": "Buscar", - "modmanager.category.food": "Comida", - "modmanager.category.equipment": "Equipamento", - "modmanager.category.misc": "Misceláneo", - "modmanager.changes.title": "§e§lSe han detectado cambios§r", - "modmanager.changes.message": "Los cambios surtirán efecto tras reiniciar.\n¿Desear salir de Minecraft ahora?", - "modmanager.channel.info": "Cambia entre las versiones beta y estables", - "modmanager.channel.all": "Todo", - "modmanager.channel.stable": "Estable", - "modmanager.channel.unstable": "Inestable", - "modmanager.details.author": "Por %s", - "modmanager.details.versioning": "De %s a %s", - "modmanager.error.title": "§b§4Error:§r", - "modmanager.error.container.notFound": "El mod que estás intentando actualizar ha sido desactivado en el transcurso\nEsto no debería ser posible", - "modmanager.error.unknown": "Ha ocurrido un error desconocido al buscar la información:\n %s", - "modmanager.error.unknown.install": "Ha ocurrido un error desconocido durante la instalación:\n %s", - "modmanager.error.unknown.update": "Ha ocurrido un error desconocido durante la actualización:\n %s", - "modmanager.error.invalidStatus": "Se ha recibido un código de estado inválido:\n %d", - "modmanager.error.network": "Error de red al buscar la información:\n %s", - "modmanager.error.failedToParse": "No se ha podido procesar la respuesta:\n %s", - "modmanager.error.noCompatibleModVersionFound": "¡No se ha encontrado una versión compatible para tu canal actual!\nIntenta cambiar de canal en la configuración de Mod Manager", - "modmanager.error.noProviderSelected": "¡El proveedor seleccionado %s no está disponible!", - "modmanager.error.update.noFabricJar": "¡El autor del mod ha marcado a una versión compatible\ncon Fabric pero no ha proveído un archivo jar!", - "modmanager.error.jar.notFound": "El archivo jar no se ha encontrado. ¿Es parte de otro mod?", - "modmanager.error.jar.failedDelete": "No se ha podido eliminar el mod:\n %s", - "modmanager.error.invalidHash": "El archivo descargado probablemente esté roto ya que el hash no coincide\nIntenta checando tu red o contacta al autor del mod", - "modmanager.status.installing": "Instalando %s...", - "modmanager.status.install.success": "¡%s se ha instalado con éxito!\n¿Te gustaría regresar?", - "modmanager.status.updating": "Actualizando %s...", - "modmanager.status.update.success": "¡%s se ha actualizado con éxito!\n¿Te gustaría regresar?", - "modmanager.sorting.sort": "Ordenar por", - "modmanager.sorting.relevance": "Relevancia", - "modmanager.sorting.downloads": "Descargas", - "modmanager.sorting.updated": "Actualizados", - "modmanager.sorting.newest": "Nuevos", - "modmanager.search": "Buscar...", - "modmanager.page.next": "Siguiente página", - "modmanager.page.previous": "Página anterior", - "modmanager.provider.info": "Permite cambiar el proveedor predeterminado para buscar", - "modmanager.toast.update.title": "¡Actualizaciones disponibles!", - "modmanager.toast.update.description": "%d mods tienen actualizaciones", - "modmanager.title.updating": "Actualizando todos los mods..." -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/ko_kr.json b/src/main/resources/assets/modmanager/lang/ko_kr.json deleted file mode 100644 index 81338a1..0000000 --- a/src/main/resources/assets/modmanager/lang/ko_kr.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "설치됨", - "modmanager.badge.outdated": "이전 버전", - "modmanager.button.update": "업데이트", - "modmanager.button.install": "설치", - "modmanager.button.remove": "제거", - "modmanager.button.updateAll": "모두 업데이트", - "modmanager.button.tryAgain": "다시 시도", - "modmanager.button.defaultProvider": "기본 공급자", - "modmanager.button.updateChannel": "업데이트 채널", - "modmanager.button.save": "저장", - "modmanager.button.hide": "업데이트 숨기기", - "modmanager.button.show": "업데이트 보이기", - "modmanager.button.open": "ModManager 열기", - "modmanager.categories": "카테고리", - "modmanager.category.updatable": "업데이트 가능한 모드", - "modmanager.category.technology": "기술", - "modmanager.category.adventure": "모험", - "modmanager.category.magic": "마법", - "modmanager.category.utility": "도구", - "modmanager.category.decoration": "장식", - "modmanager.category.library": "라이브러리", - "modmanager.category.cursed": "저주받은 모드", - "modmanager.category.worldgen": "월드 생성", - "modmanager.category.storage": "저장고", - "modmanager.category.search": "검색", - "modmanager.category.food": "음식", - "modmanager.category.equipment": "장비", - "modmanager.category.misc": "기타", - "modmanager.changes.title": "§e§l변경사항 감지됨§r", - "modmanager.changes.message": "변경사항은 클라이언트를 재시작하면 적용됩니다.\nMinecraft를 지금 재시작 하시겠습니까?", - "modmanager.channel.info": "베타와 안정 버전 교체", - "modmanager.channel.all": "전체", - "modmanager.channel.stable": "안정", - "modmanager.channel.unstable": "불안정", - "modmanager.details.author": "게시자: %s", - "modmanager.details.versioning": "%s 에서 %s (으)로", - "modmanager.error.title": "§b§4오류:§r", - "modmanager.error.container.notFound": "모드를 업데이트하는 도중 언로드되었습니다\n업데이트가 불가능합니다", - "modmanager.error.unknown": "데이터를 검색하는 도중 알 수 없는 오류가 발생했습니다:\n %s", - "modmanager.error.unknown.install": "설치를 진행하는 도중 알 수 없는 오류가 발생했습니다:\n %s", - "modmanager.error.unknown.update": "업데이트를 진행하는 도중 알 수 없는 오류가 발생했습니다:\n %s", - "modmanager.error.invalidStatus": "잘못된 상태 코드를 받았습니다:\n %d", - "modmanager.error.network": "데이터를 검색하는 도중 네트워크 오류가 발생했습니다:\n %s", - "modmanager.error.failedToParse": "응답을 분석하지 못했습니다:\n %s", - "modmanager.error.noCompatibleModVersionFound": "현재 채널에 맞는 버전을 찾을 수 없습니다!\nMod Manager 설정에서 채널을 변경하십시오!", - "modmanager.error.noProviderSelected": "선택한 공급자 %s 는 지금 사용할 수 없습니다!", - "modmanager.error.update.noFabricJar": "모드 작성자가 패브릭과 호환되는 버전으로 표시했지만\n파일을 제공하지 않았습니다!", - "modmanager.error.jar.notFound": "오류, jar 파일을 찾을 수 없습니다. 모드의 일부인가요?", - "modmanager.error.jar.failedDelete": "모드를 제거하는데 실패했습니다:\n %s", - "modmanager.error.invalidHash": "오류, %s 해쉬값이 맞지 않습니다. 모드가 고장났을 수 있습니다\n당신의 네트워크를 확인하거나 모드 작성자에게 문의하십시오", - "modmanager.status.installing": "%s 설치중...", - "modmanager.status.install.success": "성공적으로 %s 을(를) 설치했습니다!\n돌아가시겠습니까?", - "modmanager.status.updating": "%s 업데이트중...", - "modmanager.status.update.success": "성공적으로 %s 을(를) 업데이트 했습니다!\n돌아가시겠습니까?", - "modmanager.sorting.sort": "정렬", - "modmanager.sorting.relevance": "관련성", - "modmanager.sorting.downloads": "다운로드 수", - "modmanager.sorting.updated": "업데이트순", - "modmanager.sorting.newest": "공개순", - "modmanager.search": "검색...", - "modmanager.page.next": "다음 페이지", - "modmanager.page.previous": "이전 페이지", - "modmanager.provider.info": "기본 검색 공급자를 변경할 수 있습니다", - "modmanager.toast.update.title": "업데이트가 가능합니다!", - "modmanager.toast.update.description": "%d 모드를 업데이트 할 수 있습니다", - "modmanager.title.updating": "모든 모드를 업데이트 ..." -} diff --git a/src/main/resources/assets/modmanager/lang/ru_ru.json b/src/main/resources/assets/modmanager/lang/ru_ru.json deleted file mode 100644 index b930d8d..0000000 --- a/src/main/resources/assets/modmanager/lang/ru_ru.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "Установлен", - "modmanager.badge.outdated": "Устарел", - "modmanager.button.update": "Обновить", - "modmanager.button.install": "Установить", - "modmanager.button.remove": "Удалить", - "modmanager.button.updateAll": "Обновить все", - "modmanager.button.tryAgain": "Ещё раз", - "modmanager.button.defaultProvider": "Источник по умолчанию", - "modmanager.button.updateChannel": "Канал обновления", - "modmanager.button.save": "Сохранить", - "modmanager.button.hide": "Скрыть обновления", - "modmanager.button.show": "Показать обновления", - "modmanager.button.open": "Открыть менеджер модов", - "modmanager.categories": "Категории", - "modmanager.category.updatable": "Обновления", - "modmanager.category.technology": "Технологии", - "modmanager.category.adventure": "Приключения", - "modmanager.category.magic": "Магия", - "modmanager.category.utility": "Утилиты", - "modmanager.category.decoration": "Косметика", - "modmanager.category.library": "Библиотеки", - "modmanager.category.cursed": "Проклятые", - "modmanager.category.worldgen": "Генерация мира", - "modmanager.category.storage": "Инвентарь", - "modmanager.category.search": "Поиск", - "modmanager.category.food": "Еда", - "modmanager.category.equipment": "Экипировка", - "modmanager.category.misc": "Разное", - "modmanager.changes.title": "§e§lОбнаружены изменения§r", - "modmanager.changes.message": "Изменения вступят в силу после перезапуска.\nЗакрыть Minecraft сайчас?", - "modmanager.channel.info": "Переключиться между стабильными и бета-версиями", - "modmanager.channel.all": "Все", - "modmanager.channel.stable": "Стабильные", - "modmanager.channel.unstable": "Нестабильные", - "modmanager.details.author": "Автор: %s", - "modmanager.details.versioning": "С %s до %s", - "modmanager.error.title": "§b§4Ошибка:§r", - "modmanager.error.container.notFound": "Мод, который вы пытаетесь обновить, был удалён.\nОбновление не представляется возможным.", - "modmanager.error.unknown": "Неизвестная ошибка при получении данных:\n %s", - "modmanager.error.unknown.install": "Неизвестная ошибка в процессе установки:\n %s", - "modmanager.error.unknown.update": "Неизвестная ошибка в процессе обновления:\n %s", - "modmanager.error.invalidStatus": "Получен неверный код состояния:\n %d", - "modmanager.error.network": "Ошибка подключения при получении данных:\n %s", - "modmanager.error.failedToParse": "Не удалось обработать запрос:\n %s", - "modmanager.error.noCompatibleModVersionFound": "Совместимая версия для вашего текущего канала не найдена.\nПопробуйте изменить канал в настройках Mod Manager.", - "modmanager.error.noProviderSelected": "Выбранный поставщик %s недоступен.", - "modmanager.error.update.noFabricJar": "Автор мода пометил версию совместимой с Fabric,\nно не предоставил её.", - "modmanager.error.jar.notFound": "Ошибка Файл .jar не найден. Возможно, это часть другого мода?", - "modmanager.error.jar.failedDelete": "Не удалось удалить мод:\n %s", - "modmanager.error.invalidHash": "Ошибка Загруженный файл (вероятно) повреждён, так как хэши %s не совпадают.\nПроверьте ваше соединение или свяжитесь с автором мода.", - "modmanager.status.installing": "Установка %s...", - "modmanager.status.install.success": "%s успешно установлен!\nХотите продолжить?", - "modmanager.status.updating": "Обновление...", - "modmanager.status.update.success": "%s успешно обновлён!\nХотите продолжить?", - "modmanager.sorting.sort": "Сортировка", - "modmanager.sorting.relevance": "по популярности", - "modmanager.sorting.downloads": "по скачиваниям", - "modmanager.sorting.updated": "недавно обновлённые", - "modmanager.sorting.newest": "новейшие", - "modmanager.search": "Поиск...", - "modmanager.page.next": "Следующая страница", - "modmanager.page.previous": "Предыдущая страница", - "modmanager.provider.info": "Позволяет изменить источник по умолчанию для просмотра", - "modmanager.toast.update.title": "Доступны обновления!", - "modmanager.toast.update.description": "Можно обновить модов: %d", - "modmanager.title.updating": "Обновление всех модов..." -} diff --git a/src/main/resources/assets/modmanager/lang/tr_tr.json b/src/main/resources/assets/modmanager/lang/tr_tr.json deleted file mode 100644 index 27010bc..0000000 --- a/src/main/resources/assets/modmanager/lang/tr_tr.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "modmanager.badge.installed": "Kurulu", - "modmanager.badge.outdated": "Eski", - "modmanager.button.update": "Güncelle", - "modmanager.button.install": "Kur", - "modmanager.button.remove": "Kaldır", - "modmanager.button.updateAll": "Tümünü güncelle", - "modmanager.button.tryAgain": "Tekrar dene", - "modmanager.button.defaultProvider": "Varsayılan sağlayıcı", - "modmanager.button.updateChannel": "Güncelleme kanalı", - "modmanager.button.save": "Kaydet", - "modmanager.categories": "Kategoriler", - "modmanager.category.updatable": "Güncellenebilir Modlar", - "modmanager.category.technology": "Teknoloji", - "modmanager.category.adventure": "Macera", - "modmanager.category.magic": "Büyü", - "modmanager.category.utility": "Kullanışlı", - "modmanager.category.decoration": "Dekorasyon", - "modmanager.category.library": "Kütpahane", - "modmanager.category.cursed": "Lanetli", - "modmanager.category.worldgen": "Dünya Oluşumu", - "modmanager.category.storage": "Depolama", - "modmanager.category.search": "Ara", - "modmanager.category.food": "Yiyecek", - "modmanager.category.equipment": "Ekipman", - "modmanager.category.misc": "Çeşitli", - "modmanager.changes.title": "§e§lDeğişiklik algılandı§r", - "modmanager.changes.message": "Yapılan değişiklikler, oyunu yeniden başlattıktan sonra uygulanacaktır.\nMinecraft'ı şimdi kapat?", - "modmanager.channel.info": "Beta ve tam sürüm arasında geçiş yap", - "modmanager.channel.all": "Tümü", - "modmanager.channel.stable": "Kararlı", - "modmanager.channel.unstable": "Kararsız", - "modmanager.details.author": "%s tarafından", - "modmanager.details.versioning": "%s sürümünden, %s sürümüne", - "modmanager.error.title": "§b§4Hata:§r", - "modmanager.error.unknown": "Veri alınırken bilinmeyen bir hata meydana geldi:\n %s", - "modmanager.error.unknown.install": "Kurulum yapılırken bilinmeyen bir hata meydana geldi:\n %s", - "modmanager.error.unknown.update": "Güncelleme yapılırken bilinmeyen bir hata meydana geldi:\n %s", - "modmanager.error.invalidStatus": "Geçersiz durum kodu alındı:\n %d", - "modmanager.error.network": "Veri alınırken ağ sorunu meydana geldi:\n %s", - "modmanager.error.failedToParse": "Alınan yanıt, parçalanamadı (Failed to parse response):\n %s", - "modmanager.error.noCompatibleModVersionFound": "Şu anki kanalın için uyumlu sürüm bulunamadı!\nMod Manager ayarlarından kanalı değiştirmeyi dene!", - "modmanager.status.installing": "%s kuruluyor...", - "modmanager.status.install.success": "%s başarıyla kuruldu!\nGeri dönmek istiyor musun?", - "modmanager.status.updating": "%s güncelleniyor...", - "modmanager.status.update.success": "%s başarıyla güncellendi!\nGeri dönmek istiyor musun?", - "modmanager.sorting.sort": "Sırala", - "modmanager.sorting.relevance": "Önerilen", - "modmanager.sorting.downloads": "Yükleme Sayısı", - "modmanager.sorting.updated": "Güncellik", - "modmanager.sorting.newest": "En Yeniler", - "modmanager.search": "Ara...", - "modmanager.page.next": "Sıradaki Sayfa", - "modmanager.page.previous": "Önceki Sayfa", - "modmanager.provider.info": "Arama yapmak için varsayılan sağlayıcını değiştirmeni sağlar", - "modmanager.toast.update.title": "Güncellemeler Mevcut!", - "modmanager.toast.update.description": "%d mod güncellenebilir durumda", - "modmanager.error.jar.notFound": "Error jar file not found. Is it part of another mod?", - "modmanager.error.invalidHash": "Error the downloaded file is probably broken as the %s hashes don't match\nTry checking your network or contact the mod author" -} \ No newline at end of file diff --git a/src/main/resources/assets/modmanager/lang/zh_cn.json b/src/main/resources/assets/modmanager/lang/zh_cn.json deleted file mode 100644 index ac577e3..0000000 --- a/src/main/resources/assets/modmanager/lang/zh_cn.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "modmanager.badge.installed": "已安装", - "modmanager.badge.outdated": "可更新", - "modmanager.button.update": "更新", - "modmanager.button.install": "安装", - "modmanager.button.remove": "卸载", - "modmanager.button.updateAll": "更新全部", - "modmanager.button.tryAgain": "重试", - "modmanager.button.defaultProvider": "默认源", - "modmanager.button.updateChannel": "版本通道", - "modmanager.button.save": "保存", - "modmanager.button.hide": "隐藏更新", - "modmanager.button.show": "显示更新", - "modmanager.button.open": "打开 Mod Manager", - "modmanager.categories": "类别", - "modmanager.category.updatable": "可更新", - "modmanager.category.technology": "科技", - "modmanager.category.adventure": "冒险", - "modmanager.category.magic": "魔法", - "modmanager.category.utility": "辅助", - "modmanager.category.decoration": "装饰", - "modmanager.category.library": "前置", - "modmanager.category.cursed": "魔改", - "modmanager.category.worldgen": "世界生成", - "modmanager.category.storage": "储存", - "modmanager.category.search": "搜索", - "modmanager.category.food": "食物", - "modmanager.category.equipment": "装备", - "modmanager.category.misc": "杂项", - "modmanager.changes.title": "§e§l检测到更改§r", - "modmanager.changes.message": "更改将会在游戏重启后生效。\n现在退出游戏吗?", - "modmanager.channel.info": "在稳定版与测试版模组间切换", - "modmanager.channel.all": "所有", - "modmanager.channel.stable": "稳定版", - "modmanager.channel.unstable": "测试版", - "modmanager.details.author": "作者: %s", - "modmanager.details.versioning": "从%s到%s", - "modmanager.error.title": "§b§4错误: §r", - "modmanager.error.container.notFound": "你试图更新的模组已经被卸载了/这应该是不可能的.", - "modmanager.error.unknown": "检索数据时发生了未知错误:\n %s", - "modmanager.error.unknown.install": "安装过程中发生了未知错误:\n %s", - "modmanager.error.unknown.update": "更新过程中发生了未知错误:\n %s", - "modmanager.error.invalidStatus": "接收到了无效的状态码:\n %d", - "modmanager.error.network": "检索数据时发生了网络问题:\n %s", - "modmanager.error.failedToParse": "无法处理响应:\n %s", - "modmanager.error.noCompatibleModVersionFound": "在当前版本通道下没有找到适合当前版本的模组!\n请尝试在 Mod Manager 设置中更换版本通道。", - "modmanager.error.noProviderSelected": "选定的模组来源%s不可用!", - "modmanager.error.update.noFabricJar": "该模组的作者标记了这个模组有兼容 Fabric 的版本,但实际上并没有为 Fabric 提供一个版本!", - "modmanager.error.jar.notFound": "错误,没有找到 Jar 文件。它是另一个模组的一部分吗?", - "modmanager.error.jar.failedDelete": "删除模组失败:\n %s", - "modmanager.error.invalidHash": "错误,下载的文件可能已经损坏,因为 %s 的哈希值不匹配\n尝试检查您的网络或联系模组作者", - "modmanager.status.installing": "正在安装 %s...", - "modmanager.status.install.success": "%s 已成功安装!\n您想要返回吗?", - "modmanager.status.updating": "正在更新 %s...", - "modmanager.status.update.success": "%s 已成功更新!\n您想要返回吗?", - "modmanager.sorting.sort": "排序依据", - "modmanager.sorting.relevance": "相关性", - "modmanager.sorting.downloads": "下载数", - "modmanager.sorting.updated": "最近更新", - "modmanager.sorting.newest": "最新上传", - "modmanager.search": "搜索...", - "modmanager.page.next": "下一页", - "modmanager.page.previous": "上一页", - "modmanager.provider.info": "允许你更改检索时的默认模组来源", - "modmanager.toast.update.title": "检测到更新!", - "modmanager.toast.update.description": "%d个模组可更新", - "modmanager.title.updating": "正在更新所有模组..." -} diff --git a/src/main/resources/assets/modmanager/textures/gui/hide_button.png b/src/main/resources/assets/modmanager/textures/gui/hide_button.png deleted file mode 100644 index 06e38a8..0000000 Binary files a/src/main/resources/assets/modmanager/textures/gui/hide_button.png and /dev/null differ diff --git a/src/main/resources/assets/modmanager/textures/gui/install_button.png b/src/main/resources/assets/modmanager/textures/gui/install_button.png deleted file mode 100644 index 3fd02a0..0000000 Binary files a/src/main/resources/assets/modmanager/textures/gui/install_button.png and /dev/null differ diff --git a/src/main/resources/assets/modmanager/textures/gui/loading.png b/src/main/resources/assets/modmanager/textures/gui/loading.png deleted file mode 100644 index e7f2a2e..0000000 Binary files a/src/main/resources/assets/modmanager/textures/gui/loading.png and /dev/null differ diff --git a/src/main/resources/assets/modmanager/textures/gui/show_button.png b/src/main/resources/assets/modmanager/textures/gui/show_button.png deleted file mode 100644 index 516855c..0000000 Binary files a/src/main/resources/assets/modmanager/textures/gui/show_button.png and /dev/null differ diff --git a/src/main/resources/build.info b/src/main/resources/build.info deleted file mode 100644 index 25107b6..0000000 --- a/src/main/resources/build.info +++ /dev/null @@ -1,2 +0,0 @@ -version=${version} -releaseTarget=${release_target} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 4c08856..e62ca55 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,50 +1,51 @@ { "schemaVersion": 1, + "name": "ModManager", "id": "modmanager", "version": "${version}", - "name": "Mod Manager", "description": "Extends ModMenu with an additional tab where you can install mods from Modrinth", + "environment": "client", + "icon": "assets/modmanager/icon.png", "authors": [ - "DeathsGun" + "DeathsGun" + ], + "contributors": [ + "Felix14-v2", + "kuzeeeyk", + "MineCommanderCN", + "buiawpkgew1", + "luni3359", + "msfjarvis", + "AlphaKR93" ], "contact": { - "homepage": "https://modrinth.com/mod/modmanager", - "sources": "https://github.com/DeathsGun/ModManager", - "issues": "https://github.com/DeathsGun/ModManager/issues" + "homepage": "https://modrinth.com/mod/modmanager", + "sources": "https://github.com/ModManagerMC/ModManager", + "issues": "https://github.com/ModManagerMC/ModManager/issues" }, - "icon": "assets/modmanager/icon.png", - "license": "Apache-2.0", - "environment": "client", "entrypoints": { - "client": [ - { - "adapter": "kotlin", - "value": "xyz.deathsgun.modmanager.ModManager" - } - ], - "preLaunch": [ - { - "adapter": "kotlin", - "value": "xyz.deathsgun.modmanager.PreLaunchHook" - } - ], - "modmenu": [ - "xyz.deathsgun.modmanager.ModMenuEntrypoint" - ] + "client": [ + { + "adapter": "kotlin", + "value": "net.modmanagermc.modmanager.ModManagerEntrypoint" + } + ] }, "custom": { "modmanager": { "modrinth": "6kq7BzRK" } }, + "depends": { + "fabricloader": ">=0.12", + "fabric-language-kotlin": ">=${fabricKotlinVersion}", + "minecraft": "~1.18", + "java": ">=17" + }, + "breaks": { + "modget": "*" + }, "mixins": [ "modmanager.mixins.json" - ], - "depends": { - "fabricloader": ">=0.12", - "modmenu": "^${modmenu_version}", - "fabric-language-kotlin": ">=${fabric_kotlin_version}", - "minecraft": "1.18.x", - "java": ">=16" - } -} + ] +} \ No newline at end of file diff --git a/src/main/resources/modmanager.mixins.json b/src/main/resources/modmanager.mixins.json index 0fc525f..0d3471a 100644 --- a/src/main/resources/modmanager.mixins.json +++ b/src/main/resources/modmanager.mixins.json @@ -1,14 +1,14 @@ { "required": true, - "minVersion": "0.8", - "package": "xyz.deathsgun.modmanager.mixin", "compatibilityLevel": "JAVA_17", - "mixins": [ - ], + "minVersion": "0.8", + "package": "net.modmanagermc.modmanager.mixin", "client": [ - "ModsScreenMixin", + "ModMenuTexturedButtonWidgetMixin", + "ModsScreenMixin", + "MinecraftClientMixin" ], "injectors": { - "defaultRequire": 1 + "defaultRequire": 1 } -} +} \ No newline at end of file diff --git a/src/test/kotlin/xyz/deathsgun/modmanager/dummy/DummyModrinthProvider.kt b/src/test/kotlin/xyz/deathsgun/modmanager/dummy/DummyModrinthProvider.kt deleted file mode 100644 index cf192e0..0000000 --- a/src/test/kotlin/xyz/deathsgun/modmanager/dummy/DummyModrinthProvider.kt +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.dummy - -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json -import net.minecraft.text.TranslatableText -import xyz.deathsgun.modmanager.api.http.VersionResult -import xyz.deathsgun.modmanager.api.mod.Asset -import xyz.deathsgun.modmanager.api.mod.Version -import xyz.deathsgun.modmanager.api.mod.VersionType -import xyz.deathsgun.modmanager.api.provider.IModUpdateProvider -import xyz.deathsgun.modmanager.providers.modrinth.models.ModrinthVersion -import java.io.BufferedReader -import java.io.InputStreamReader -import java.time.Instant -import java.time.ZoneOffset - -/** - * Dummy which provided the version data - * for [xyz.deathsgun.modmanager.update.VersionFinderTest] - */ -internal class DummyModrinthVersionProvider : IModUpdateProvider { - - private val json = Json { - ignoreUnknownKeys = true - } - - override fun getName(): String { - return "Modrinth" - } - - /** - * Reads the provided id from /version/id.json - * @param id the mod slug from Modrinth - */ - @OptIn(ExperimentalSerializationApi::class) - override fun getVersionsForMod(id: String): VersionResult { - return try { - val stream = DummyModrinthVersionProvider::class.java.getResourceAsStream("/version/$id.json") - ?: return VersionResult.Error(TranslatableText("reading.failed")) - val reader = BufferedReader(InputStreamReader(stream)) - val modrinthVersions = json.decodeFromString>(reader.readText()) - val versions = ArrayList() - for (modVersion in modrinthVersions) { - if (!modVersion.loaders.contains("fabric")) { - continue - } - val assets = ArrayList() - for (file in modVersion.files) { - assets.add(Asset(file.url, file.filename, file.hashes, file.primary)) - } - versions.add( - Version( - modVersion.version, - modVersion.changelog, - // 2021-09-03T10:56:59.402790Z - Instant.parse(modVersion.releaseDate).atOffset( - ZoneOffset.UTC - ).toLocalDate(), - getVersionType(modVersion.type), - modVersion.gameVersions, - assets - ) - ) - } - VersionResult.Success(versions) - } catch (e: Exception) { - VersionResult.Error(TranslatableText("modmanager.error.failedToParse", e.message), e) - } - } - - private fun getVersionType(id: String): VersionType { - return when (id) { - "release" -> VersionType.RELEASE - "alpha" -> VersionType.ALPHA - "beta" -> VersionType.BETA - else -> VersionType.UNKNOWN - } - } -} \ No newline at end of file diff --git a/src/test/kotlin/xyz/deathsgun/modmanager/providers/modrinth/ModrinthTest.kt b/src/test/kotlin/xyz/deathsgun/modmanager/providers/modrinth/ModrinthTest.kt deleted file mode 100644 index 7c90694..0000000 --- a/src/test/kotlin/xyz/deathsgun/modmanager/providers/modrinth/ModrinthTest.kt +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.providers.modrinth - -import net.minecraft.text.TranslatableText -import org.junit.jupiter.api.Test -import xyz.deathsgun.modmanager.api.http.CategoriesResult -import xyz.deathsgun.modmanager.api.http.ModResult -import xyz.deathsgun.modmanager.api.http.ModsResult -import xyz.deathsgun.modmanager.api.http.VersionResult -import xyz.deathsgun.modmanager.api.mod.Category -import xyz.deathsgun.modmanager.api.mod.Mod -import xyz.deathsgun.modmanager.api.mod.VersionType -import xyz.deathsgun.modmanager.api.provider.Sorting -import kotlin.test.* - -internal class ModrinthTest { - - private val modrinth = Modrinth() - - @Test - fun getCategories() { - val result = modrinth.getCategories() - if (result is CategoriesResult.Error) { - result.cause?.let { - fail(result.text.key, it) - } - fail(result.text.key) - } - val categories = (result as CategoriesResult.Success).categories - assertTrue(categories.isNotEmpty()) - categories.forEach { - assertTrue(it.id.isNotEmpty()) - assertEquals(String.format("modmanager.category.%s", it.id), it.text.key) - } - } - - @Test - fun getModsBySorting() { - val result = modrinth.getMods(Sorting.NEWEST, 0, 10) - if (result is ModsResult.Error) { - result.cause?.let { - fail(result.text.key, it) - } - fail(result.text.key) - } - val mods = (result as ModsResult.Success).mods - checkMods(mods) - } - - @Test - fun getModsByCategory() { - val result = modrinth.getMods(listOf(Category("misc", TranslatableText(""))), Sorting.RELEVANCE, 0, 10) - if (result is ModsResult.Error) { - result.cause?.let { - fail(result.text.key, it) - } - fail(result.text.key) - } - val mods = (result as ModsResult.Success).mods - checkMods(mods) - } - - @Test - fun getModsByQuery() { - val result = modrinth.search("Mod", emptyList(), Sorting.DOWNLOADS, 0, 10) - if (result is ModsResult.Error) { - result.cause?.let { - fail(result.text.key, it) - } - fail(result.text.key) - } - val mods = (result as ModsResult.Success).mods - checkMods(mods) - } - - private fun checkMods(mods: List) { - assertTrue(mods.isNotEmpty()) - assertEquals(mods.size, 10) - mods.forEach { - assertTrue(it.id.isNotEmpty()) - assertTrue(it.slug.isNotEmpty()) - assertTrue(it.name.isNotEmpty()) - assertNotNull(it.author) - assertNotNull(it.iconUrl) - assertTrue(it.shortDescription.isNotEmpty()) - assertTrue(it.categories.isNotEmpty()) - - // Only filled when getMod(id) is called - assertNull(it.description, "description should be null as it's only loaded by getMod") - assertNull(it.license, "description should be null as it's only loaded by getMod") - } - } - - @Test - fun getMod() { - val testMod = modrinth.getMods(Sorting.NEWEST, 0, 1) - if (testMod is ModsResult.Error) { - testMod.cause?.let { - fail(testMod.text.key, it) - } - fail(testMod.text.key) - } - val result = modrinth.getMod((testMod as ModsResult.Success).mods[0].id) - if (result is ModResult.Error) { - result.cause?.let { - fail(result.text.key, it) - } - fail(result.text.key) - } - val mod = (result as ModResult.Success).mod - assertTrue(mod.id.isNotEmpty()) - assertTrue(mod.slug.isNotEmpty()) - assertTrue(mod.name.isNotEmpty()) - assertNull(mod.author) - assertTrue(mod.shortDescription.isNotEmpty()) - assertTrue(mod.categories.isNotEmpty()) - assertNotNull(mod.description) - assertTrue(mod.description!!.isNotEmpty()) - assertNotNull(mod.license) - assertTrue(mod.license!!.isNotEmpty()) - } - - @Test - fun getVersionsForMod() { - val result = modrinth.getVersionsForMod("6kq7BzRK") - if (result is VersionResult.Error) { - result.cause?.let { - fail(result.text.key, it) - } - fail(result.text.key) - } - val versions = (result as VersionResult.Success).versions - assertTrue(versions.isNotEmpty()) - versions.forEach { - assertTrue(it.gameVersions.isNotEmpty()) - assertTrue(it.version.isNotEmpty()) - assertTrue(it.changelog.isNotEmpty()) - it.assets.forEach { asset -> - assertTrue(asset.filename.isNotEmpty()) - assertTrue(asset.filename.endsWith(".jar")) - assertTrue(asset.url.isNotEmpty()) - assertTrue(asset.hashes.isNotEmpty()) - assertContains(asset.hashes, "sha512") - } - } - } -} \ No newline at end of file diff --git a/src/test/kotlin/xyz/deathsgun/modmanager/update/VersionFinderTest.kt b/src/test/kotlin/xyz/deathsgun/modmanager/update/VersionFinderTest.kt deleted file mode 100644 index 82ff9b8..0000000 --- a/src/test/kotlin/xyz/deathsgun/modmanager/update/VersionFinderTest.kt +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2021 DeathsGun - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package xyz.deathsgun.modmanager.update - -import net.fabricmc.loader.api.VersionParsingException -import org.junit.jupiter.api.DynamicTest.dynamicTest -import org.junit.jupiter.api.TestFactory -import org.junit.jupiter.api.fail -import xyz.deathsgun.modmanager.api.http.VersionResult -import xyz.deathsgun.modmanager.api.provider.IModUpdateProvider -import xyz.deathsgun.modmanager.config.Config -import xyz.deathsgun.modmanager.dummy.DummyModrinthVersionProvider -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull -import kotlin.test.assertTrue - -/** - * Tests the [VersionFinder] implementation - */ -internal class VersionFinderTest { - - private val provider: IModUpdateProvider = DummyModrinthVersionProvider() - - /** - * Tests the fallback for versions which are not following - * the SemVer scheme. These mods are resolved by their release date. - */ - @TestFactory - fun findUpdateByFallback() = listOf( - Scenario( - "lithium", - "mc1.17.1-0.7.4", - "mc1.17.1-0.7.1", - Config.UpdateChannel.STABLE, - "1.17" - ), - Scenario( - "dynamic-fps", - "v2.0.5", - "2.0.5", - Config.UpdateChannel.STABLE, - "1.17" - ), - Scenario( - "iris", - "mc1.17.1-1.1.2", - "mc1.17-v1.1.1", - Config.UpdateChannel.STABLE, - "1.17" - ) - ).map { scenario -> - dynamicTest("${scenario.mod} ${scenario.expectedVersion} ${scenario.channel}") { - val versions = when (val result = provider.getVersionsForMod(scenario.mod)) { - is VersionResult.Error -> fail(result.text.key, result.cause) - is VersionResult.Success -> result.versions - } - val latest = VersionFinder.findUpdateFallback( - scenario.installedVersion, - scenario.mcVersion, - scenario.mcVersion, - scenario.channel, - versions - ) - assertNotNull(latest) - assertEquals(scenario.expectedVersion, latest.version) - assertTrue(latest.assets.isNotEmpty()) - } - } - - /** - * Tests some version scenarios in which the [VersionFinder] - * should definitely return null. - */ - @TestFactory - fun findUpdateByVersionError() = listOf( - /** - * This scenario will fail because mc1.17.1-0.7.1 - * can not be parsed by the parser as it starts with mc. - */ - Scenario( - "lithium", - "none", - "mc1.17.1-0.7.1", - Config.UpdateChannel.STABLE, - "1.17" - ), - /** - * This scenario will fail because fabric-5.3.3-BETA+6027c282 - * can not be parsed by the parser as it starts with fabric. - */ - Scenario( - "terra", - "none", - "fabric-5.3.3-BETA+6027c282", - Config.UpdateChannel.ALL, - "1.17" - ), - /** - * No update for this scenario should be found. - * When an update should be found this would be an - * error as 2.0.13 is the latest - */ - Scenario( - "modmenu", - "none", - "2.0.13", - Config.UpdateChannel.STABLE, - "1.17" - ) - ).map { scenario -> - dynamicTest("${scenario.mod} ${scenario.expectedVersion} ${scenario.channel}") { - val versions = when (val result = provider.getVersionsForMod(scenario.mod)) { - is VersionResult.Error -> fail(result.text.key, result.cause) - is VersionResult.Success -> result.versions - } - val latest = try { - VersionFinder.findUpdateByVersion( - scenario.installedVersion, - scenario.mcVersion, - scenario.mcVersion, - scenario.channel, - versions - ) - } catch (e: VersionParsingException) { - null - } - assertNull(latest) - } - } - - /** - * This tests all mods which are following the semantic version scheme. - */ - @TestFactory - fun findUpdateByVersion() = listOf( - Scenario( - "modmanager", - "1.0.2+1.17-alpha", - "1.0.0-alpha", - Config.UpdateChannel.ALL, - "1.17" - ), - Scenario( - "modmenu", - "2.0.13", - "2.0.5", - Config.UpdateChannel.ALL, - "1.17" - ) - ).map { scenario -> - dynamicTest("${scenario.mod} ${scenario.expectedVersion} ${scenario.channel}") { - val versions = when (val result = provider.getVersionsForMod(scenario.mod)) { - is VersionResult.Error -> fail(result.text.key, result.cause) - is VersionResult.Success -> result.versions - } - val latest = VersionFinder.findUpdateByVersion( - scenario.installedVersion, - scenario.mcVersion, - scenario.mcVersion, - scenario.channel, - versions - ) - assertNotNull(latest) - assertEquals(scenario.expectedVersion, latest.version) - } - } - - private data class Scenario( - val mod: String, - val expectedVersion: String, - val installedVersion: String, - val channel: Config.UpdateChannel, - val mcVersion: String - ) -} \ No newline at end of file diff --git a/src/test/resources/version/dynamic-fps.json b/src/test/resources/version/dynamic-fps.json deleted file mode 100644 index 1dd0cf7..0000000 --- a/src/test/resources/version/dynamic-fps.json +++ /dev/null @@ -1,246 +0,0 @@ -[ - { - "id": "RgJGw0dO", - "mod_id": "LQ3K71Q1", - "author_id": "HLI9Dbyv", - "featured": false, - "name": "v2.0.5", - "version_number": "v2.0.5", - "changelog": "- Worked around reload screen fadeout not working (#35—thanks, altrisi!)\n- File size reduced by ~300 KB (#30—thanks, wafflecoffee!)\n- Localization updates: Russian (#28), Chinese (#34)", - "changelog_url": null, - "date_published": "2021-08-08T21:03:25.103818Z", - "downloads": 2929, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "84135f5da20608c732ac90439dd7929dcf61cc6471667e5c8842466ec0cbfdf3199d8dc2cdb2088b5ba76cde55c5df015989b00376d6be65c4b8a1c1d3b13be7", - "sha1": "07eab9095517baedb1ba8426310e7fa66fd9747d" - }, - "url": "https://cdn.modrinth.com/data/LQ3K71Q1/versions/v2.0.5/dynamic-fps-2.0.5.jar", - "filename": "dynamic-fps-2.0.5.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "oIZUkvvs", - "mod_id": "LQ3K71Q1", - "author_id": "HLI9Dbyv", - "featured": false, - "name": "2.0.4", - "version_number": "v2.0.4", - "changelog": "- Added an option to run garbage collection whenever the window loses focus.", - "changelog_url": null, - "date_published": "2021-06-29T12:56:14.536461Z", - "downloads": 1300, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "a172c61df0a4deffa669d19f7dd83282b2ea0210", - "sha512": "539617d9f1b32fc4ef3859ec6c7cf934de20552b0f3255b8881213c8496fbcb7d646375fd5558cf173d8ce7db9e97add9f2f49b3dd05ee181f6334d14b9c666f" - }, - "url": "https://cdn.modrinth.com/data/LQ3K71Q1/versions/v2.0.4/dynamic-fps-2.0.4.jar", - "filename": "dynamic-fps-2.0.4.jar", - "primary": true - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1-pre1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "muZxaaxq", - "mod_id": "LQ3K71Q1", - "author_id": "HLI9Dbyv", - "featured": false, - "name": "2.0.2", - "version_number": "v2.0.2", - "changelog": "- Updated Russian Localization ([#22—Felix14-v2](https://github.com/juliand665/Dynamic-FPS/pull/22))", - "changelog_url": null, - "date_published": "2021-05-08T14:35:25.087402Z", - "downloads": 1524, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "1b080f859e529dbe87a0b5d7c71adfbb6bca5db4", - "sha512": "b3a8a9e008a3cf6c585c3ddd016374f6e202e8f321259c7c2cd014936884d4658ad5ef0de685e0cee92d51840c12ef8a5438efc2a7e7ffaf4dfe3745dad293d5" - }, - "url": "https://cdn.modrinth.com/data/LQ3K71Q1/versions/2.0.2/dynamic-fps-2.0.2.jar", - "filename": "dynamic-fps-2.0.2.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5", - "21w03a", - "21w05a", - "21w05b", - "21w06a", - "21w07a", - "21w08a", - "21w08b", - "21w10a", - "21w11a", - "21w13a", - "21w14a", - "21w15a", - "21w16a", - "21w17a", - "21w18a" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "XlBOTUIQ", - "mod_id": "LQ3K71Q1", - "author_id": "HLI9Dbyv", - "featured": false, - "name": "Localization", - "version_number": "v2.0.1", - "changelog": "", - "changelog_url": null, - "date_published": "2021-01-21T04:25:08.291787Z", - "downloads": 772, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "923eb8206fea45bfc455bb195d71ab3eddf986e1cc2cc48fa9543e7601b34c0e184ad463f4c119622218559a7872ea4e3ebc6815c2dc172f41d1cabe1171ffa2", - "sha1": "672904fc5332f7064db872635549b63a10444f59" - }, - "url": "https://cdn.modrinth.com/data/LQ3K71Q1/versions/v2.0.1/dynamic-fps-2.0.1.jar", - "filename": "dynamic-fps-2.0.1.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.2", - "1.16.3", - "1.16.3-rc1", - "1.16.4", - "1.16.4-pre1", - "1.16.4-pre2", - "1.16.4-rc1", - "1.16.5", - "1.16.5-rc1", - "20w45a", - "20w46a", - "20w48a", - "20w49a", - "20w51a", - "21w03a" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "gVvtLF6M", - "mod_id": "LQ3K71Q1", - "author_id": "HLI9Dbyv", - "featured": false, - "name": "Configurability", - "version_number": "v2.0.0", - "changelog": "", - "changelog_url": null, - "date_published": "2021-01-19T16:53:49.879150Z", - "downloads": 28, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "972a09c66b164dd77e97524e06fc16904a859863", - "sha512": "38e85da3025c9b47905781fae0f4ae10a2437e97716c3fa60bb04510c57154e14e3cbd17a6ee5a8b375ee66621010a0110f9784709abd3a7fbdbbb5220be0be7" - }, - "url": "https://cdn.modrinth.com/data/LQ3K71Q1/versions/v2.0.0/dynamic-fps-2.0.0.jar", - "filename": "dynamic-fps-2.0.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.2", - "1.16.3", - "1.16.3-rc1", - "1.16.4", - "1.16.4-pre1", - "1.16.4-pre2", - "1.16.4-rc1", - "1.16.5", - "1.16.5-rc1", - "20w45a", - "20w46a", - "20w48a", - "20w49a", - "20w51a" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "kurPEwi6", - "mod_id": "LQ3K71Q1", - "author_id": "HLI9Dbyv", - "featured": false, - "name": "Localization", - "version_number": "v1.2.1", - "changelog": "", - "changelog_url": "https://cdn.modrinth.com/data/LQ3K71Q1/versions/v1.2.1/changelog.md", - "date_published": "2021-01-07T18:37:47.131931Z", - "downloads": 17, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "2103fd47a4ee86087e908df34eacdcb0bc271d09" - }, - "url": "https://cdn.modrinth.com/data/LQ3K71Q1/versions/v1.2.1/dynamic-fps-1.2.1.jar", - "filename": "dynamic-fps-1.2.1.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.2", - "1.16.2-pre1", - "1.16.2-pre2", - "1.16.2-pre3", - "1.16.2-rc1", - "1.16.2-rc2", - "1.16.3", - "1.16.3-rc1", - "1.16.4", - "1.16.4-pre1", - "1.16.4-pre2", - "1.16.4-rc1", - "20w45a", - "20w46a", - "20w48a", - "20w49a", - "20w51a" - ], - "loaders": [ - "fabric" - ] - } -] \ No newline at end of file diff --git a/src/test/resources/version/iris.json b/src/test/resources/version/iris.json deleted file mode 100644 index 66023ff..0000000 --- a/src/test/resources/version/iris.json +++ /dev/null @@ -1,220 +0,0 @@ -[ - { - "id": "YwBoFV6P", - "mod_id": "YL57xq9U", - "author_id": "v7k4QluE", - "featured": false, - "name": "Iris v1.1.2 + Sodium for MC 1.17.1", - "version_number": "mc1.17.1-1.1.2", - "changelog": "A trimmed changelog is available below. A more detailed changelog is available [on GitHub](https://github.com/IrisShaders/Iris/blob/trunk/docs/changelogs/1.1.2/full.md) for those who are interested.\n\n## Notable Changes\n\n- This release includes a new shadow culling system as well as a new batched entity rendering system, improving performance with many shader packs and fixing a bunch of bugs!\n- For 1.17.1 and above, this release also contains a modified version of Sodium based on 0.3.2 instead of 0.3.0 like before, improving performance and graphics driver compatibility.\n\n## Major changes for all versions\n\n- Shadow culling has been completely rewritten. It no longer incorrectly culls chunks compared to OptiFine, and overall performance has improved greatly compared to the previous system (especially with shader packs like Enhanced Default, BSL, and Complementary Shaders).\n- A Max Shadow Distance slider is now available in Video Settings, allowing you to tweak the render distance of shadows on packs that don't specify one.\n- Batched entity rendering has been completely rewritten, fixing many memory management, correctness, and performance issues.\n- Fog now fully works in most shader packs, including Sildur's Enhanced Default and other vanilla-like shaders\n- Entities now flash red when hurt, and flash white when they are going to explode\n- End portals now properly render with most shader packs\n- blockEntityId and entityId are now fully supported (Fixes many issues with Complementary Shaders' Integrated PBR)\n- Iris now has initial support for the path-traced lighting in SEUS PTGI, and has some fixes to the lighting in SEUS Renewed. (SEUS PTGI is still not officially supported, its water still does not work on Iris.)\n\n## Major fixes for 1.17.1 and above\n\n- End gateway beams no longer appear to render twice with shader packs that use shadows.\n- Fixed separate leads incorrectly rendering as connected\n- Block selection outlines now render properly, even with world curvature enabled. (due to a different issue that will be fixed soon, this doesn't work with some packs like Enhanced Default.)\n- Chunk borders (F3 + G), hitboxes, and other lines now render properly with shaders enabled. (similarly, this doesn't work with some packs like Enhanced Default.)\n- World borders render properly with most packs now.\n- The energy swirl around charged creepers now renders properly.\n\n## Mod compatibility fixes\n\n- Fix most issues with Physics Mod\n- Initial compatibility with Immersive Portals is now available on 1.17.1, though there are still issues. (credit to qouteall for implementing the compatibility code)\n- Fixed an issue where directional shading would be enabled on some blocks rendered with the Fabric Rendering API, even if the shader pack disabled it. (Fixes issues with CTM mods)\n- Added a new screen for when you have an incompatible version of Sodium installed.\n\n## But wait, there's more!\n\nFor the first time, we are releasing versions of Iris for the 1.18 snapshots for everyone to use. These builds do not represent the final version, however, they should be mostly playable (though there are significant performance issues caused by 1.18 itself.) These builds will be released to Patrons first for testing, then released for the general public after a few days once we confirm no major issues are in them. Currently, you can only get 1.18 versions of Iris through Github Releases (for Fabric). Overall, shaders should be mostly usable on 1.18 snapshots!\n", - "changelog_url": null, - "date_published": "2021-09-06T02:38:18.747662Z", - "downloads": 5205, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "55a13a56c6eed76ab98fdce9bcf8f4dbaa66a2b09f6caf254fdd24ff4bd0f147542e380be9f854b85048848eaaa1d478beef84c3b8f4f271a345b529f312a161", - "sha1": "259d43b3b89827a22717f5628dcb67469224adbd" - }, - "url": "https://cdn.modrinth.com//data/YL57xq9U/versions/mc1.17.1-1.1.2/iris-and-sodium-mc1.17-1.1.2+build.9.jar", - "filename": "iris-and-sodium-mc1.17-1.1.2+build.9.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "ZmYHYMB0", - "mod_id": "YL57xq9U", - "author_id": "v7k4QluE", - "featured": false, - "name": "Iris v1.1.2 + Sodium for MC 1.16.5", - "version_number": "mc1.16.5-1.1.2", - "changelog": "A trimmed changelog is available below. A more detailed changelog is available [on GitHub](https://github.com/IrisShaders/Iris/blob/trunk/docs/changelogs/1.1.2/full.md) for those who are interested.\n\n## Notable Changes\n\n- This release includes a new shadow culling system as well as a new batched entity rendering system, improving performance with many shader packs and fixing a bunch of bugs!\n- For 1.17.1 and above, this release also contains a modified version of Sodium based on 0.3.2 instead of 0.3.0 like before, improving performance and graphics driver compatibility.\n\n## Major changes for all versions\n\n- Shadow culling has been completely rewritten. It no longer incorrectly culls chunks compared to OptiFine, and overall performance has improved greatly compared to the previous system (especially with shader packs like Enhanced Default, BSL, and Complementary Shaders).\n- A Max Shadow Distance slider is now available in Video Settings, allowing you to tweak the render distance of shadows on packs that don't specify one.\n- Batched entity rendering has been completely rewritten, fixing many memory management, correctness, and performance issues.\n- Fog now fully works in most shader packs, including Sildur's Enhanced Default and other vanilla-like shaders\n- Entities now flash red when hurt, and flash white when they are going to explode\n- End portals now properly render with most shader packs\n- blockEntityId and entityId are now fully supported (Fixes many issues with Complementary Shaders' Integrated PBR)\n- Iris now has initial support for the path-traced lighting in SEUS PTGI, and has some fixes to the lighting in SEUS Renewed. (SEUS PTGI is still not officially supported, its water still does not work on Iris.)\n\n## Major fixes for 1.17.1 and above\n\n- End gateway beams no longer appear to render twice with shader packs that use shadows.\n- Fixed separate leads incorrectly rendering as connected\n- Block selection outlines now render properly, even with world curvature enabled. (due to a different issue that will be fixed soon, this doesn't work with some packs like Enhanced Default.)\n- Chunk borders (F3 + G), hitboxes, and other lines now render properly with shaders enabled. (similarly, this doesn't work with some packs like Enhanced Default.)\n- World borders render properly with most packs now.\n- The energy swirl around charged creepers now renders properly.\n\n## Mod compatibility fixes\n\n- Fix most issues with Physics Mod\n- Initial compatibility with Immersive Portals is now available on 1.17.1, though there are still issues. (credit to qouteall for implementing the compatibility code)\n- Fixed an issue where directional shading would be enabled on some blocks rendered with the Fabric Rendering API, even if the shader pack disabled it. (Fixes issues with CTM mods)\n- Added a new screen for when you have an incompatible version of Sodium installed.\n\n## But wait, there's more!\n\nFor the first time, we are releasing versions of Iris for the 1.18 snapshots for everyone to use. These builds do not represent the final version, however, they should be mostly playable (though there are significant performance issues caused by 1.18 itself.) These builds will be released to Patrons first for testing, then released for the general public after a few days once we confirm no major issues are in them. Currently, you can only get 1.18 versions of Iris through Github Releases (for Fabric). Overall, shaders should be mostly usable on 1.18 snapshots!\n", - "changelog_url": null, - "date_published": "2021-09-06T02:31:47.141289Z", - "downloads": 1004, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "3a5f8fa1da6973da5714c7577388049dc3183699", - "sha512": "4c4458f0a82141e3a91b92c678ec37503c8304e32e2f47f28141068cb214aec5243b8f5c48fd88e4a880dcf5f2c8cc4707095996deff05692f6b19dddebc6372" - }, - "url": "https://cdn.modrinth.com//data/YL57xq9U/versions/mc1.16.5-1.1.2/iris-and-sodium-mc1.16.5-1.1.2+build.4.jar", - "filename": "iris-and-sodium-mc1.16.5-1.1.2+build.4.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "AosvzXCO", - "mod_id": "YL57xq9U", - "author_id": "DzLrfrbK", - "featured": false, - "name": "Iris v1.1.1 + Sodium for MC 1.16.5", - "version_number": "mc1.16.5-v1.1.1", - "changelog": "This release primarily fixes a number of stability issues in Iris. \n\n\n\nFixes for 1.16.5 & 1.17.1: - Fixed Complementary not compiling on macOS in non-overworld dimensions - Avoid crashes with Physics Mod, but there are still some weird bugs with it - Fixed colored shadows not working (this was a regression shipped in 1.1.0) - Fixed clouds being cut off at low render distances when shaders are disabled - Added rudimentary support for atlasSize, needed by newer versions of Complementary Shaders - Fixed block breaking animations for block entities - Support separateAo for blocks rendered with the Fabric Rendering API - Fixed a number of issues related to the ordering of entity rendering", - "changelog_url": null, - "date_published": "2021-07-29T02:06:23.037856Z", - "downloads": 4309, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "59f6678d834ae190100931d218b250dc56c5ae1f", - "sha512": "a2e6b52c16d42750b19f0dda93a94235df15a8c4ec061866585a4ca4899c2b5caedce30b5af4bb41eb7df7cb6a958d82ff9502c508756ea8e40f0cc23e03c34e" - }, - "url": "https://cdn.modrinth.com/data/YL57xq9U/versions/mc1.16.5-v1.1.1/iris-mc1.16.5-1.1.1.jar", - "filename": "iris-mc1.16.5-1.1.1.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "lAEtBzCu", - "mod_id": "YL57xq9U", - "author_id": "DzLrfrbK", - "featured": false, - "name": "Iris v1.1.1 + Sodium for MC 1.17.1", - "version_number": "mc1.17-v1.1.1", - "changelog": "This release primarily fixes a number of stability issues in the 1.17.1 version of Iris. Previously, the bundled version of Sodium for 1.17 was based on an older beta build, but now we've released to the much more stable Sodium 0.3.0 release. In addition, IMS fixed a memory leak in the sky horizon rendering code on Iris for 1.17.1.\n\n \n\nOverall, Iris 1.1.1 for 1.17.1 is much more stable than Iris 1.1.0 for 1.17.1! We've been working on a much bigger update, but unfortunately that code isn't quite ready yet. Instead of continually holding back critical fixes until that code is ready, we've decided to pull the critical fixes into an intermediate build, giving us time to polish up the next update.\n\n \n\nFixes for 1.16.5 & 1.17.1: - Fixed Complementary not compiling on macOS in non-overworld dimensions - Avoid crashes with Physics Mod, but there are still some weird bugs with it - Fixed colored shadows not working (this was a regression shipped in 1.1.0) - Fixed clouds being cut off at low render distances when shaders are disabled - Added rudimentary support for atlasSize, needed by newer versions of Complementary Shaders - Fixed block breaking animations for block entities - Support separateAo for blocks rendered with the Fabric Rendering API - Fixed a number of issues related to the ordering of entity rendering\n\n \n\nFixes for 1.17.1: - Allow shader packs to detect when the player is in powdered snow - The bundled version of Sodium is now based on the 0.3.0 release instead of a beta build, fixing a memory leak - Fixed vanilla clouds not rendering in packs that use them - Fixed beacon beams not rendering - Fixed a memory leak in horizon rendering", - "changelog_url": null, - "date_published": "2021-07-29T02:04:54.765633Z", - "downloads": 14135, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "6fc947f2b749502ac510c65cebfeab9f64cecfe1", - "sha512": "18aa480d8503cf98e87bc37ba734ca61b2f1c85dd92a52e5501b4e2a5d8fe17dba1de9b748155c054cb6a3f31e1fc9643d4491413ad7cf7f20ba90aec338cb76" - }, - "url": "https://cdn.modrinth.com/data/YL57xq9U/versions/mc1.17-v1.1.1/iris-mc1.17-1.1.1.jar", - "filename": "iris-mc1.17-1.1.1.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "lQjKfhXZ", - "mod_id": "YL57xq9U", - "author_id": "v7k4QluE", - "featured": false, - "name": "Iris v1.1.0 + Sodium for MC 1.17", - "version_number": "mc1.17-v1.1.0", - "changelog": "This release includes fixes for the vast majority of the hardware compatibility issues that Iris 1.0.0 faced. In addition, a compatible version of Sodium is now available for 1.17, allowing people to have incredible performance with shaders on both Minecraft 1.16 and Minecraft 1.17!\n\n", - "changelog_url": null, - "date_published": "2021-06-29T23:26:10.609754Z", - "downloads": 9051, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "80da62de0e01bf4023e640326e4a05bd5b5ee007", - "sha512": "09c473690fb28a7b9df862d2168bf5430e13e91112d67d1936399685900973956e2243669ce3daf1f73ca53f4a8baabc3a6a4bb84791c579ee531cb9ca468c06" - }, - "url": "https://cdn.modrinth.com/data/YL57xq9U/versions/mc1.17-v1.1.0/iris-mc1.17-1.1.0.jar", - "filename": "iris-mc1.17-1.1.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "7ULwjID9", - "mod_id": "YL57xq9U", - "author_id": "v7k4QluE", - "featured": false, - "name": "Iris v1.1.0 + Sodium for MC 1.16.5", - "version_number": "mc1.16.5-v1.1.0", - "changelog": "This release includes fixes for the vast majority of the hardware compatibility issues that Iris 1.0.0 faced. It also includes a number of general bug fixes.", - "changelog_url": null, - "date_published": "2021-06-29T23:24:38.723910Z", - "downloads": 3856, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "4c34acec4277eaeb0f4f111a7308c87f8c8fabce66af8c736b7f8492b0a448e6ebf28587208305ae740f5efa751fede24a9315e19dbcfda31473683b931a0f54", - "sha1": "ab3cd5967d11221ebf3e0374f13ecfac2e8ff7bf" - }, - "url": "https://cdn.modrinth.com/data/YL57xq9U/versions/mc1.16.5-v1.1.0/iris-mc1.16.5-1.1.0.jar", - "filename": "iris-mc1.16.5-1.1.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "BKUpdPtO", - "mod_id": "YL57xq9U", - "author_id": "DzLrfrbK", - "featured": false, - "name": "Iris - Sodium", - "version_number": "1.0.0-sodium", - "changelog": "This is the recommended version to use, for users who want a stable experience on 1.16.5.", - "changelog_url": null, - "date_published": "2021-06-09T23:01:39.653663Z", - "downloads": 3338, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "faa6f06df478e6c5297e47cb7eb7a9ade4904d4210a2ff27935140187604d2bf071e11468fe9cd479803c8ce4e4d1d3f49a17238cc6f6204864f89784032ec7c", - "sha1": "5d7ea138d8f47a6e26eda6acec849fea06cc6ec1" - }, - "url": "https://cdn.modrinth.com/data/YL57xq9U/versions/1.0.0-sodium/iris-mc1.16.5-1.0.0.jar", - "filename": "iris-mc1.16.5-1.0.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - } -] \ No newline at end of file diff --git a/src/test/resources/version/lithium.json b/src/test/resources/version/lithium.json deleted file mode 100644 index c5e0ed5..0000000 --- a/src/test/resources/version/lithium.json +++ /dev/null @@ -1,359 +0,0 @@ -[ - { - "id": "nVR7Q63z", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.7.4", - "version_number": "mc1.17.1-0.7.4", - "changelog": "The changelog is available on GitHub right [here](https://github.com/CaffeineMC/lithium-fabric/releases/tag/mc1.17.1-0.7.4).", - "changelog_url": null, - "date_published": "2021-08-25T15:11:04.183885Z", - "downloads": 7602, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "32e06c4d401fcba6ef539cd6dbfa0ee032302462", - "sha512": "e3564bef105f23b6d4f77196f080f6bae3eed78b810e795c41b6587e88130ead66d0bbc01225a2ca2a3b1bdaedd7baec35219e28e36b3fe5c7a9b694618dfc76" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.17.1-0.7.4/lithium-fabric-mc1.17.1-0.7.4.jar", - "filename": "lithium-fabric-mc1.17.1-0.7.4.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "cTZv31gu", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.7.3", - "version_number": "mc1.17.1-0.7.3", - "changelog": "The changelog is available on GitHub right [here](https://github.com/CaffeineMC/lithium-fabric/releases/tag/mc1.17.1-0.7.3).", - "changelog_url": null, - "date_published": "2021-07-07T15:19:45.667011Z", - "downloads": 11059, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "9b128f30cf2ac2b48abe69c11da805a52522504d", - "sha512": "302a9ac685e513b75eb4dea0d956335f1dfbda33b5b19e94e8df76172a7502cf02a68faf801c623ff0775f12f3831fc863ff7f83af44105098376956ed331c5c" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.17.1-0.7.3/lithium-fabric-mc1.17.1-0.7.3.jar", - "filename": "lithium-fabric-mc1.17.1-0.7.3.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "aZ0JFf08", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.7.2", - "version_number": "mc1.17-0.7.2", - "changelog": "The changelog is available on GitHub right [here](https://github.com/CaffeineMC/lithium-fabric/releases/tag/mc1.17-0.7.2).", - "changelog_url": null, - "date_published": "2021-06-21T15:47:40.697756Z", - "downloads": 2696, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "ca6b619a6399c9edba99ef70a73f9836ba3dab27dc335f8d709ef732b2121855f245c0bb82dbcffa6932ae2965e9f2ec8b86d3ef3215af2afcaf9fbb8e109bc1", - "sha1": "1c69065da5730027343db347a7bf0ff0e257dd1b" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.17-0.7.2/lithium-fabric-mc1.17-0.7.2.jar", - "filename": "lithium-fabric-mc1.17-0.7.2.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "7jxErppe", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.7.1", - "version_number": "mc1.17-0.7.1", - "changelog": "The changelog is available on GitHub right [here](https://github.com/CaffeineMC/lithium-fabric/releases/tag/mc1.17-0.7.1).", - "changelog_url": null, - "date_published": "2021-06-16T18:38:57.919231Z", - "downloads": 901, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "352fd021048737693d2fbae1b9ad5d10e4c4c1f8", - "sha512": "647b5b626978b2cad5b44616808543445bc565e87b53c7b9bb026bd3d00f10f5c350d8c9e93677268c93d0ace0e7c1d2b27e0fe8b5814be297f01204f7188bb2" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.17-0.7.1/lithium-fabric-mc1.17-0.7.1.jar", - "filename": "lithium-fabric-mc1.17-0.7.1.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "rvsW1zhb", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.6.6", - "version_number": "mc1.16.5-0.6.6", - "changelog": "The changelog is available on GitHub right [here](https://github.com/jellysquid3/lithium-fabric/releases/tag/mc1.16.5-0.6.6).", - "changelog_url": null, - "date_published": "2021-06-09T13:10:44.980214Z", - "downloads": 4534, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "bb2dd085a6c5fcf86ba9a63d680fb5144a5788efe9c00a9417d978722dbb84163e47bb545c310869647924dad89bcfe2bbe04cd64476b304eada914083e5c094", - "sha1": "ff9416b228333b481cdc98ec50c5f9944225d16b" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.16.5-0.6.6/lithium-fabric-mc1.16.5-0.6.6.jar", - "filename": "lithium-fabric-mc1.16.5-0.6.6.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.2", - "1.16.3", - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "Le0tKjFX", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.7.0", - "version_number": "mc1.17-0.7.0", - "changelog": "The changelog is available on GitHub right [here](https://github.com/CaffeineMC/lithium-fabric/releases/tag/mc1.17-0.7.0).", - "changelog_url": null, - "date_published": "2021-06-08T19:45:03.750911Z", - "downloads": 1057, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "533614aa733d74cf049d31a731f53873103987b2", - "sha512": "9c0c9a98896966b4728d9ccb1b7605b3229599197f9ffaf6c12cb15deb28e0cb99be85e46772d1d258820e2385f1aa73aa7cb862ec9383e7e242baefc6eb7921" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.17-0.7.0/lithium-fabric-mc1.17-0.7.0.jar", - "filename": "lithium-fabric-mc1.17-0.7.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "pGhOMdTm", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.6.5", - "version_number": "mc1.16.5-0.6.5", - "changelog": "The changelog is available on GitHub right [here](https://github.com/jellysquid3/lithium-fabric/releases/tag/mc1.16.5-0.6.5).", - "changelog_url": null, - "date_published": "2021-06-08T13:48:35.642184Z", - "downloads": 153, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "e15e2563db5d6c0de539e799c04e76e02d3b01378d80477952703e7d32ea65a845eea4b8503ece52f676ed1f2343e9f15bfcc2c0c43d22927a1ac95394876478", - "sha1": "a811c3b2ea4a07c4eb4c070ee1a0fcbd0f5791ff" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.16.5-0.6.5/lithium-fabric-mc1.16.5-0.6.5.jar", - "filename": "lithium-fabric-mc1.16.5-0.6.5.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.2", - "1.16.3", - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "igqdFUYG", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.6.4", - "version_number": "mc1.16.5-0.6.4", - "changelog": "The changelog is available on GitHub right [here](https://github.com/jellysquid3/lithium-fabric/releases/tag/mc1.16.5-0.6.4).", - "changelog_url": null, - "date_published": "2021-02-24T14:15:07.080780Z", - "downloads": 4429, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "a5d54bace83489e878e14ddb1792c97e75b0ecc61bfd43de53342646d4c4ba49543874d5d2f63558a6b52419024e83895b0715c7dec19248de89e9b80b2da092", - "sha1": "188f85adab94146bdfff931592e8405c213cb87a" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.16.5-0.6.4/lithium-fabric-mc1.16.5-0.6.4.jar", - "filename": "lithium-fabric-mc1.16.5-0.6.4.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.2", - "1.16.3", - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "ouTdXXWj", - "mod_id": "gvQqBUqZ", - "author_id": "uhPSqlnd", - "featured": false, - "name": "Lithium 0.6.3", - "version_number": "mc1.16.5-0.6.3", - "changelog": "The changelog is available on GitHub right [here](https://github.com/jellysquid3/lithium-fabric/releases/tag/mc1.16.5-0.6.3).", - "changelog_url": null, - "date_published": "2021-02-02T21:07:33.498154Z", - "downloads": 1178, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "5acd33822982835ca8c7d9abfea00a5088d3800d", - "sha512": "5eda84d07a36b7c2e5d723c35c4c94ec8a487a762ce818290eaa946b68c927492c49bf1cd02f52dd51ab523b55d7b072ffe9806b1ba0f81d4156c1a18a76af4f" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.16.5-0.6.3/lithium-fabric-mc1.16.5-0.6.3.jar", - "filename": "lithium-fabric-mc1.16.5-0.6.3.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.2", - "1.16.3", - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "5fmGl08Y", - "mod_id": "gvQqBUqZ", - "author_id": "TEZXhE2U", - "featured": false, - "name": "Lithium 0.6.1", - "version_number": "mc1.16.5-0.6.1", - "changelog": "The changelog is available on GitHub right [here](https://github.com/jellysquid3/lithium-fabric/releases/tag/mc1.16.5-0.6.1).", - "changelog_url": null, - "date_published": "2021-01-29T02:31:43.508656Z", - "downloads": 245, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "b9e8a58de7013fae72e676bb55593d476727b2c7", - "sha512": "07b00fa9ec12c3c455b3f5c2870ececae11904a6450e206474404b96126bd64753b56be47c4e4d752e364f40cfad3efd78ac4b2862000d91f5b1aa671770395e" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.16.5-v0.6.1/lithium-fabric-mc1.16.5-0.6.1.jar", - "filename": "lithium-fabric-mc1.16.5-0.6.1.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.2", - "1.16.3", - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "EhG1mQzx", - "mod_id": "gvQqBUqZ", - "author_id": "TEZXhE2U", - "featured": false, - "name": "Lithium 0.6.0", - "version_number": "mc1.16.4-0.6.0", - "changelog": "", - "changelog_url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.16.4-0.6.0/changelog.md", - "date_published": "2021-01-03T00:56:52.295118Z", - "downloads": 520, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "6ab1c5adc97ab0c66f9c9afcdb1d143a607db82c" - }, - "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.16.4-0.6.0/lithium-fabric-mc1.16.4-0.6.0.jar", - "filename": "lithium-fabric-mc1.16.4-0.6.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4" - ], - "loaders": [ - "fabric" - ] - } -] \ No newline at end of file diff --git a/src/test/resources/version/modmanager.json b/src/test/resources/version/modmanager.json deleted file mode 100644 index bdedf73..0000000 --- a/src/test/resources/version/modmanager.json +++ /dev/null @@ -1,110 +0,0 @@ -[ - { - "id": "CdhVgHal", - "mod_id": "6kq7BzRK", - "author_id": "VUdG1FR5", - "featured": false, - "name": "1.0.2+1.17-alpha", - "version_number": "1.0.2+1.17-alpha", - "changelog": "Bugs fixed:\n\n- Fix CPU overload when using ModManager [#48](https://github.com/DeathsGun/ModManager/issues/48)\n- Fix forge artifacts being downloaded [#37](https://github.com/DeathsGun/ModManager/pull/37)\n- Fix NullPointerException while updating a mod [#34](https://github.com/DeathsGun/ModManager/issues/34)\n\nImprovements:\n\n- New loading icon [#40](https://github.com/DeathsGun/ModManager/pull/40)\n- Improved Turkish translation (Special thanks to kuzeeeyk) [#39](https://github.com/DeathsGun/ModManager/pull/39)\n- Added Chinese translation (Special thanks to MineCommanderCN) [#36](https://github.com/DeathsGun/ModManager/pull/36)\n- Added Korean translation (Special thanks to arlytical#1) [#32](https://github.com/DeathsGun/ModManager/pull/32)\n- Added Russian translation (Special thanks to Felix14-v2) [#31](https://github.com/DeathsGun/ModManager/pull/31)\n\n", - "changelog_url": null, - "date_published": "2021-09-03T10:56:59.402790Z", - "downloads": 474, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha512": "24661776bab56c8e77abaac3c66219e01742de2a0e9433945bfd1a6d284b1dd41e891f1d9c62f30c8f34688525e2c784e84e8720bde9355b2d7efa5e4fb53d2d", - "sha1": "c1b802582903dadf56c1965bc5c6a31716250848" - }, - "url": "https://cdn.modrinth.com//data/6kq7BzRK/versions/1.0.2+1.17-alpha/modmanager-1.0.2+1.17-alpha.jar", - "filename": "modmanager-1.0.2+1.17-alpha.jar", - "primary": true - } - ], - "dependencies": [ - { - "version_id": "E4QBMVtO", - "dependency_type": "required" - } - ], - "game_versions": [ - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "gGSLHqJK", - "mod_id": "6kq7BzRK", - "author_id": "VUdG1FR5", - "featured": false, - "name": "1.0.1+1.17-alpha", - "version_number": "1.0.1+1.17-alpha", - "changelog": "Bugs fixed:\n\n- Fixed crash when opening ModMenu [#13](https://github.com/DeathsGun/ModManager/issues/13)\n- Fixed update error on Windows because of file locks [#17](https://github.com/DeathsGun/ModManager/issues/13)\n- Search only when enter key was hit for improved performance [#7](https://github.com/DeathsGun/ModManager/issues/7)\n- Fixed crash when ModManager loses connection while opening a more detailed\n view [#16](https://github.com/DeathsGun/ModManager/issues/16)\n- Fixed icons being mixed up [#22](https://github.com/DeathsGun/ModManager/issues/22)\n- Fixed unknown mods showing up [#18](https://github.com/DeathsGun/ModManager/issues/18)\n\nImprovements:\n\n- Added Turkish translation (Special thanks to kuzeeeyk) [#21](https://github.com/DeathsGun/ModManager/pull/21)\n- Only show \"Updatable mods\" category when there are updatable\n mods [#10](https://github.com/DeathsGun/ModManager/issues/10)\n", - "changelog_url": null, - "date_published": "2021-08-24T17:26:03.297706Z", - "downloads": 225, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha1": "0228ab2ac3cc3120512041d01b31925f03e764e5", - "sha512": "7ec3293ac8f43adf12e02e60f3ce1c1a6410fb21674bf8ab50184d4e32cf34535b428f642b429515c7119328d49d0c852817cb00f7c109cc1135963313c9d474" - }, - "url": "https://cdn.modrinth.com/data/6kq7BzRK/versions/1.0.1+1.17-alpha/modmanager-1.0.1+1.17-alpha.jar", - "filename": "modmanager-1.0.1+1.17-alpha.jar", - "primary": true - } - ], - "dependencies": [ - { - "version_id": "E4QBMVtO", - "dependency_type": "required" - } - ], - "game_versions": [ - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "2J1ys6qf", - "mod_id": "6kq7BzRK", - "author_id": "VUdG1FR5", - "featured": false, - "name": "1.0.0-alpha", - "version_number": "1.0.0-alpha", - "changelog": "This project has reached the alpha stage.\nI think the mod has reached a point in which it can be called an alpha.\n\nWhat can do now?\n* Browse through Modrinth\n* Install, remove and update mods\n* Notify about updates\n* Show you an overview of mods that need an update ", - "changelog_url": null, - "date_published": "2021-08-23T17:00:19.010541Z", - "downloads": 55, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha512": "e57fddfc3d2d7789f6b260e345ba5a469b0de343692535d742762336afaf10d0f753aa537384d48b7aa16a5c6a4d71adff36b22f26f6248862f19f94dfbcd5ce", - "sha1": "a646cc8a6ef18ad2bf8a771776780e87d35e79a1" - }, - "url": "https://cdn.modrinth.com/data/6kq7BzRK/versions/1.0.0-alpha/modmanager-1.0.0-alpha.jar", - "filename": "modmanager-1.0.0-alpha.jar", - "primary": true - } - ], - "dependencies": [ - { - "version_id": "E4QBMVtO", - "dependency_type": "required" - } - ], - "game_versions": [ - "1.17.1" - ], - "loaders": [ - "fabric" - ] - } -] \ No newline at end of file diff --git a/src/test/resources/version/modmenu.json b/src/test/resources/version/modmenu.json deleted file mode 100644 index 6604358..0000000 --- a/src/test/resources/version/modmenu.json +++ /dev/null @@ -1,1412 +0,0 @@ -[ - { - "id": "PN4NcBa1", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.21 for 1.16.5", - "version_number": "1.16.21", - "changelog": "- Fixed immediate crash when using Java 1.8", - "changelog_url": null, - "date_published": "2021-09-27T01:53:22.474594Z", - "downloads": 39, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "cfdd10585e96d53321d4d84d44d7505b4130527747da05f4c407cb3b072ff2a25ec819df12d7840810bc9ca6d2497a7bc847525a3f15dad08204caa2c68c9844", - "sha1": "96c9741127516103b273fac5fac7e5b179f64270" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.21/modmenu-1.16.21.jar", - "filename": "modmenu-1.16.21.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "jZQ0G78K", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.1.1 for 21w38a", - "version_number": "2.1.1", - "changelog": "- Removed deprecated Mod Menu API, mods must use `com.terraformersmc.modmenu.api.ModMenuApi` now\n- Removed deprecated custom value loading, mods must use the `modmenu` container custom value now", - "changelog_url": null, - "date_published": "2021-09-26T01:50:56.813057Z", - "downloads": 23, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "0053e0a958e2d26b00739b830c015708a12be298", - "sha512": "c665b46f6b9f703a95fbf4f3b7c385851e212ba9f69b3335d98e8e3594b6b14d2b631db6092b8ef5fb5601a86cbb06c99f70961b068bc0204e014a7c848aa150" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.1.1/modmenu-2.1.1.jar", - "filename": "modmenu-2.1.1.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "21w37a", - "21w38a" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "WKj0jgYj", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.13 for 1.17", - "version_number": "2.0.13", - "changelog": "- Updated English (en_PT) translation\n- Updated Mongo (lol_US) translation", - "changelog_url": null, - "date_published": "2021-09-26T01:50:10.779807Z", - "downloads": 277, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "f8cab8735f0ad6c63da5154594397861daae0964", - "sha512": "3bc8647db8f82f141d7f9309ac3f27014f1c915445d3ee68f805f7b659b988c92bc5e68b9dc16a68b370723ac6575e5c8439b1f2f607289f4f303998a293cb10" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.13/modmenu-2.0.13.jar", - "filename": "modmenu-2.0.13.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "JOqf8AZn", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.20 for 1.16.5", - "version_number": "1.16.20", - "changelog": "- Updated English (en_PT) translation\n- Updated Mongo (lol_US) translation", - "changelog_url": null, - "date_published": "2021-09-26T01:49:48.667423Z", - "downloads": 14, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "fae574348ba6a371e7e35e7010fb952b91a85ffa", - "sha512": "2fd7fb090d5430a3c92636933b3dfc8c3fe1cc916109db7f71aed1000ba36f5e713947deefd4232e5dec7038b989b049573ccf004f18647aa96b7cb7d4fe8805" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.20/modmenu-1.16.20.jar", - "filename": "modmenu-1.16.20.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "LVxVja5i", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.1.0 for 21w37a", - "version_number": "2.1.0", - "changelog": "No Changelog Available", - "changelog_url": null, - "date_published": "2021-09-21T14:48:05.867840Z", - "downloads": 50, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "7dfaa4b25877a1892ac30e3609b6d0633c03166310140ad1e4d2c1fe4fb420e4d74591afac7cf0d1a558fbf258f49be7a864a96820ba1da58439fc2b50a7309f", - "sha1": "bfee5982424e18bc68f6927b5658ba6557b155de" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/2.1.0/modmenu-2.1.0.jar", - "filename": "modmenu-2.1.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "21w37a", - "21w38a" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "9xECQHnM", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.12 for 1.17", - "version_number": "2.0.12", - "changelog": "- Fixed Minecraft crash caused by broken mod config screens\n- Updated German translation", - "changelog_url": null, - "date_published": "2021-09-21T02:22:22.768837Z", - "downloads": 414, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "5d7f921acd3712b7db606e273fbfe73bee532b63858be844e7d3659b71cc533d8580d2c28dc264df8ac1382452873ec3d1b11e3411377c1aa5bccc1c9fab332c", - "sha1": "01e02fd25f30a1078ca2fccd9064839a5dd181e8" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/2.0.12/modmenu-2.0.12.jar", - "filename": "modmenu-2.0.12.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "aH8qgnVM", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.19 for 1.16.5", - "version_number": "1.16.19", - "changelog": "- Fixed Minecraft crash caused by broken mod config screens\n- Updated German translation", - "changelog_url": null, - "date_published": "2021-09-21T02:20:59.248250Z", - "downloads": 68, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "7be89f7fcaefd034244820fcbd7266805de10724", - "sha512": "9d39c100c031d86492fab9cdd658278658134cb9a596c342be242f22cca9256cd985dd50eb17e34d801b8496d4b29ec8e1b45ae24253a94403469ee8d6acd833" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/1.16.19/modmenu-1.16.19.jar", - "filename": "modmenu-1.16.19.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "FMqdptUn", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.11 for 1.17", - "version_number": "2.0.11", - "changelog": "- Updated Russian translation\n- Updated Russian translation\n- Updated Bulgarian translation\n- Updated English (en_PT) translation\n- Updated English (en_UD) translation\n- Updated English (en_WS) translation\n- Updated Italian translation", - "changelog_url": null, - "date_published": "2021-09-17T16:10:25.681935Z", - "downloads": 379, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "f7ff368917b4c4d6b5655de2a46584cba09e95c80cd6c70f1cd61589f999e2872be26ff3820b038dbf1b27fa79c09928b27fa492ff3d416daf536745121e2a6d", - "sha1": "93f5281f5f446cb43724c2c2bb0fe75e5b47c069" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/2.0.11/modmenu-2.0.11.jar", - "filename": "modmenu-2.0.11.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "VaZTuVan", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.18 for 1.16.5", - "version_number": "1.16.18", - "changelog": "- Updated Russian translation\n- Updated Bulgarian translation\n- Updated English (en_PT) translation\n- Updated English (en_UD) translation\n- Updated English (en_WS) translation\n- Updated Italian translation\n- Updated Russian translation", - "changelog_url": null, - "date_published": "2021-09-17T16:02:07.470359Z", - "downloads": 51, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "c68bde6d376e3387c8afcc2d4c26b43ca761dba9", - "sha512": "27c1b62d44db781021f1b4a3e326a0eee302ec6fe8bc24680e86bf3cd6e43a6dc80b24187485cec9f8d79d7841f8e082b2d5e69d0228c00cd0036d772a37b4a2" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/1.16.18/modmenu-1.16.18.jar", - "filename": "modmenu-1.16.18.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "XtL1i60M", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.10 for 1.17", - "version_number": "2.0.10", - "changelog": "- Fixed Java icon loosing background color when selected", - "changelog_url": null, - "date_published": "2021-09-06T11:46:18.682245Z", - "downloads": 922, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "66b4fc25284a8078060a259313f3814ff289374d", - "sha512": "9c65fbafe8eabc1949d050f76cb0cf05b9a1fcdb98e4f738609ce19434c7960c1fcb1d2a5390b8f7df74c06346963b19fef9683b0f2b1fcb0e508cd7dd204a5f" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/2.0.10/modmenu-2.0.10.jar", - "filename": "modmenu-2.0.10.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "DOitjZ89", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.17 for 1.16.5", - "version_number": "1.16.17", - "changelog": "- Updated Portuguese (Brazil) translation", - "changelog_url": null, - "date_published": "2021-09-06T11:45:40.107879Z", - "downloads": 117, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "848365e77db8871bdfafe3e20fc879aa1cab75c3e75f429c2196dad83aee67e7e2c55242cf1c13470dbaf8256163a73f65c2a92d08b151f630ad5d4679147d55", - "sha1": "0106a8f8fd5d49dc9358880da35605746f71cdde" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/1.16.17/modmenu-1.16.17.jar", - "filename": "modmenu-1.16.17.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "tlM0eBmY", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.9 for 1.17", - "version_number": "2.0.9", - "changelog": "- Fixed a crash when optional dependencies were used in mod config screens", - "changelog_url": null, - "date_published": "2021-09-02T07:41:19.101417Z", - "downloads": 470, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "db2c640258ec56e9403a1089a27e6982b27fdb93", - "sha512": "775905aaac1f7737e1747188792359cab577d4fb0fb30095430eb96e3c453403f18fc18e8f2e172a0fc2eb67b2149adf346b95e91953afe11fafbabd320ca740" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/2.0.9/modmenu-2.0.9.jar", - "filename": "modmenu-2.0.9.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "Wr4GfZdy", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.16 for 1.16.5", - "version_number": "1.16.16", - "changelog": "- Fixed a crash when optional dependencies were used in mod config screens", - "changelog_url": null, - "date_published": "2021-09-02T07:39:28.064909Z", - "downloads": 67, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "d0c8a302fc432d882dc4cedc918bdc85fc64ad84", - "sha512": "326f920e83dc02368ff2126c11fcf86329d1ab129469625fdabc8dbab191553298e832e50a668707c95ab7a7c1a9129d50c83326defeae6cdb424733444ce130" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/1.16.16/modmenu-1.16.16.jar", - "filename": "modmenu-1.16.16.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "GOPQZTVp", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.15 for 1.16.5", - "version_number": "1.16.15", - "changelog": "- Updated Portuguese (Brazil) translation", - "changelog_url": null, - "date_published": "2021-09-01T18:08:13.789812Z", - "downloads": 11, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "c778d3d32523fcebea70614f14bc0950afec6a06", - "sha512": "7a9d99de0ce679111c243c983a2d4e7c38fa1ed12f563534163abea83936b60e3d5f4b3de2c9bc9e78e7916bcddbffa3f69e1b0877c81ee2083f28cbab7f346a" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/1.16.15/modmenu-1.16.15.jar", - "filename": "modmenu-1.16.15.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "JyL5b75a", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.8 for 1.17", - "version_number": "2.0.8", - "changelog": "- Updated Portuguese (Brazil) translation\n- Updated Swedish translation", - "changelog_url": null, - "date_published": "2021-09-01T18:07:59.639490Z", - "downloads": 62, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "205d5aac4f64a5e1a70534ef7c08806596ede109", - "sha512": "05f5ef82bf43e5087a6a481a027588fdda281d7c0168d340e672f689797a9316d4d805f60e999f1ef2e40048b5cdd1e4b1d48ce81d87d5a21bb94a94d5befc46" - }, - "url": "https://cdn.modrinth.com//data/mOgUt4GM/versions/2.0.8/modmenu-2.0.8.jar", - "filename": "modmenu-2.0.8.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "G8sCBZ1X", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.7 for 1.17", - "version_number": "2.0.7", - "changelog": "- Updated ɥsᴉꞁᵷuƎ translation\n- Updated LOLCAT translation\n- Updated Portuguese (Brazil) translation\n- Updated Swedish translation", - "changelog_url": null, - "date_published": "2021-08-30T23:41:16.288205Z", - "downloads": 195, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "5425b82d434a69de9e0ca539d92c7ed7bfef7146", - "sha512": "bb065e91fdde821b1bd7d8190ba7cd5ad35f22438ac6f3ba213a54f7e1ccf2b11599ae457d839eadec37da72ce0fd8c43194f4401936b4839dd7a65293c3dc40" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.7/modmenu-2.0.7.jar", - "filename": "modmenu-2.0.7.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "4Ar2wg0k", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.14 for 1.16.5", - "version_number": "1.16.14", - "changelog": "- Updated ɥsᴉꞁᵷuƎ translation\n- Updated LOLCAT translation\n- Updated Portuguese (Brazil) translation\n- Updated Swedish translation", - "changelog_url": null, - "date_published": "2021-08-30T23:40:57.517439Z", - "downloads": 25, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "e0c23845500c81dfd6ffce29fb0c0bd199413b0b16c0e96b167076e8d26b7d77cd049d94243bbefa416319d590acc5f7cd441553e7dd4e0c350d6db7441adc63", - "sha1": "c909bd99670715573163f47e5b62025cd8ed8ca4" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.14/modmenu-1.16.14.jar", - "filename": "modmenu-1.16.14.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "bojzkt4w", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.6 for 1.17", - "version_number": "2.0.6", - "changelog": "- Added mod list hotkeys: SPACE to open/close a list of child mods, LEFT to select the parent or close the list, RIGHT to open the list or select the first child", - "changelog_url": null, - "date_published": "2021-08-27T21:00:07.614860Z", - "downloads": 404, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "254cb07f4e14f0f3a60c000a92ec1bd578c61172", - "sha512": "bc473a6307bde7bd9dbcc3c5717a11cedfb6105b8f0134e823529af75cb2b1bf72713494b0bd7f3861ef4462ed1a38bae82462db6d22753ff28763a0cfb7350c" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.6/modmenu-2.0.6.jar", - "filename": "modmenu-2.0.6.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "c6uDXZX8", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.13 for 1.16.5", - "version_number": "1.16.13", - "changelog": "- Added mod list hotkeys: SPACE to open/close a list of child mods, LEFT to select the parent or close the list, RIGHT to open the list or select the first child", - "changelog_url": null, - "date_published": "2021-08-27T20:59:37.008093Z", - "downloads": 61, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "ab20c871f3b0ba25a89c636ee10ffcaaf8a8271c", - "sha512": "443ae53b897e6fb77e66570b215d54125ca6c3bb6a95270748456a26434fb3821adc8bd610175e74a590dac6597466ea1ab823998c4ed8015c73c75b0af88349" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.13/modmenu-1.16.13.jar", - "filename": "modmenu-1.16.13.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "E4QBMVtO", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.5 for 1.17", - "version_number": "2.0.5", - "changelog": "- Fixed a crash when mods declare themselves as their own parent\n- Updated Italian translation\n- Added Classical Chinese Language translation\n- Updated German translation\n- Updated French translation\n- Updated Turkish translation\n- Updated Persian translation", - "changelog_url": null, - "date_published": "2021-08-19T12:01:27.204434Z", - "downloads": 871, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "6a74b40142425a6ba3fa75272e7e9bf2604c132a", - "sha512": "136eee2b29b4209680a98a32c301e78ba5f10e539d576c006721a25eae1143d1f95420e4a29af18172a4463e17936ab37638ba2bc35e0081e0b374e24dcd1b08" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.5/modmenu-2.0.5.jar", - "filename": "modmenu-2.0.5.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "u955lyFM", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.12 for 1.16.5", - "version_number": "1.16.12", - "changelog": "- Fixed a crash when mods declare themselves as their own parent\n- Updated German translation\n- Updated French translation\n- Updated Turkish translation\n- Updated Persian translation", - "changelog_url": null, - "date_published": "2021-08-19T12:01:14.906512Z", - "downloads": 124, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "98c6fb528c6f64c0148a62a11ba971efdf4b2f3e", - "sha512": "53a998ab9e803d5b06cb0b7b8b387af67933fb647ecd2910d242b54479393ef05c450f7376977e96d86f6bb75c205667630b250d43b21a4f368337de0946fccd" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.12/modmenu-1.16.12.jar", - "filename": "modmenu-1.16.12.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "oQr5VO7q", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.4 for 1.17", - "version_number": "2.0.4", - "changelog": "- Fixed sounds resuming when exiting Mod Menu with ESC while paused\n- Update Polish Translation", - "changelog_url": null, - "date_published": "2021-07-25T07:44:38.772570Z", - "downloads": 2247, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "fa26fc594dea1370adc376667bf64c8f45b0d8d6", - "sha512": "65ea03ce8e5863840007e37128bd6e15c0c632b67eae10ef5fb722e355ae82e512b52b8d15fb254a4509b5879d0b431fa74f99f1d0773c4bbff58df98b6dea3d" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.4/modmenu-2.0.4.jar", - "filename": "modmenu-2.0.4.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "NyFB1gry", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.11 for 1.16.5", - "version_number": "1.16.11", - "changelog": "- Fixed sounds resuming when exiting Mod Menu with ESC while paused\n- Update Polish Translation", - "changelog_url": null, - "date_published": "2021-07-25T07:44:17.812465Z", - "downloads": 410, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "215bd4c1126e82e247c05f83d9cef70439424bcdcf2b23dcd5e9d12b4c8a2c1a6c124d820dbb3831c64b1d66958f2fd8f31c6111a23ba8815259e8b0649eb11d", - "sha1": "bafd3da269de96601f47cf96fa028255ee4aafaa" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.11/modmenu-1.16.11.jar", - "filename": "modmenu-1.16.11.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "a8bewBQT", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.3 for 1.17", - "version_number": "2.0.3", - "changelog": "No Changelog Available", - "changelog_url": null, - "date_published": "2021-07-20T00:38:02.587253Z", - "downloads": 638, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "4af7c6bb26ee80bd816ebe9068b16902cafb946d", - "sha512": "27984e37c91a90232c77af795d6a58a36b7b3c276aab9d03f456deb49b38c982f88ced3dd6ec2e70a6852c0d247f833ba36e75c8d9ed59fff4d54d1c15c90ede" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.3/modmenu-2.0.3.jar", - "filename": "modmenu-2.0.3.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "bHODZExo", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.10 for 1.16.5", - "version_number": "1.16.10", - "changelog": "- Added Korean Translation", - "changelog_url": null, - "date_published": "2021-07-20T00:33:33.033376Z", - "downloads": 93, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "07861d3eea9bbee3cece379b3f9169329078ffd0533aecb9f6a1bf3d026cecc55f1dd2bba7def13724c186fbbb228a2d4bb33a5b60b663dccea216dd53b455d0", - "sha1": "49ae9c7668df07fc576fcd74299c81ffa417ec76" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.10/modmenu-1.16.10.jar", - "filename": "modmenu-1.16.10.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "mzVbb1XI", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.2 for 1.17", - "version_number": "2.0.2", - "changelog": "- Update Persian Translation\n- Allow for more \"dynamic\" provider factories through the API\n- Added Korean Translation\n- Fixed some rendering issues from the 21w14a port\n- Update Russian Translation\n- Updated Catalan translation\n- Handle errors in API implementations more gracefully\n- Updated Simplified Chinese Translation\n- Updated to 21w14a\n- Re-ported Mod Menu v1.16.7 to Minecraft Snapshot 20w06a (from Minecraft 1.16.5)", - "changelog_url": null, - "date_published": "2021-06-12T03:29:55.681242Z", - "downloads": 2122, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "2d66d55e114ee19877ffd3ad6ac901a3290b6b4f0e9000c7a3a8f0a5f401ea3a29bccafea7ea06a7d604057d6be9319f24752e456796624b2e36d0bcce062504", - "sha1": "e6ebbc3115c74dd601129099acc792e214783966" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.2/modmenu-2.0.2.jar", - "filename": "modmenu-2.0.2.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17", - "1.17.1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "wRE7Emzz", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.0-beta.7 for 1.17-pre1", - "version_number": "2.0.0-beta.7", - "changelog": "- Update Persian Translation\n- Allow for more \"dynamic\" provider factories through the API\n- Added Korean Translation\n- Fixed some rendering issues from the 21w14a port\n- Update Russian Translation\n- Updated Catalan translation\n- Handle errors in API implementations more gracefully\n- Updated Simplified Chinese Translation\n- Updated to 21w14a\n- Re-ported Mod Menu v1.16.7 to Minecraft Snapshot 20w06a (from Minecraft 1.16.5)", - "changelog_url": null, - "date_published": "2021-05-31T18:14:39.483247Z", - "downloads": 191, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "d08ccef96f514813b577d1d1d246af546619cc8d8a21f058d5f920bb52477f98f2228ff80f1332891a96e7228812cc85dcca5217af0adacc8a8839780028eff1", - "sha1": "a3b26ff7bb57b226dcf500f6dbe42162d658e850" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.0-beta.7/modmenu-2.0.0-beta.7.jar", - "filename": "modmenu-2.0.0-beta.7.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17-pre1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "EDbIonje", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.0-beta.5 for 1.17-pre1", - "version_number": "2.0.0-beta.5", - "changelog": "No Changelog Available", - "changelog_url": null, - "date_published": "2021-05-29T07:04:58.631931Z", - "downloads": 35, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "92c2c785c0b06cff93203e2280abc794d62c959c", - "sha512": "917b08fdca974897ee46ffda2dea111211119f040137b7ba2314cce7e12a243ea182c547b89980efb6744b79898582f0d06824f53307c6c477f057b0415d532f" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.0-beta.5/modmenu-2.0.0-beta.5.jar", - "filename": "modmenu-2.0.0-beta.5.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17-pre1" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "Gz5wa6j2", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.10.6 for 1.15.2", - "version_number": "1.10.6", - "changelog": "- Fix crash with default API getId implementation resulting in NPE", - "changelog_url": null, - "date_published": "2021-04-10T19:39:37.333394Z", - "downloads": 202, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "197062aefc991c5151ac143343bd2082535ca2f6", - "sha512": "58628244c8e2a22dc89eb091db3d5a12852130e97f97d979e55d1a3f083ad5db89806dfd50bf8b4fbfa9c67c74f09205d33439b80a8a179701151de8b9bd7a5b" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.10.6/modmenu-1.10.6.jar", - "filename": "modmenu-1.10.6.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.15.2" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "RIf7gcLA", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.0-beta.4 for 21w14a", - "version_number": "2.0.0-beta.4", - "changelog": "- Update Persian Translation\n- Allow for more \"dynamic\" provider factories through the API\n- Added Korean Translation\n- Fixed some rendering issues from the 21w14a port", - "changelog_url": null, - "date_published": "2021-04-10T08:18:47.063082Z", - "downloads": 49, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "544b546c1b2568dd0b093e50d5f62831b9e5064d", - "sha512": "914f3b947feebb48f71c49af6599d8dd111b8e9e86323b9611e4a6377e7addd807e22b5990a2fc9294df3f95629ae2db01bb907b5b3826d4c35bde4229b93c1a" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.0-beta.4/modmenu-2.0.0-beta.4.jar", - "filename": "modmenu-2.0.0-beta.4.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "21w14a" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "pqlMITZQ", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.0-beta.3 for 21w14a", - "version_number": "2.0.0-beta.3", - "changelog": "- Update Russian Translation\n- Updated Catalan translation\n- Handle errors in API implementations more gracefully\n- Updated Simplified Chinese Translation\n- Updated to 21w14a", - "changelog_url": null, - "date_published": "2021-04-08T02:20:56.992170Z", - "downloads": 10, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "c90741f8ddfe2d1f5e563aa017ee0814544278272bd60414c8d9cbe8a67066147be7eb44bfcf08a8ddec9e29051fcc7521ea5e903405f88726016ac67f696065", - "sha1": "483ebf02440cbca5926433f6caecd175f64f04d7" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.0-beta.3/modmenu-2.0.0-beta.3.jar", - "filename": "modmenu-2.0.0-beta.3.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "21w14a" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "bPE0GIoY", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.9 for 1.16.5", - "version_number": "1.16.9", - "changelog": "- Allow for more \"dynamic\" provider factories through the API\n- Updated Persian Translation\n- Updated Catalan translation\n- Updated Russian Translation", - "changelog_url": null, - "date_published": "2021-04-08T01:59:50.513004Z", - "downloads": 1868, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "513e4e6355ac5ba2192222482eb0bd8d2d8edeb7", - "sha512": "fe5d944e2925a608babf73890e6423ee655872048ed122f0336c4c697024440e19146d04dda4c448a317273fb70578a393cf04e7cb6a33e85bc7ec7807b1fd15" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.9/modmenu-1.16.9.jar", - "filename": "modmenu-1.16.9.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "wb5nbuL5", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.8 for 1.16.5", - "version_number": "1.16.8", - "changelog": "- Handle errors in API implementations more gracefully\n- Updated Simplified Chinese Translation", - "changelog_url": null, - "date_published": "2021-02-20T23:28:08.977665Z", - "downloads": 916, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "9d5fbe5ce7b1a7a26f4a4c12321809b9a0c6e9099a3f74ff7ad4f49c96f13885c4695938c516b39f529b51823f0ea5038f67ddbf4ed3ec69432f09c20f7d875b", - "sha1": "d59e0064d42213462379f63d3aa0e72151439aac" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.8/modmenu-1.16.8.jar", - "filename": "modmenu-1.16.8.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "6YvLIUDN", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v2.0.0-beta.2 for 21w06a", - "version_number": "2.0.0-beta.2", - "changelog": "- Re-ported Mod Menu v1.16.7 to Minecraft Snapshot 21w06a (from Minecraft 1.16.5)", - "changelog_url": null, - "date_published": "2021-02-11T02:59:39.111229Z", - "downloads": 69, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "595beb5853cb1ac7cb0ea4ae83d120dafdd0adfc", - "sha512": "37851b3fa8e460e79dce63dd0a65d7a8f6fedeaff0d9985e46cc733309b16ceddeb81817951f3c0ab038b50fe441a370f882b3520f1971282024810356a3b898" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/2.0.0-beta.2/modmenu-2.0.0-beta.2.jar", - "filename": "modmenu-2.0.0-beta.2.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "21w06a" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "pxj9L3Vy", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.10.5 for 1.15.2", - "version_number": "1.10.5", - "changelog": "- Added a default implementation to getModId to allow for backwards compatible mods", - "changelog_url": null, - "date_published": "2021-02-11T01:34:19.762546Z", - "downloads": 18, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "62df0e2478d6248b1117ef0ef97d24dc3e48e99b31dfe019e4af93001da213f455bff64320451550d13037083862ae488bce7245f7d7c30132a2c4585740a052", - "sha1": "3f059cb8b9c237ae1393730c29a2706284404dd4" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.10.5/modmenu-1.10.5.jar", - "filename": "modmenu-1.10.5.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.15.2" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "Mnl0OeFI", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.7 for 1.16.5", - "version_number": "1.16.7", - "changelog": "- Include fabric-api-base\n- Added translations for Wiki and Crowdin link keys", - "changelog_url": null, - "date_published": "2021-02-11T00:59:39.572339Z", - "downloads": 229, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "63da238680e21e125ce85ebebc82c06677e8548f", - "sha512": "c20c276036ed10f6c49b8c1d0a43839d8f6ce372155ce9b45e255d8bac24f540b39d22b9b7f11f2d2429eaa430d79474a73f4b472e63c7d9248592d4a0b6795e" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.7/modmenu-1.16.7.jar", - "filename": "modmenu-1.16.7.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "PqgXyy3N", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.6 for 1.16.5", - "version_number": "1.16.6", - "changelog": "- Mark Better Mod Button as incompatible\n- Handle errors from other mods' config factories more gracefully, will now just log and remove the mod's config button.", - "changelog_url": null, - "date_published": "2021-02-05T22:22:58.469004Z", - "downloads": 131, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "8da9d6db8ff527c926dad773d1f115fa7f770ad1d44bca128fe844f2d3302e491cf1e7bdedda82c350420e5ab3ca3b3c143c9fafa07c5085fde3b7e5dd05e358", - "sha1": "cd1b7d594e17cdfcb9313fd1af7f9a1f3d216701" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.6/modmenu-1.16.6.jar", - "filename": "modmenu-1.16.6.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "TleLdS1A", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.5 for 1.16.5", - "version_number": "1.16.5", - "changelog": "- Added additional link key translations for common links", - "changelog_url": null, - "date_published": "2021-02-03T17:37:00.869777Z", - "downloads": 97, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "412db6dd04056379c6df0997bf3570a01816dd2d", - "sha512": "19efda14091e729e994344c88bda708b9dc4db1fa7a58deaf6a276ea8877f68048e6fb8a2155be4e32760822d5b78102e0c3e6bf216216f3bb613adae6fbe16f" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.5/modmenu-1.16.5.jar", - "filename": "modmenu-1.16.5.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "kBofQyu4", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.4 for 1.16.5", - "version_number": "1.16.4", - "changelog": "- Moved the licensing information above credits\n- Changed the order of the config buttons\n- Updated Finnish translation", - "changelog_url": null, - "date_published": "2021-02-03T00:30:43.903288Z", - "downloads": 35, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "c62b8b2e1f39c611219639f791592a4b964db770", - "sha512": "c250843a0e64cdfb3be7b60781cdb9935d75549f7a8200dcfaa6dc95734b731c9506892d9356462fb06f20f16da81b556065378910924f98dc59eea6de1035c5" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.4/modmenu-1.16.4.jar", - "filename": "modmenu-1.16.4.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "79rtoAM6", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.3 for 1.16.5", - "version_number": "1.16.3", - "changelog": "- Fixed incorrect error being logged when a mod defines an invalid icon\n- Fixed an error being logged when no icon is at the default path", - "changelog_url": null, - "date_published": "2021-02-02T06:00:47.911634Z", - "downloads": 24, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "8f330a0437ce6840b5c1292338944a313c420cee009b7308b128f4f9f2cec9bd42c5f3484a7f1f07c8ba8fd649784e6353146733ed019d0f247b7c4b13f80bbc", - "sha1": "a069de2a17a6a4a9d2712c5045ade3b8ac0c2711" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.3/modmenu-1.16.3.jar", - "filename": "modmenu-1.16.3.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "7QWIhei3", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.2 for 1.16.5", - "version_number": "1.16.2", - "changelog": "- Fixed icons for mods that were using the default icon path\n- Added the old button textures to the Programmer Art resource pack\n- Update Catalan translation\n- Updated Turkish translation", - "changelog_url": null, - "date_published": "2021-02-02T02:55:07.428315Z", - "downloads": 15, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "88dd61ffdcf974ca8fd8f5234507f383497979f91f5e4349e729fca4deb7fef3c5c558d37b40ff0af7404b4ae66c418ebcf17d7d86470ba8bb1be000aa477c58", - "sha1": "214413d0f21514355e49e399be268b8f00536570" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.2/modmenu-1.16.2.jar", - "filename": "modmenu-1.16.2.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "zC13OZD9", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.1 for 1.16.5", - "version_number": "1.16.1", - "changelog": "- Updated Estonian translation\n- Fixed a bug with the mod count\n- Added mod id tooltip for fake mods", - "changelog_url": null, - "date_published": "2021-02-01T16:43:37.225565Z", - "downloads": 18, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "f6135e7d451e7b530931f401e2281d6515f35324", - "sha512": "101e5b0b6f53cd3d48ddc4df6f560fde2a0e1024a3e1441cae36feda8566508d58d40d74e672d41f216536296add5689042521336b654eccb4c61ac3894532a7" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.1/modmenu-1.16.1.jar", - "filename": "modmenu-1.16.1.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "O90fUm3q", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.16.0 for 1.16.5", - "version_number": "1.16.0", - "changelog": "- Fixed two of the Mods button style names being wrong\n- Added an API for getting the Mods button text", - "changelog_url": null, - "date_published": "2021-02-01T07:43:32.314913Z", - "downloads": 24, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "ff8d7b2889aa69af06d73bfc2b679db80cb78190", - "sha512": "99a3f39e463e53da878a34e37a6084caa5cfefd1df9f973989815195af26548bceeb351a30585e27e77413e27e7ede95bd653549b633663004b5904658fb3f38" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.16.0/modmenu-1.16.0.jar", - "filename": "modmenu-1.16.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "DgzrfgAZ", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.15.0 for 1.16.5", - "version_number": "1.15.0", - "changelog": "- Major internal refactors\n- Added links, contributors, and license information\n- Added an options screen for Mod Menu\n- Added a compact list mode option\n- Added an options to change Mods button style to: Below Realms (Default), Shrink Realms, Replace Realms, and Fabric Icon\n- Added an option to hide mod badges\n- Added an option to move where the mod count is displayed (on button, on title screen, both, neither)\n- Added options to specify whether or not to count libraries, children, and hidden mods in the mod count\n- Added options to hide mod links, credits, or license info\n- Added options to disable the modification of the title screen and/or game menu screen\n- Changed the hardcoded icon for \"java\n- Probably more that got forgotten about in this massive update", - "changelog_url": null, - "date_published": "2021-02-01T06:38:14.029901Z", - "downloads": 87, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "9c09902f887f3f742082835b8dd05a7f648786c5", - "sha512": "0a89c3513294091c639f9ed4c64252f9b469d252993e86163222687db2455d331984341c954eca84037ba06f38227de37406912fd77f342feb23bdc96048c6f6" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.15.0/modmenu-1.15.0.jar", - "filename": "modmenu-1.15.0.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "M3KFXLhq", - "mod_id": "mOgUt4GM", - "author_id": "Dc7EYhxG", - "featured": false, - "name": "Mod Menu v1.14.15 for 1.16.5", - "version_number": "1.14.15", - "changelog": "", - "changelog_url": null, - "date_published": "2021-01-23T23:55:25.659110Z", - "downloads": 125, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "5e213c8cebfed2785f7d4f5f84af121f488e51ce", - "sha512": "c53c4e17a9008f7f3c99b081ae9da14716c62456975e4c7eefc09641f517a788a974fbce6e6924c366f5b5781ae1825b469e2a10b43e1f03a7e3898dd8571c37" - }, - "url": "https://cdn.modrinth.com/data/mOgUt4GM/versions/1.14.15/modmenu-1.14.15.jar", - "filename": "modmenu-1.14.15.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "fabric" - ] - } -] \ No newline at end of file diff --git a/src/test/resources/version/terra.json b/src/test/resources/version/terra.json deleted file mode 100644 index 16e17cc..0000000 --- a/src/test/resources/version/terra.json +++ /dev/null @@ -1,1113 +0,0 @@ -[ - { - "id": "i38N6tkR", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "fabric-5.4.1-BETA+40e95073", - "version_number": "5.4.1-BETA+40e95073", - "changelog": "", - "changelog_url": null, - "date_published": "2021-06-20T00:08:19.146680Z", - "downloads": 3004, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "20229a82dcbd486ef6a680a05021cc76e852b559", - "sha512": "24443715db3143eb53b234aafe519ef1b67da10f796a1ed11410d77947076b6754d7954ae79b1a0d90b27499359031d59aa4da00b91830d0477514d12b223850" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.4.1-BETA+40e95073/Terra-fabric-5.4.1-BETA+40e95073-shaded-mapped.jar", - "filename": "Terra-fabric-5.4.1-BETA+40e95073-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "z4dIPu75", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "fabric-5.3.3-BETA+6027c282", - "version_number": "fabric-5.3.3-BETA+6027c282", - "changelog": "", - "changelog_url": null, - "date_published": "2021-06-08T17:30:42.514821Z", - "downloads": 834, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "a72fcf11b8e1867e5c0a2e354ba9b6ee9b7f60ac", - "sha512": "ff0e48d023f06d76cdbb35e1da12d21b4a24a7a06ef85892bd9ccddd15738b07554faa469acff052ef3e38fde5465a941f49e033578dd0c7de23696a919c2efe" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/fabric-5.3.3-BETA+6027c282/Terra-fabric-5.3.3-BETA+6027c282-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.3-BETA+6027c282-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.17" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "bD7DEeaK", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "forge-5.3.3-BETA+ec3b0e5d", - "version_number": "forge-5.3.3-BETA+ec3b0e5d", - "changelog": "", - "changelog_url": null, - "date_published": "2021-05-23T05:10:36.657171Z", - "downloads": 10183, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha1": "dc9292f501f03d03e5f05f67b8d23ef6378d8b51", - "sha512": "7f449fc1f64500c564a6006c133f1021b3a1bec210b416749173cb996473b9927d240aee6c6fe42ee92a21dd745370c3ebc4043482069c843913c748f6870a99" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/forge-5.3.3-BETA+ec3b0e5d/Terra-forge-5.3.3-BETA+ec3b0e5d.jar", - "filename": "Terra-forge-5.3.3-BETA+ec3b0e5d.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "forge" - ] - }, - { - "id": "9DWPUHbr", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "fabric-5.3.3-BETA+5dd00db8", - "version_number": "fabric-5.3.3-BETA+5dd00db8", - "changelog": "", - "changelog_url": null, - "date_published": "2021-05-19T04:10:22.025090Z", - "downloads": 2804, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "26f517eb0fdd694de00f5ceb4fe6e33a0eba87f4a9ccb86207ef8c104116a4aff497a3c15c7bee23e71511f596735a381503f75e41860d6d1d2f02d441b439e1", - "sha1": "5ffed3a47cf09f192c52fb6476ad7bbca406794e" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/fabric-5.3.3-BETA+5dd00db8/Terra-fabric-5.3.3-BETA+5dd00db8-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.3-BETA+5dd00db8-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "DYQWCFn1", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "forge-5.3.3-BETA+2dc7b501", - "version_number": "forge-5.3.3-BETA+2dc7b501", - "changelog": "", - "changelog_url": null, - "date_published": "2021-05-19T03:36:58.578212Z", - "downloads": 1504, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha1": "04525b596e133311932a04e6b7ada1d69ef294ba", - "sha512": "8b771d6fce2c1f9471b6973c0b25f06d775fb5132ebdeece747f246735f88c89c8defb664009b479ecba4d4c0a528324293bddbe4b0bc14d63cc46b51e198a49" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/forge-5.3.3-BETA+2dc7b501/Terra-forge-5.3.3-BETA+2dc7b501.jar", - "filename": "Terra-forge-5.3.3-BETA+2dc7b501.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "forge" - ] - }, - { - "id": "hrYE97dR", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "fabric-5.3.2-BETA+bac026a1", - "version_number": "fabric-5.3.2-BETA+bac026a1", - "changelog": "", - "changelog_url": null, - "date_published": "2021-05-16T04:51:17.782216Z", - "downloads": 355, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "a9eb4ddce22ec15a0eb1d13702176c7a342e3ce6", - "sha512": "8ad15dda0d689205e6faac8e6dfc73fe4907dbcfa6d68bb7c7fb06000264309561238dbedb5b63013d1a192da1f7c473510c2e3b0c06c12b59592be2beb74f44" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/fabric-5.3.2-BETA+bac026a1/Terra-fabric-5.3.2-BETA+bac026a1-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.2-BETA+bac026a1-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "lrZzc0KE", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "forge-5.3.2-BETA+e86f37fd", - "version_number": "forge-5.3.2-BETA+e86f37fd", - "changelog": "", - "changelog_url": null, - "date_published": "2021-05-15T05:40:52.461013Z", - "downloads": 1682, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha512": "8f8dab17a02727f535dfcfb6d37817cc27e6ad3a349ba108c77a12bd83657037a60812d883d8adf39b00b136076ef1922867ae1043f916932d5f018b55bdd712", - "sha1": "7fd939542fe1e7ba3b86ef2ff55b4ba4a1eb2506" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/forge-5.3.2-BETA+e86f37fd/Terra-forge-5.3.2-BETA+e86f37fd.jar", - "filename": "Terra-forge-5.3.2-BETA+e86f37fd.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "forge" - ] - }, - { - "id": "wM9oTkoy", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "fabric-5.3.2-BETA+9d991dbb", - "version_number": "fabric-5.3.2-BETA+9d991dbb", - "changelog": "", - "changelog_url": null, - "date_published": "2021-05-14T17:32:13.034801Z", - "downloads": 185, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "d300c51e38634641ee8854b0c61990b2fcb08ada", - "sha512": "a2fb03263d80c80dc7acc93ecb5647acc9c35fcdbbab1fbb20fdf403686f432c61f9ec02b305bd14fa212cf1869430c8c8608d72c1e70af24a7c7cf90b4fd9ee" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/fabric-5.3.2-BETA+9d991dbb/Terra-fabric-5.3.2-BETA+9d991dbb-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.2-BETA+9d991dbb-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "BRrEE6Bp", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "fabric-5.3.1-BETA+0ab94917", - "version_number": "fabric-5.3.1-BETA+0ab94917", - "changelog": "", - "changelog_url": null, - "date_published": "2021-05-12T03:10:02.580283Z", - "downloads": 339, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "6b48f470dffb7bc157084f3044deb44cfcd5e4b847a846c81ffad4893cfd9e4c1177254169f6cd1618bcfcd2d745db94badcd3e1e3f361df617cf3c5e27b0613", - "sha1": "4d5259f57253ad4ab1c9959def4dd86c0e5bc980" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/fabric-5.3.1-BETA+0ab94917/Terra-fabric-5.3.1-BETA+0ab94917-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.1-BETA+0ab94917-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "49u1xXFO", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.1-BETA+0ab94917", - "version_number": "5.3.1-BETA+0ab94917-fabric", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-11T23:09:29.462461Z", - "downloads": 58, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "d7abbdb68962f25607a833743e4c77568aa47b59a7d8fd84393f4a4909a16f9a164a8fa643251e8831f0aa989fd3d83a1d0e889bbbbe696db54d31fdf7f1ec74", - "sha1": "29c1c0fe4a060ace636a4c71c412cc4cb7cd477b" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.1-BETA+0ab94917-fabric/Terra-fabric-5.3.1-BETA+0ab94917-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.1-BETA+0ab94917-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "WIgGr0NO", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.1-BETA+2bfaa95a", - "version_number": "5.3.1-BETA+2bfaa95a-fabric", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-11T23:04:44.142443Z", - "downloads": 2, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "d36112b5bdc36b9f73587fb78bd00f64994e4530", - "sha512": "6faa1f5f28a97773689ca292dc045b78931a35af37ca1f427ae519dc1dd22e127a81d444c6d2e4bd3d0b8655818d52f338d054caf196818cff7134f1d6f33f81" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.1-BETA+2bfaa95a-fabric/Terra-fabric-5.3.1-BETA+2bfaa95a-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.1-BETA+2bfaa95a-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "6LSdGHFk", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.1-BETA+96de1554", - "version_number": "5.3.1-BETA+96de1554-fabric", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-11T22:59:28.421224Z", - "downloads": 3, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "0bc4abbc5d8474c8df5ed88b61f744258272cf56817427291107275a3e18084418dfb693192dd93138196922bfe4ef77ae75e0e86e0d74ea2ca4ae6cdcbbcda6", - "sha1": "dc1f9585630bad2ce550caa2b461cdf4593c22b1" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.1-BETA+96de1554-fabric/Terra-fabric-5.3.1-BETA+96de1554-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.1-BETA+96de1554-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "TV5SStzQ", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.1-BETA+f83dcd80", - "version_number": "5.3.1-BETA+f83dcd80-fabric", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-11T16:04:33.658292Z", - "downloads": 55, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "fcc8fd9ed09448fa979ae6bfedccb382c1d89ed005755636fd75fd169d0a9b33ccd718729edd2eac56eb2ba8da1b2424f3676475ad0e018dcb826c881c5f7b35", - "sha1": "1bbff473dcb280109985fa37b63146ec97178588" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.1-BETA+f83dcd80-fabric/Terra-fabric-5.3.1-BETA+f83dcd80-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.1-BETA+f83dcd80-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "w1sOAxwx", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.1-BETA+e00271e4", - "version_number": "5.3.1-BETA+e00271e4-fabric", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-11T06:19:47.983356Z", - "downloads": 105, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "5dc9d5b378bbd27cd10cbcb7b7f8649cdf8be44ca565013e9204956e61622d06e16669ab594aca8bcbdd4860100f2d95241d97dae874f25e41f492c05315a3a4", - "sha1": "320f81bbf6fea8179ba0707ec39324b0927b7b7e" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.1-BETA+e00271e4-fabric/Terra-fabric-5.3.1-BETA+e00271e4-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.1-BETA+e00271e4-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "gG1VHSY5", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.0-BETA+fd48f5f1", - "version_number": "5.3.0-BETA+fd48f5f1-fabric", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-04T23:49:32.273528Z", - "downloads": 635, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "bf605d49dee7a3dd9bf53c3d9aa8236e89abd9ae534926ac08a3d87293afe0e8b4c037e2842bcc2684a414582186533f902d780d849c46775c10c299c9ffe1b8", - "sha1": "75447b4b6468cee52d3ef85c2f8286d01671bcb4" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.0-BETA+fd48f5f1-fabric/Terra-fabric-5.3.0-BETA+fd48f5f1-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.0-BETA+fd48f5f1-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "uGSeZ34X", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.0-BETA+fd48f5f1", - "version_number": "5.3.0-BETA+fd48f5f1-forge", - "changelog": "The project has been updated to project ':platforms:forge'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-04T23:49:28.721624Z", - "downloads": 3465, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha1": "00ae0c809136cd48d464e3b8828f68dd84a455e7", - "sha512": "258b538ae9309a68e6577683da4212348734b6208bbb6cb2a55bd36bc2b558bd453bd82e5712b2f67ca56fe3c8c0e7a868d15f5111e5d4bb0f573f49f9f736c6" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.0-BETA+fd48f5f1-forge/Terra-forge-5.3.0-BETA+fd48f5f1-shaded.jar", - "filename": "Terra-forge-5.3.0-BETA+fd48f5f1-shaded.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "forge" - ] - }, - { - "id": "as9EalBI", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.0-BETA+dbc60b1d", - "version_number": "5.3.0-BETA+dbc60b1d-fabric", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-04T23:20:01.726676Z", - "downloads": 14, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "00254ac571b114ae82f795e53ca23c992e96a369", - "sha512": "caef6d8867408b8484078bbdf88c9fe2ab973bb1964e3e67182cf3d5f14e295d8b6245ae77336d0c57c9314ace3f32d3bb3998b07ec40bbc7819dd7782222131" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.0-BETA+dbc60b1d-fabric/Terra-fabric-5.3.0-BETA+dbc60b1d-shaded-mapped.jar", - "filename": "Terra-fabric-5.3.0-BETA+dbc60b1d-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "tpRPSoxK", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.3.0-BETA+dbc60b1d", - "version_number": "5.3.0-BETA+dbc60b1d-forge", - "changelog": "The project has been updated to project ':platforms:forge'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-04T23:19:58.525675Z", - "downloads": 95, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha1": "dbddbabbf9ff8913dbf5cc425f3a33fcb08539f0", - "sha512": "569f63da94afda35dc2ad9c42ad0c7fd98a603180d41cc66e691e41e605e6f6b5d9a2970b11a5a0e92d4e196ab5104900eba417f7ab6aa01475fc7fd8eb5daae" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.3.0-BETA+dbc60b1d-forge/Terra-forge-5.3.0-BETA+dbc60b1d-shaded.jar", - "filename": "Terra-forge-5.3.0-BETA+dbc60b1d-shaded.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "forge" - ] - }, - { - "id": "SSmQT73f", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.2.1-BETA+a7e3a028", - "version_number": "5.2.1-BETA+a7e3a028-fabric", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-03T00:49:47.553997Z", - "downloads": 19, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "f03106f57767c4bcbc3f2dfbdfd0bdbc4ea2b32b", - "sha512": "cabc50642516ba0d026eb10da684ef043c198fc6c817ad3216976518c9ecb71fe87dfea33b9084d6c316ef7b216919578e1b289cfd06479d770b25dba910f97e" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.2.1-BETA+a7e3a028-fabric/Terra-fabric-5.2.1-BETA+a7e3a028-shaded-mapped.jar", - "filename": "Terra-fabric-5.2.1-BETA+a7e3a028-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "2N4ewkYC", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.2.1-BETA+a7e3a028", - "version_number": "5.2.1-BETA+a7e3a028-forge", - "changelog": "The project has been updated to project ':platforms:forge'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-03T00:49:47.027126Z", - "downloads": 41, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha1": "bb4638f89cb3d92aeb2ef99f9efbe45c0877d385", - "sha512": "74f55db4e5ddd0cd15b9bbd25235312492593bdb12a7b9e9de91dbbee9b504838fe2d452028e95c4011b52427900bc340b4be52d59df2568456abd3ca3b33023" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.2.1-BETA+a7e3a028-forge/Terra-forge-5.2.1-BETA+a7e3a028-shaded.jar", - "filename": "Terra-forge-5.2.1-BETA+a7e3a028-shaded.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "forge" - ] - }, - { - "id": "S2MR1UPS", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.2.1-BETA+6da89248", - "version_number": "5.2.1-BETA+6da89248", - "changelog": "The project has been updated to project ':platforms:forge'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-05-03T00:44:17.711246Z", - "downloads": 48, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha512": "11e9f821d4f127ff56d2cac94cccf24547a4491dfa91e194d7df736cddf55d3af6063b8f36a13be659f2d38b116106a27d73baf369a7d76aadb08bc3209f519b", - "sha1": "2ee706131d954e00576c7ff47cabcdfc1874d796" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.2.1-BETA+6da89248/Terra-forge-5.2.1-BETA+6da89248-shaded.jar", - "filename": "Terra-forge-5.2.1-BETA+6da89248-shaded.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.5" - ], - "loaders": [ - "forge" - ] - }, - { - "id": "WwSRJnsL", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.2.0-BETA+eee54f50", - "version_number": "5.2.0-BETA+eee54f50", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-04-27T04:35:08.844327Z", - "downloads": 27, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "f04060bd63fee40c10ab053aff2f320935b68d19b5d077d31fbb01291f00923c0dabd7c5b7c7574b18e497f83aa56a7a20f85b419a9e81629a622478edfa5f6c", - "sha1": "51411007133351f890bd73c9ded2dbf312f5a817" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.2.0-BETA+eee54f50/Terra-fabric-5.2.0-BETA+eee54f50-shaded-mapped.jar", - "filename": "Terra-fabric-5.2.0-BETA+eee54f50-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "UEeyCR8s", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.3-BETA+f396e0e5", - "version_number": "5.1.3-BETA+f396e0e5", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-04-16T16:04:50.923529Z", - "downloads": 47, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "57a8bb323e7c4d419d9bc4788d27602b3642180be22b95389d57dffc40fd84938cf8a8ae0fc17cde5bbf458e91ed4df56518ec1e05f8dd860a952dc54faab98c", - "sha1": "4be032f695d25d5abe3c9247cde31079b9feadf0" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.3-BETA+f396e0e5/Terra-fabric-5.1.3-BETA+f396e0e5-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.3-BETA+f396e0e5-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "QFi5X6v3", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.3-BETA+5ac72575", - "version_number": "5.1.3-BETA+5ac72575", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-04-12T01:59:56.019903Z", - "downloads": 29, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "3d8adf23d735507a78df5c35a931d4efc50d624c5e4d494888426fa9320799fb5a67edfb10b9eb9d11397a67f9306febb85964012ad34689654d4b767ccc44e9", - "sha1": "9a3165ccb099e6dc947788816d0f274c961db5c1" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.3-BETA+5ac72575/Terra-fabric-5.1.3-BETA+5ac72575-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.3-BETA+5ac72575-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "MyOLliqX", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.2-BETA+7a703ad0", - "version_number": "5.1.2-BETA+7a703ad0", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-04-11T21:20:59.975856Z", - "downloads": 5, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "e5cdfbcc8f5db913bd971ca8af7ba2bef3e91ef5", - "sha512": "577dfdc73c9d0238eba3c27c5963a5c86a945fefc14ea0bdcabacc3b536f6857428638352e4a44dc18ea405a4f20b7e9de01f72d0a746af47ab34b9783362d10" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.2-BETA+7a703ad0/Terra-fabric-5.1.2-BETA+7a703ad0-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.2-BETA+7a703ad0-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "IcJeyROT", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.2-BETA+8a933609", - "version_number": "5.1.2-BETA+8a933609", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-04-01T22:19:37.101837Z", - "downloads": 37, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "c4db77fadef4fcf2eccd72f3cf1025d95ff78c13", - "sha512": "1207c868ed19ef4524920bb1aa9435538d4e3e875f40522ba5ea013b8dd846d8638e96768c84c0e98717bb3308d8bd2ebcb67c6e0502f348f90e8cf4472eab73" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.2-BETA+8a933609/Terra-fabric-5.1.2-BETA+8a933609-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.2-BETA+8a933609-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "ZRDLEqdv", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.2-BETA+f8e8ce8b", - "version_number": "5.1.2-BETA+f8e8ce8b", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-04-01T03:54:45.253691Z", - "downloads": 428, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "49afc056e7fbee77cf909af0c100e6e56dd34f8ca93fee4df2da68717f1d7e7b54a6956d24a15a417bb2b37118b95605124f7497f653c7b4a7efee4e1cfcc113", - "sha1": "51d54039ab98bc8dc297ee2a03bd8a30a284c2a7" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.2-BETA+f8e8ce8b/Terra-fabric-5.1.2-BETA+f8e8ce8b-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.2-BETA+f8e8ce8b-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "YAgTTVXU", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.1-BETA+ec0730ef", - "version_number": "5.1.1-BETA+ec0730ef", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-03-30T04:16:10.640365Z", - "downloads": 38, - "version_type": "release", - "files": [ - { - "hashes": { - "sha512": "324b911a9e18a062f577a49d9906aadc89f16d488486460d20d473fbe64fd9599d618160a19ce3868c239a363ccd56c4e77208c23f2514df7fe1b0476f3fbebb", - "sha1": "160b3e1fa0421947f119aec46a35adca319d2f7d" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.1-BETA+ec0730ef/Terra-fabric-5.1.1-BETA+ec0730ef-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.1-BETA+ec0730ef-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "Gj35Qm97", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.1-BETA+fb8c7098", - "version_number": "5.1.1-BETA+fb8c7098", - "changelog": "The project has been updated to project ':platforms:fabric'. No changelog was specified.", - "changelog_url": null, - "date_published": "2021-03-30T04:08:54.458254Z", - "downloads": 30, - "version_type": "release", - "files": [ - { - "hashes": { - "sha1": "a7aa029b20d0d0b8ff241e84bb8562319d381f9d", - "sha512": "448102309a0f942048b544a74a3e3e167ffe656f37f67c3a5c58bc0dc63b12b5c59dc4c29608856fef980a6585bb0c7e12060a753b46d2d060d8493d96242723" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.1-BETA+fb8c7098/Terra-fabric-5.1.1-BETA+fb8c7098-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.1-BETA+fb8c7098-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "oVS8UkGG", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.1-BETA", - "version_number": "5.1.1-BETA", - "changelog": "", - "changelog_url": null, - "date_published": "2021-03-29T23:54:33.659374Z", - "downloads": 1, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "6b5dae6a0ba85809c651417b39941966cc0cb3929e6b8b4106e6508db2f3f8492f72a514253cde37a06b287e4f5b9506ab97530dc5f74d328d548bc72faa3d59", - "sha1": "127c76ae5f671b2671766657deae1fd13f397c16" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.1-BETA/Terra-fabric-5.1.1-BETA+c5800970-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.1-BETA+c5800970-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "8PKBI4jd", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "Terra-5.1.0-BETA+2e8cd54a", - "version_number": "Terra-5.1.0-BETA+2e8cd54a", - "changelog": "", - "changelog_url": null, - "date_published": "2021-03-17T20:50:21.106124Z", - "downloads": 29, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "6a7813aa0bc9d3508ab4c3b69c23eff8c874f029ee69dcbec3cb8994188b42fc3554d69bd04862182fd8a6c1aa729450b3bb3694cd96ce1f935a2d983083e7cf", - "sha1": "49e7a81a3d9ab17ee2e4395f9ab7a6a518588c90" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/Terra-5.1.0-BETA+2e8cd54a/Terra-fabric-5.1.0-BETA+2e8cd54a-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.0-BETA+2e8cd54a-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "zQ3kJfme", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.1.0-BETA+2e8cd54a", - "version_number": "5.1.0-BETA+2e8cd54a", - "changelog": "", - "changelog_url": null, - "date_published": "2021-03-17T20:36:15.982618Z", - "downloads": 1, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha512": "2c3941a2ae94d73ebb1e519b0935016ba66d9403a90336a9b55b1182818df3cacbe18e2c7a5e25b7444b93aa451c709f6eb78708f3e0eae3a59763370f5628b3", - "sha1": "50825527bac734a98265dc414a29ddb42640c964" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.1.0-BETA+2e8cd54a/Terra-fabric-5.1.0-BETA+2e8cd54a-shaded-mapped.jar", - "filename": "Terra-fabric-5.1.0-BETA+2e8cd54a-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "Bu3XrzNE", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.0.0-BETA+c44d26cc", - "version_number": "5.0.0-BETA+c44d26cc", - "changelog": "Performance improvements\n", - "changelog_url": null, - "date_published": "2021-03-08T05:31:09.257394Z", - "downloads": 29, - "version_type": "beta", - "files": [ - { - "hashes": { - "sha1": "d3c31ec6076758bef23dd5ccad7ccbb506d72e88", - "sha512": "a90ed0199f33fba1c24e42c98bc1f6d5404a9e526f4b1cdba378f552045ccc5d4f805eee3581f64a7f48561fa8ad277257cbe02271988100b8a84bde478edad7" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.0.0-BETA+c44d26cc/Terra-fabric-5.0.0-BETA+c44d26cc-shaded-mapped.jar", - "filename": "Terra-fabric-5.0.0-BETA+c44d26cc-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "1TeOdIt7", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.0.0-BETA+7f988dcf", - "version_number": "5.0.0-BETA+7f988dcf", - "changelog": "This version adds inventory and entity support, meaning the `loot` and `entity` TerraScript functions will now work.\n\nIt also adds more rotation stuff, so there should no longer be weirdly rotated stuff in structures.", - "changelog_url": null, - "date_published": "2021-02-25T08:53:57.376949Z", - "downloads": 46, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha512": "35ead16c9e7948b50a61a65a639bc5908e6fa98bd0d8f25a2facd49c8a429ec25dc77ebd469c2f78d4753f3df5cc964e9685768eff6f61146f7f015371acff45", - "sha1": "660a6023c2bccadc18931a1cecbeccbaaffd266e" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.0.0-BETA+7f988dcf/Terra-fabric-5.0.0-BETA+7f988dcf-shaded-mapped.jar", - "filename": "Terra-fabric-5.0.0-BETA+7f988dcf-shaded-mapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - }, - { - "id": "6jFzKi0e", - "mod_id": "FIlZB9L0", - "author_id": "2PqmLmXm", - "featured": false, - "name": "5.0.0-BETA+1637644b", - "version_number": "5.0.0-BETA+1637644b", - "changelog": "", - "changelog_url": null, - "date_published": "2021-02-24T22:24:59.184812Z", - "downloads": 20, - "version_type": "alpha", - "files": [ - { - "hashes": { - "sha1": "83917b1f185b820fd7c331d7efadbe570cf955fb", - "sha512": "bb1a9ccd86fb6e0f427dca6252ccbd680b71c1d7ffb41389c23f0b459d0ed3c41f279a652ca6393758be07f340dae2d45972c8a44a43f9c5e811efd2bfdfad80" - }, - "url": "https://cdn.modrinth.com/data/FIlZB9L0/versions/5.0.0-BETA+1637644b/Terra-fabric-5.0.0-BETA+1637644b-shaded-remapped.jar", - "filename": "Terra-fabric-5.0.0-BETA+1637644b-shaded-remapped.jar", - "primary": false - } - ], - "dependencies": [], - "game_versions": [ - "1.16.4", - "1.16.5" - ], - "loaders": [ - "fabric" - ] - } -] \ No newline at end of file