From c0b0111060d06705659b73bc4a1baa29b7644c1d Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Sun, 27 Oct 2024 11:31:14 +0000 Subject: [PATCH] feat: publishing CI --- .github/workflows/release.yml | 29 +++ .gitignore | 3 +- update/changelog.md => CHANGELOG.md | 2 +- Jenkinsfile | 35 --- build.gradle | 243 +++++++++++++----- gradle.properties | 16 +- gradle/wrapper/gradle-wrapper.properties | 2 +- libs/FastWorkbench-1.12.2-1.3.2.jar | Bin 23218 -> 0 bytes settings.gradle | 1 + .../mod/update/ThreadUpdateChecker.java | 85 ------ .../mod/update/UpdateChecker.java | 56 ---- .../resources/META-INF/accesstransformer.cfg | 2 +- .../META-INF/neoforge.mods.toml | 33 +-- update/updateVersions.properties | 11 - 14 files changed, 240 insertions(+), 278 deletions(-) create mode 100644 .github/workflows/release.yml rename update/changelog.md => CHANGELOG.md (99%) delete mode 100644 Jenkinsfile delete mode 100644 libs/FastWorkbench-1.12.2-1.3.2.jar delete mode 100644 src/main/java/de/ellpeck/actuallyadditions/mod/update/ThreadUpdateChecker.java delete mode 100644 src/main/java/de/ellpeck/actuallyadditions/mod/update/UpdateChecker.java rename src/main/{resources => templates}/META-INF/neoforge.mods.toml (56%) delete mode 100644 update/updateVersions.properties diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..b9f4da548 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,29 @@ +name: "Release" + +on: + push: + tags: + - "v*" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Clone project + uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: "microsoft" + java-version: 21 + - name: Fix borked permissions + run: chmod +x ./gradlew + - name: Run gradle tasks + uses: gradle/gradle-build-action@v2 + env: + MR_TOKEN: ${{ secrets.MR_TOKEN }} + CF_TOKEN: ${{ secrets.CF_TOKEN }} + MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + arguments: clean build publish publishMods diff --git a/.gitignore b/.gitignore index 5cd074a6a..b2b67e101 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ .settings/org.eclipse.buildship.core.prefs *.launch .settings/org.eclipse.jdt.core.prefs -*.prefs \ No newline at end of file +*.prefs +.DS_Store diff --git a/update/changelog.md b/CHANGELOG.md similarity index 99% rename from update/changelog.md rename to CHANGELOG.md index d2d4caa03..4e12e9422 100644 --- a/update/changelog.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.3.6+mc1.21.1 +# 1.3.7+mc1.21.1 * Added recipes for AA crops in the IE cloche. # 1.3.6+mc1.21.1 diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 7ae0e3cdf..000000000 --- a/Jenkinsfile +++ /dev/null @@ -1,35 +0,0 @@ -pipeline { - agent any - stages { - stage('Clean') { - steps { - sh './gradlew clean --no-daemon' - } - } - - stage('Build') { - steps { - sh './gradlew build --no-daemon' - } - } - - stage('Upload Artifacts') { - steps { - archiveArtifacts 'build/libs/**.jar' - } - } - - stage('Publish') { - when { - branch '1.12.2' - } - steps { - sh './gradlew publish --no-daemon' - } - } - - } - environment { - local_maven = '/var/www/maven' - } -} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 75f254de4..3b730b94e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,76 +1,92 @@ plugins { id 'java-library' - id 'eclipse' - id 'idea' id 'maven-publish' - id 'net.neoforged.gradle.userdev' version '7.0.165' + id 'net.neoforged.moddev' version '1.0.21' + id "me.modmuss50.mod-publish-plugin" version "0.7.4" } -def buildSuffix = System.getenv('BUILD_NUMBER') ? "-b${System.getenv('BUILD_NUMBER')}" : "" +tasks.named('wrapper', Wrapper).configure { + distributionType = Wrapper.DistributionType.BIN +} + +version = "$mod_version+mc${game_version}" +group = "de.ellpeck" -version = "$mod_version+mc${game_version}${buildSuffix}" -group = "de.ellpeck.actuallyadditions" base { - archivesName = "ActuallyAdditions" + archivesName = "actuallyadditions" } java.toolchain.languageVersion = JavaLanguageVersion.of(21) -if (rootProject.file('src/main/resources/META-INF/accesstransformer.cfg').exists()) { - minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg') -} +neoForge { + version = project.neo_version -runs { - // applies to all the run configs below - configureEach { net.neoforged.gradle.dsl.common.runs.run.Run run -> - //Limit ram usage for the dev environment to 4GB - jvmArgument '-Xmx4G' + parchment { + mappingsVersion = project.parchment_mappings_version + minecraftVersion = project.hasProperty("parchment_minecraft_version") ? project.parchment_minecraft_version : project.game_version + } - if (run.project.javaToolchains.launcherFor(java.toolchain).map { it.metadata.vendor }.getOrElse("").contains("JetBrains")) { - run.jvmArgument("-XX:+AllowEnhancedClassRedefinition") + runs { + client { + client() + systemProperty 'neoforge.enabledGameTestNamespaces', "actuallyadditions" + programArguments.addAll '--width=1920', '--height=1080' } - modSource project.sourceSets.main + client2 { + client() + + programArguments.addAll '--username', 'Dev2' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + systemProperty 'neoforge.enabledGameTestNamespaces', "actuallyadditions" + } + + server { + server() + programArgument '--nogui' + systemProperty 'neoforge.enabledGameTestNamespaces', "actuallyadditions" + } + + gameTestServer { + type = "gameTestServer" + systemProperty 'neoforge.enabledGameTestNamespaces', "actuallyadditions" + } + + data { + data() + programArguments.addAll '--mod', "actuallyadditions", '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() + } + + configureEach { run -> + systemProperty 'forge.logging.markers', 'REGISTRIES' + logLevel = org.slf4j.event.Level.DEBUG + + jvmArgument '-Xmx4G' + + if (run.project.javaToolchains.launcherFor(java.toolchain).map { it.metadata.vendor }.getOrElse("").contains("JetBrains")) { + run.jvmArgument("-XX:+AllowEnhancedClassRedefinition") + } + } } - client { - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - systemProperty 'neoforge.enabledGameTestNamespaces', "actuallyadditions" - } - client2 { - configure ("client") - - programArguments.addAll '--username', 'Dev2' - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - systemProperty 'neoforge.enabledGameTestNamespaces', "actuallyadditions" - } - - server { - systemProperty 'neoforge.enabledGameTestNamespaces', "actuallyadditions" - programArgument '--nogui' - } - - data { - // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it - // workingDirectory project.file('run-data') - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - programArguments.addAll '--mod', "actuallyadditions", '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() + mods { + "actuallyadditions" { + sourceSet(sourceSets.main) + } } } sourceSets.main.resources { srcDir 'src/generated/resources' } -// Sets up a dependency configuration called 'localRuntime'. -// This configuration should be used instead of 'runtimeOnly' to declare -// a dependency that will be present for runtime testing but that is -// "optional", meaning it will not be pulled by dependents of this mod. configurations { runtimeClasspath.extendsFrom localRuntime } repositories { + maven { + url = "https://maven.neoforged.net/releases" + } maven { url = "https://maven.blamejared.com" } @@ -84,8 +100,6 @@ repositories { } dependencies { - implementation "net.neoforged:neoforge:${neo_version}" - compileOnly "mezz.jei:jei-${jei_minecraft}-common-api:${jei_version}" compileOnly "mezz.jei:jei-${jei_minecraft}-neoforge-api:${jei_version}" @@ -126,7 +140,28 @@ jar { from sourceSets.main.output } -task apiJar(type: Jar) { +var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) { + var replaceProperties = [ + minecraft_version : game_version, + minecraft_version_range: game_version_range, + neo_version : neo_version, + neo_version_range : neo_version_range, + loader_version_range : loader_version_range, + mod_id : "actuallyadditions", + mod_name : "Actually Additions", + mod_version : mod_version, + ] + + inputs.properties replaceProperties + expand replaceProperties + from "src/main/templates" + into "build/generated/sources/modMetadata" +} + +sourceSets.main.resources.srcDir generateModMetadata +neoForge.ideSyncTask generateModMetadata + +tasks.register('apiJar', Jar) { from sourceSets.main.output from sourceSets.main.java archiveClassifier.set('api') @@ -137,12 +172,13 @@ javadoc { include 'de/ellpeck/actuallyadditions/api/**' } -task javadocJar(type: Jar, dependsOn: javadoc) { +tasks.register('javadocJar', Jar) { + dependsOn javadoc from 'build/docs/javadoc' archiveClassifier.set('javadoc') } -task sourcesJar(type: Jar) { +tasks.register('sourcesJar', Jar) { from sourceSets.main.java archiveClassifier.set('sources') } @@ -151,38 +187,111 @@ artifacts { archives sourcesJar, apiJar, javadocJar } -publishing { - tasks.publish.dependsOn build - publications { - mavenJava(MavenPublication) { - groupId = group - artifactId = base.archivesName.get() - version = version +publishing { + publications { + register('mavenJava', MavenPublication) { from components.java + // Add sources and javadoc to the publication artifact sourcesJar artifact apiJar artifact javadocJar - - pom.withXml { - def node = asNode() - if (node.dependencies.size() > 0) - node.remove(node.dependencies) - } } } + repositories { - maven { - url "file://" + System.getenv("local_maven") + def token = providers.environmentVariable("MAVEN_TOKEN") + if (token.isPresent()) { + maven { + url "https://maven.saps.dev/releases" + credentials { + username = "ell" + password = token.get() + } + } } } } -// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior. + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' +} + idea { module { downloadSources = true downloadJavadoc = true } } + +/** + * Seek out the changelog for the current version and return it as a string. + */ +def createChangelog = () -> { + def changelogText = new File("CHANGELOG.md").text + def changelog = "" + + def lines = changelogText.split("\n") + def inChangelog = false + for (int i = 0; i < lines.size(); i++) { + def line = lines[i] + if (line.startsWith("# ")) { + if (inChangelog) { + break + } else { + if (line.contains(mod_version)) { + inChangelog = true + } + } + } + + if (inChangelog) { + changelog += line + "\n" + } + } + + def output = changelog.trim() + return output.empty ? "No changelog found" : output +} + +def cfToken = providers.environmentVariable("CF_TOKEN") +def mrToken = providers.environmentVariable("MR_TOKEN") +def ghToken = providers.environmentVariable("GITHUB_TOKEN") + +publishMods { + dryRun = !cfToken.isPresent() || !mrToken.isPresent() || !ghToken.isPresent() + changelog = createChangelog().trim() + version = mod_version + displayName = "Actually Additions ${mod_version}" + type = STABLE + + file = jar.archiveFile + + additionalFiles.from apiJar.archiveFile + additionalFiles.from javadocJar.archiveFile + additionalFiles.from sourcesJar.archiveFile + + modLoaders.add("neoforge") + + curseforge { + accessToken = cfToken + projectId = "228404" + minecraftVersions.add(game_version) + javaVersions.add(JavaVersion.VERSION_21) + } + + modrinth { + accessToken = mrToken + projectId = "4K7Q3nqd" + minecraftVersions.add(game_version) + } + + github { + repository = "Ellpeck/ActuallyAdditions" + accessToken = ghToken + commitish = providers.environmentVariable("GITHUB_SHA").orElse("dryRun") + tagName = providers.environmentVariable("GITHUB_REF_NAME").orElse("dryRun") + } +} diff --git a/gradle.properties b/gradle.properties index 72c446dd9..6073706ce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,17 +1,23 @@ org.gradle.jvmargs=-Xmx3G -org.gradle.daemon=false -# Actually Additions +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configuration-cache=false mod_version=1.3.7 # Forge game_version=1.21.1 +game_version_range=[1.21.1,1.22) + neo_version=21.1.71 +neo_version_range=[21.1,21.2) +loader_version_range=4 # Parchment (Mappings) -neogradle.subsystems.parchment.minecraftVersion=1.21 -neogradle.subsystems.parchment.mappingsVersion=2024.07.28 -neogradle.subsystems.conventions.runs.create-default-run-per-type=false +# Uncomment to apply a different mc version for parchment +parchment_minecraft_version=1.21 +parchment_mappings_version=2024.07.28 # Other mods jei_minecraft=1.21.1 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4413138c..09523c0e5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/libs/FastWorkbench-1.12.2-1.3.2.jar b/libs/FastWorkbench-1.12.2-1.3.2.jar deleted file mode 100644 index 5f43fdda6f98a419b308034333dc7a9bf804d250..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23218 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

1`wvA6^? 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 D)z_Pn diff --git a/settings.gradle b/settings.gradle index c37689192..de72f59b3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,4 +11,5 @@ pluginManagement { plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } + rootProject.name = "actuallyadditions" diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/update/ThreadUpdateChecker.java b/src/main/java/de/ellpeck/actuallyadditions/mod/update/ThreadUpdateChecker.java deleted file mode 100644 index df830fb91..000000000 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/update/ThreadUpdateChecker.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file ("ThreadUpdateChecker.java") is part of the Actually Additions mod for Minecraft. - * It is created and owned by Ellpeck and distributed - * under the Actually Additions License to be found at - * http://ellpeck.de/actaddlicense - * View the source code at https://github.com/Ellpeck/ActuallyAdditions - * - * © 2015-2017 Ellpeck - */ - -package de.ellpeck.actuallyadditions.mod.update; - -import de.ellpeck.actuallyadditions.mod.ActuallyAdditions; -import de.ellpeck.actuallyadditions.mod.config.CommonConfig; -import de.ellpeck.actuallyadditions.mod.util.Util; - -import java.io.InputStreamReader; -import java.net.URL; -import java.util.Properties; - -public class ThreadUpdateChecker extends Thread { - - public ThreadUpdateChecker() { - this.setName(ActuallyAdditions.NAME + " Update Checker"); - this.setDaemon(true); - this.start(); - } - - @Override - public void run() { - ActuallyAdditions.LOGGER.info("Starting Update Check..."); - try { - URL newestURL = new URL("https://raw.githubusercontent.com/Ellpeck/ActuallyAdditions/main/update/updateVersions.properties"); - Properties updateProperties = new Properties(); - updateProperties.load(new InputStreamReader(newestURL.openStream())); - - String currentMcVersion = Util.getMcVersion(); - if (CommonConfig.Other.UPDATE_CHECK_VERSION_SPECIFIC.get()) { - String newestVersionProp = updateProperties.getProperty(currentMcVersion); - - UpdateChecker.updateVersionInt = Integer.parseInt(newestVersionProp); - UpdateChecker.updateVersionString = currentMcVersion + "-r" + newestVersionProp; - } else { - int highest = 0; - String highestString = ""; - - for (String updateMC : updateProperties.stringPropertyNames()) { - String updateVersion = updateProperties.getProperty(updateMC); - int update = Integer.parseInt(updateVersion); - if (highest < update) { - highest = update; - highestString = updateMC + "-r" + updateVersion; - } - } - - UpdateChecker.updateVersionInt = highest; - UpdateChecker.updateVersionString = highestString; - } - - String clientVersionString = Util.getMajorModVersion(); - int clientVersion = Integer.parseInt(clientVersionString.contains("_") ? clientVersionString.substring(0, clientVersionString.indexOf("_")) : clientVersionString); - if (UpdateChecker.updateVersionInt > clientVersion) { - UpdateChecker.needsUpdateNotify = true; - } - - ActuallyAdditions.LOGGER.info("Update Check done!"); - } catch (Exception e) { - ActuallyAdditions.LOGGER.error("Update Check failed!", e); - UpdateChecker.checkFailed = true; - } - - if (!UpdateChecker.checkFailed) { - if (UpdateChecker.needsUpdateNotify) { - ActuallyAdditions.LOGGER.info("There is an Update for " + ActuallyAdditions.NAME + " available!"); - ActuallyAdditions.LOGGER.info("Current Version: " + ActuallyAdditions.VERSION + ", newest Version: " + UpdateChecker.updateVersionString + "!"); - ActuallyAdditions.LOGGER.info("View the Changelog at " + UpdateChecker.CHANGELOG_LINK); - ActuallyAdditions.LOGGER.info("Download at " + UpdateChecker.DOWNLOAD_LINK); - } else { - ActuallyAdditions.LOGGER.info(ActuallyAdditions.NAME + " is up to date!"); - } - } - - UpdateChecker.threadFinished = true; - } -} \ No newline at end of file diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/update/UpdateChecker.java b/src/main/java/de/ellpeck/actuallyadditions/mod/update/UpdateChecker.java deleted file mode 100644 index df8c1e42a..000000000 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/update/UpdateChecker.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file ("UpdateChecker.java") is part of the Actually Additions mod for Minecraft. - * It is created and owned by Ellpeck and distributed - * under the Actually Additions License to be found at - * http://ellpeck.de/actaddlicense - * View the source code at https://github.com/Ellpeck/ActuallyAdditions - * - * © 2015-2017 Ellpeck - */ - -package de.ellpeck.actuallyadditions.mod.update; - -import de.ellpeck.actuallyadditions.mod.ActuallyAdditions; -import net.minecraft.client.Minecraft; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.neoforge.client.event.ClientTickEvent; -import net.neoforged.neoforge.common.NeoForge; - -public class UpdateChecker { - - public static final String DOWNLOAD_LINK = "http://ellpeck.de/actadddownload"; - public static final String CHANGELOG_LINK = "http://ellpeck.de/actaddchangelog"; - public static boolean checkFailed; - public static boolean needsUpdateNotify; - public static int updateVersionInt; - public static String updateVersionString; - public static boolean threadFinished = false; - - public UpdateChecker() { -// if (CommonConfig.OTHER.DO_UPDATE_CHECK.get() && !Util.isDevVersion()) { -// ActuallyAdditions.LOGGER.info("Initializing Update Checker..."); -// new ThreadUpdateChecker(); -// MinecraftForge.EVENT_BUS.register(this); -// } - } - - - @SubscribeEvent(receiveCanceled = true) - public void onTick(ClientTickEvent.Pre event) { - if (Minecraft.getInstance().player != null) { - Player player = Minecraft.getInstance().player; - if (UpdateChecker.checkFailed) { - player.displayClientMessage(Component.translatable("info.actuallyadditions.update.failed"), false); - } else if (UpdateChecker.needsUpdateNotify) { - player.displayClientMessage(Component.translatable("info.actuallyadditions.update.generic"), false); - player.displayClientMessage(Component.translatable("info.actuallyadditions.update.versionCompare", ActuallyAdditions.VERSION, UpdateChecker.updateVersionString), false); - player.displayClientMessage(Component.translatable("info.actuallyadditions.update.buttons", UpdateChecker.CHANGELOG_LINK, UpdateChecker.DOWNLOAD_LINK), false); - } - if (threadFinished) { - NeoForge.EVENT_BUS.unregister(this); - } - } - } -} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 66112eb33..d25ef625f 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -8,4 +8,4 @@ public net.minecraft.world.inventory.InventoryMenu TEXTURE_EMPTY_SLOTS public net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool templates public-f net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool rawTemplates public net.minecraft.world.entity.npc.VillagerTrades$ItemsForEmeralds -public net.minecraft.world.entity.npc.VillagerTrades$EmeraldForItems \ No newline at end of file +public net.minecraft.world.entity.npc.VillagerTrades$EmeraldForItems diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/templates/META-INF/neoforge.mods.toml similarity index 56% rename from src/main/resources/META-INF/neoforge.mods.toml rename to src/main/templates/META-INF/neoforge.mods.toml index 961f45804..b0a12609c 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/templates/META-INF/neoforge.mods.toml @@ -1,30 +1,33 @@ - modLoader="javafml" -loaderVersion="[4,)" +loaderVersion="${loader_version_range}" license="MIT" +issueTrackerURL="https://github.com/Ellpeck/ActuallyAdditions/issues" + [[mods]] modId="actuallyadditions" -version="${file.jarVersion}" -displayName="Actually Additions" -#logoFile="logo.png" +version="${mod_version}" +displayName="${mod_name}" +displayURL="https://github.com/Ellpeck/ActuallyAdditions" credits="Author: Ellpeck; Textures and Models: BootyToast, GlenthorLP, canitzp; Porters: Flanks, MrBysco, ErrorMikey; 1.20+ Textures: Ridanisaurus" authors="Ellpeck" description=''' Do you want Automation? Wireless Transport? Better Machines? A cup o\' Coffee? Chests? Better Hoppers? Leaf Blowers? Faster Growth? Plants? Well, Actually Additions has all that and a lot more! ''' + [[mixins]] config = "actuallyadditions.mixins.json" [[dependencies.actuallyadditions]] - modId="neoforge" - type="required" - versionRange="[21.1.1,)" - ordering="NONE" - side="BOTH" +modId="neoforge" +type="required" +versionRange="${neo_version_range}" +ordering="NONE" +side="BOTH" +# Here's another dependency [[dependencies.actuallyadditions]] - modId="minecraft" - type="required" - versionRange="[1.21.1,1.22)" - ordering="NONE" - side="BOTH" +modId="minecraft" +type="required" +versionRange="${minecraft_version_range}" +ordering="NONE" +side="BOTH" diff --git a/update/updateVersions.properties b/update/updateVersions.properties deleted file mode 100644 index bff0f8155..000000000 --- a/update/updateVersions.properties +++ /dev/null @@ -1,11 +0,0 @@ -1.7.10=21 -1.8.9=26 -1.9=33 -1.9.4=45 -1.10=46 -1.10.2=105 -1.11=92 -1.11.2=110 -1.12=118 -1.12.1=121 -1.12.2=151 \ No newline at end of file