commit 32c32df053363a7bb276f040f146805b8b4abb44
Author: FalsePattern <30945458+FalsePattern@users.noreply.github.com>
Date: Thu Mar 9 20:06:44 2023 +0100
Initial Commit
diff --git a/.github/scripts/test-no-error-reports.sh b/.github/scripts/test-no-error-reports.sh
new file mode 100755
index 0000000..1fcc739
--- /dev/null
+++ b/.github/scripts/test-no-error-reports.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+
+# bashsupport disable=BP5006 # Global environment variables
+RUNDIR="run" \
+ CRASH="crash-reports" \
+ SERVERLOG="server.log"
+
+# enable nullglob to get 0 results when no match rather than the pattern
+shopt -s nullglob
+
+# store matches in array
+crash_reports=("$RUNDIR/$CRASH/crash"*.txt)
+
+# if array not empty there are crash_reports
+if [ "${#crash_reports[@]}" -gt 0 ]; then
+ # get the latest crash_report from array
+ latest_crash_report="${crash_reports[-1]}"
+ {
+ printf 'Latest crash report detected %s:\n' "${latest_crash_report##*/}"
+ cat "$latest_crash_report"
+ } >&2
+ exit 1
+fi
+
+if grep --quiet --fixed-strings 'Fatal errors were detected' "$SERVERLOG"; then
+ {
+ printf 'Fatal errors detected:\n'
+ cat server.log
+ } >&2
+ exit 1
+fi
+
+if grep --quiet --fixed-strings 'The state engine was in incorrect state ERRORED and forced into state SERVER_STOPPED' \
+ "$SERVERLOG"; then
+ {
+ printf 'Server force stopped:'
+ cat server.log
+ } >&2
+ exit 1
+fi
+
+if ! grep --quiet --perl-regexp --only-matching '.+Done \(.+\)\! For help, type "help" or "\?"' "$SERVERLOG"; then
+ {
+ printf 'Server did not finish startup:'
+ cat server.log
+ } >&2
+ exit 1
+fi
+
+printf 'No crash reports detected'
+exit 0
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
new file mode 100644
index 0000000..08df9fe
--- /dev/null
+++ b/.github/workflows/build-and-test.yml
@@ -0,0 +1,45 @@
+# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
+
+name: Build and test
+
+on:
+ pull_request:
+ branches: [ master, main ]
+ push:
+ branches: [ master, main ]
+
+jobs:
+ build-and-test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@v2
+ with:
+ java-version: '8'
+ distribution: 'adopt'
+ cache: gradle
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Setup the workspace
+ run: ./gradlew setupCIWorkspace
+
+ - name: Build the mod
+ run: ./gradlew build
+
+ - name: Run server for 1.5 minutes
+ run: |
+ mkdir run
+ echo "eula=true" > run/eula.txt
+ timeout 90 ./gradlew runServer | tee --append server.log || true
+
+ - name: Test no errors reported during server run
+ run: |
+ chmod +x .github/scripts/test-no-error-reports.sh
+ .github/scripts/test-no-error-reports.sh
diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml
new file mode 100644
index 0000000..dffb841
--- /dev/null
+++ b/.github/workflows/release-tags.yml
@@ -0,0 +1,50 @@
+# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
+
+name: Release tagged build
+
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ - name: Set release version
+ run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@v2
+ with:
+ java-version: '8'
+ distribution: 'adopt'
+ cache: gradle
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Setup the workspace
+ run: ./gradlew setupCIWorkspace
+
+ - name: Publish to Maven, Modrinth, and CurseForge
+ run: ./gradlew publish
+ env:
+ MAVEN_DEPLOY_USER: ${{ secrets.MAVEN_DEPLOY_USER }}
+ MAVEN_DEPLOY_PASSWORD: ${{ secrets.MAVEN_DEPLOY_PASSWORD }}
+ MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
+ CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }}
+
+ - name: Release under current tag
+ uses: "marvinpinto/action-automatic-releases@latest"
+ with:
+ repo_token: "${{ secrets.GITHUB_TOKEN }}"
+ automatic_release_tag: "${{ env.RELEASE_VERSION }}"
+ prerelease: false
+ title: "${{ env.RELEASE_VERSION }}"
+ files: build/libs/*.jar
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bf03ff1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,225 @@
+# Created by https://www.toptal.com/developers/gitignore/api/intellij+all,gradle,forgegradle,java,eclipse,netbeans
+# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+all,gradle,forgegradle,java,eclipse,netbeans
+
+### Eclipse ###
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# CDT- autotools
+.autotools
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/
+
+# Annotation Processing
+.apt_generated/
+.apt_generated_test/
+
+# Scala IDE specific (Scala & Java development for Eclipse)
+.cache-main
+.scala_dependencies
+.worksheet
+
+# Uncomment this line if you wish to ignore the project description file.
+# Typically, this file would be tracked if it contains build/dependency configurations:
+#.project
+
+### Eclipse Patch ###
+# Spring Boot Tooling
+.sts4-cache/
+
+### ForgeGradle ###
+# Minecraft client/server files
+run/
+
+### Intellij+all ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+.idea/artifacts
+.idea/compiler.xml
+.idea/jarRepositories.xml
+.idea/modules.xml
+.idea/*.iml
+.idea/modules
+*.iml
+*.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij+all Patch ###
+# Ignore everything but code style settings and run configurations
+# that are supposed to be shared within teams.
+
+.idea/*
+
+!.idea/codeStyles
+!.idea/runConfigurations
+
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+replay_pid*
+
+### NetBeans ###
+**/nbproject/private/
+**/nbproject/Makefile-*.mk
+**/nbproject/Package-*.bash
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+### Gradle ###
+.gradle
+**/build/
+!src/**/build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# Avoid ignore Gradle wrappper properties
+!gradle-wrapper.properties
+
+# Cache of project
+.gradletasknamecache
+
+# Eclipse Gradle plugin generated files
+# Eclipse Core
+.project
+# JDT-specific (Eclipse Java Development Tools)
+.classpath
+
+### Gradle Patch ###
+# Java heap dump
+*.hprof
+
+# End of https://www.toptal.com/developers/gitignore/api/intellij+all,gradle,forgegradle,java,eclipse,netbeans
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..ad03daa
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..cf3b250
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,63 @@
+#-------------------------------------------------------------------------------
+# @author FalsePattern
+#
+# Copyright 2023
+#
+# All rights reserved.
+# Distribution of the software in any form is only allowed with
+# explicit, prior permission from the owner.
+#-------------------------------------------------------------------------------
+@author FalsePattern
+
+
+This code is the property of and owned and copyrighted by FalsePattern.
+This code is provided under a modified visible-source license
+that is as follows:
+
+
+API Code:
+==============================
+API code is identifiable as being in an "API" package in the respective
+repository or mod, and is intended to allow some level of inter-mod
+interactions without creating hard dependencies on the mod proper. This code
+is exempt from the below restrictions for "Mod Code", as it by nature will
+require some level of copying and redistribution.
+
+The only restrictions imposed on API code are that it remain clearly marked
+with its original authorship and source, that it be used for the purpose
+described previously, and that it not be modified from the original without
+first contacting FalsePattern.
+
+
+Mod Code:
+==============================
+Any and all users are permitted to use the source for educational purposes,
+or to create derivative works for private use only. GitHub forks and direct
+downloads are considered derivative works.
+
+Unless given explicit written permission - verifiable electronic writing is
+acceptable - no user may redistribute this source code nor any derivative
+works. These pre-approved works must prominently contain this copyright notice.
+
+Derivative mods using any or all of the source code or assets are
+EXPRESSLY FORBIDDEN.
+
+Additionally, no attempt may be made to achieve monetary gain from this code
+by anyone except the original author. In the case of pre-approved derivative
+works, any monetary gains made will be shared between the original author and
+the other developer(s), proportional to the ratio of derived to original code.
+
+Finally, any and all displays, duplicates or derivatives of this code must be
+prominently marked as such, and must contain attribution to the original
+author, including a link to the original source. Any attempts to claim credit
+for this code will be treated as intentional theft.
+
+Due to the Mojang and Minecraft Mod Terms of Service and Licensing
+Restrictions, compiled versions of this code must be provided for free.
+However, with the exception of pre-approved derivative works, only the original
+author's modpacks may distribute compiled binary versions of this code.
+
+==============================
+
+Failure to comply with these restrictions is a violation of copyright law and
+will be dealt with accordingly.
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..da49aa0
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,1149 @@
+//version: 1656003793falsepattern63
+/*
+DO NOT CHANGE THIS FILE!
+
+Also, you may replace this file at any time if there is an update available.
+Please check https://github.com/FalsePattern/ExampleMod1.7.10/blob/main/build.gradle for updates.
+ */
+
+
+import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
+import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
+import com.matthewprenger.cursegradle.CurseArtifact
+import com.matthewprenger.cursegradle.CurseRelation
+import com.modrinth.minotaur.dependencies.ModDependency
+import com.modrinth.minotaur.dependencies.VersionDependency
+import org.gradle.internal.logging.text.StyledTextOutput.Style
+import org.gradle.internal.logging.text.StyledTextOutputFactory
+
+import java.nio.file.Files
+import java.nio.file.Paths
+import java.util.concurrent.TimeUnit
+import java.util.zip.ZipEntry
+import java.util.zip.ZipInputStream
+import java.util.zip.ZipOutputStream
+
+buildscript {
+ repositories {
+ mavenLocal()
+ maven {
+ name = "forge"
+ url = "https://mvn.falsepattern.com/forge"
+ }
+ maven {
+ name = "sonatype"
+ url = "https://oss.sonatype.org/content/repositories/snapshots/"
+ }
+ maven {
+ name = "Scala CI dependencies"
+ url = "https://repo1.maven.org/maven2/"
+ }
+ maven {
+ name = "jitpack"
+ url = "https://mvn.falsepattern.com/jitpack/"
+ }
+ maven {
+ name = "mavenpattern"
+ url = "https://mvn.falsepattern.com/releases/"
+ }
+ maven {
+ name = "usrv"
+ url = "https://mvn.falsepattern.com/usrv/"
+ }
+ }
+ dependencies {
+ classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.11'
+ classpath 'com.falsepattern:jtweaker:0.2.1'
+ }
+}
+
+plugins {
+ id 'java-library'
+ id 'idea'
+ id 'eclipse'
+ id 'scala'
+ id 'maven-publish'
+ id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false
+ id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false
+ id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false
+ id 'org.ajoberstar.grgit' version '4.1.1'
+ id 'com.github.johnrengelman.shadow' version '4.0.4'
+ id 'com.palantir.git-version' version '0.13.0'
+ id 'de.undercouch.download' version '5.0.1'
+ id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false
+ id 'com.modrinth.minotaur' version '2.+' apply false
+ id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
+}
+apply plugin: 'com.falsepattern.jtweaker'
+
+def out = services.get(StyledTextOutputFactory).create('an-output')
+
+apply plugin: 'forge'
+
+def projectJavaVersion = JavaLanguageVersion.of(8)
+
+java {
+ toolchain {
+ languageVersion.set(projectJavaVersion)
+ }
+}
+
+idea {
+ module {
+ inheritOutputDirs = true
+ downloadJavadoc = true
+ downloadSources = true
+ }
+}
+
+if(JavaVersion.current() != JavaVersion.VERSION_1_8) {
+ throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current())
+}
+
+checkPropertyExists("modName")
+checkPropertyExists("modId")
+checkPropertyExists("modGroup")
+checkPropertyExists("autoUpdateBuildScript")
+checkPropertyExists("minecraftVersion")
+checkPropertyExists("forgeVersion")
+checkPropertyExists("replaceGradleTokenInFile")
+checkPropertyExists("gradleTokenModId")
+checkPropertyExists("gradleTokenModName")
+checkPropertyExists("gradleTokenVersion")
+checkPropertyExists("gradleTokenGroupName")
+checkPropertyExists("apiPackage")
+checkPropertyExists("accessTransformersFile")
+checkPropertyExists("usesMixins")
+checkPropertyExists("mixinPlugin")
+checkPropertyExists("mixinsPackage")
+checkPropertyExists("coreModClass")
+checkPropertyExists("containsMixinsAndOrCoreModOnly")
+checkPropertyExists("usesShadowedDependencies")
+checkPropertyExists("developmentEnvironmentUserName")
+
+//Properties added in fork
+propertyDefaultIfUnset("skipBuildScriptUpdateCheck", false)
+propertyDefaultIfUnset("repositoryURL", "")
+propertyDefaultIfUnset("repositoryName", "")
+propertyDefaultIfUnset("mavenGroupId", "")
+propertyDefaultIfUnset("mavenArtifactId", "")
+propertyDefaultIfUnset("hasMixinDeps", false)
+propertyDefaultIfUnset("mixinConfigs", "")
+propertyDefaultIfUnset("mixinPluginPreInit", "")
+propertyDefaultIfUnset("mixinPluginMinimumVersion", "0.8.5")
+propertyDefaultIfUnset("remapStubs", false)
+
+propertyDefaultIfUnset("modrinthProjectId", "")
+propertyDefaultIfUnset("modrinthDependencies", "")
+propertyDefaultIfUnset("curseForgeProjectId", "")
+propertyDefaultIfUnset("curseForgeRelations", "")
+propertyDefaultIfUnset("changelog", "")
+
+propertyDefaultIfUnset("remoteMappings", "https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/")
+propertyDefaultIfUnset("mappingsChannel", "stable")
+propertyDefaultIfUnset("mappingsVersion", "12")
+
+String javaSourceDir = "src/main/java/"
+String scalaSourceDir = "src/main/scala/"
+String kotlinSourceDir = "src/main/kotlin/"
+
+String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/")
+String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/")
+String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/")
+if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
+ throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
+}
+
+if(apiPackage) {
+ targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
+ targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
+ targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
+ if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
+ throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
+ }
+}
+
+if(accessTransformersFile) {
+ String targetFile = "src/main/resources/META-INF/" + accessTransformersFile
+ if(!getFile(targetFile).exists()) {
+ throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile)
+ }
+}
+
+if(usesMixins.toBoolean()) {
+ if(mixinsPackage.isEmpty()) {
+ throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!")
+ }
+
+ targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
+ targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
+ targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
+ if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
+ throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
+ }
+
+ if (!mixinPlugin.isEmpty()) {
+ String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
+ String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala"
+ String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
+ String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".kt"
+ if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
+ throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
+ }
+ }
+}
+
+if(coreModClass) {
+ String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
+ String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala"
+ String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
+ String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".kt"
+ if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
+ throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
+ }
+}
+
+configurations.all {
+ resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
+
+ // Make sure GregTech build won't time out
+ System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String)
+ System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String)
+}
+
+// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version
+try {
+ 'git config core.fileMode false'.execute()
+}
+catch (Exception ignored) {
+ out.style(Style.Failure).println("git isn't installed at all")
+}
+
+// Pulls version first from the VERSION env and then git tag
+String identifiedVersion
+String versionOverride = System.getenv("VERSION") ?: null
+try {
+ identifiedVersion = versionOverride == null ? gitVersion() : versionOverride
+}
+catch (Exception ignored) {
+ out.style(Style.Failure).text(
+ 'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' +
+ 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' +
+ 'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)'
+ )
+ versionOverride = 'NO-GIT-TAG-SET'
+ identifiedVersion = versionOverride
+}
+version = identifiedVersion
+ext {
+ modVersion = identifiedVersion
+}
+
+if(identifiedVersion == versionOverride) {
+ out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7')
+}
+
+group = modGroup
+if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) {
+ archivesBaseName = customArchiveBaseName
+}
+else {
+ archivesBaseName = modId
+}
+archivesBaseName += "-mc" + minecraftVersion
+
+minecraft {
+ version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion
+ runDir = "run"
+
+ if (replaceGradleTokenInFile) {
+ for (file in replaceGradleTokenInFile.split(',')) {
+ replaceIn file
+ }
+ if(gradleTokenModId) {
+ replace gradleTokenModId, modId
+ }
+ if(gradleTokenModName) {
+ replace gradleTokenModName, modName
+ }
+ if(gradleTokenVersion) {
+ replace gradleTokenVersion, modVersion
+ }
+ if(gradleTokenGroupName) {
+ replace gradleTokenGroupName, modGroup
+ }
+ }
+}
+
+if(file("addon.gradle").exists()) {
+ apply from: "addon.gradle"
+}
+
+apply from: 'repositories.gradle'
+
+configurations {
+ for (config in [shadowImplementation, shadowCompile, shadeCompile]) {
+ implementation.extendsFrom(shadeCompile)
+ compileClasspath.extendsFrom(config)
+ runtimeClasspath.extendsFrom(config)
+ testCompileClasspath.extendsFrom(config)
+ testRuntimeClasspath.extendsFrom(config)
+ }
+}
+
+repositories {
+ maven {
+ name = "Overmind forge repo mirror"
+ url = "https://gregtech.overminddl1.com/"
+ }
+ if(usesMixins.toBoolean() || hasMixinDeps.toBoolean()) {
+ maven {
+ name = "sponge"
+ url = "https://mvn.falsepattern.com/releases"
+ }
+ maven {
+ name = "sponge2"
+ url = "https://mvn.falsepattern.com/sponge"
+ }
+ }
+}
+
+dependencies {
+ if(usesMixins.toBoolean()) {
+ annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3")
+ annotationProcessor("com.google.guava:guava:24.1.1-jre")
+ annotationProcessor("com.google.code.gson:gson:2.8.6")
+ annotationProcessor("com.llamalad7:MixinExtras:0.1.1-gasstation")
+ annotationProcessor("org.spongepowered:mixin:0.8.5-gasstation_7")
+ compile("org.spongepowered:mixin:0.8.5-gasstation_7")
+ compile("com.llamalad7:MixinExtras:0.1.1-gasstation")
+ compile("com.falsepattern:00gasstation-mc1.7.10:0.5.1:dev")
+ runtimeClasspath('org.jetbrains:intellij-fernflower:1.2.1.16')
+ testRuntimeClasspath('org.jetbrains:intellij-fernflower:1.2.1.16')
+ } else if(hasMixinDeps.toBoolean()) {
+ runtime("com.llamalad7:MixinExtras:0.1.1-gasstation")
+ runtime("org.spongepowered:mixin:0.8.5-gasstation_7")
+ runtime("com.falsepattern:00gasstation-mc1.7.10:0.5.1:dev")
+ }
+ // Latest LWJGL
+ compile "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209"
+ compile "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209"
+ minecraftNatives "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209"
+ minecraftDeps "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209"
+ minecraftDeps "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209"
+}
+
+apply from: 'dependencies.gradle'
+
+def mixinDir = new File(project.buildDir, 'mixins')
+if (!mixinDir.exists()) {
+ mixinDir.mkdirs()
+}
+def mixingConfigRefMap = "mixins." + modId + ".refmap.json"
+def srgFile = new File(project.buildDir, 'srgs/mcp-srg.srg')
+def mixinSrg = new File(mixinDir, "${mixingConfigRefMap}.srg")
+def mixinRefMap = new File(mixinDir, mixingConfigRefMap)
+
+task generateAssets {
+ if(usesMixins.toBoolean() && !mixinPlugin.isEmpty()) {
+ getFile("/src/main/resources/mixins." + modId + ".json").text = """{
+ "required": true,
+ "minVersion": "${mixinPluginMinimumVersion}",
+ "package": "${modGroup}.${mixinsPackage}",
+ "plugin": "${modGroup}.${mixinPlugin}",
+ "refmap": "${mixingConfigRefMap}",
+ "target": "@env(${mixinPluginPreInit.toBoolean() ? "PREINIT": "DEFAULT"})",
+ "compatibilityLevel": "JAVA_8"
+}
+
+"""
+ }
+}
+
+task relocateShadowJar(type: ConfigureShadowRelocation) {
+ target = tasks.shadowJar
+ prefix = modGroup + ".shadow"
+}
+
+shadowJar {
+ if (remapStubs.toBoolean()) {
+ dependsOn(removeStub)
+ }
+ project.configurations.shadeCompile.each { dep ->
+ from(project.zipTree(dep)) {
+ exclude 'META-INF', 'META-INF/**'
+ }
+ }
+
+ manifest {
+ attributes(getManifestAttributes())
+ }
+
+ minimize() // This will only allow shading for actually used classes
+ configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile]
+ dependsOn(relocateShadowJar)
+}
+
+jar {
+ if (remapStubs.toBoolean()) {
+ dependsOn(removeStub)
+ }
+ project.configurations.shadeCompile.each { dep ->
+ from(project.zipTree(dep)) {
+ exclude 'META-INF', 'META-INF/**'
+ }
+ }
+
+ manifest {
+ attributes(getManifestAttributes())
+ }
+
+ if(usesShadowedDependencies.toBoolean()) {
+ dependsOn(shadowJar)
+ enabled = false
+ }
+}
+
+reobf {
+ if(usesMixins.toBoolean()) {
+ addExtraSrgFile mixinSrg
+ }
+}
+
+if(usesMixins.toBoolean()) {
+ tasks.compileJava {
+ options.compilerArgs += [
+ '-Xlint:-processing',
+ "-AreobfSrgFile=${srgFile}",
+ "-AoutSrgFile=${mixinSrg}",
+ "-AoutRefMapFile=${mixinRefMap}"
+ ]
+ }
+}
+
+runClient {
+ def arguments = []
+ def jvmArguments = []
+
+ if (usesMixins.toBoolean()) {
+ arguments += [
+ "--mods=" + Paths.get("$projectDir").resolve(minecraft.runDir).normalize().relativize(Paths.get("$projectDir/build/libs/$archivesBaseName-${version}.jar"))
+ ]
+ }
+
+ if(usesMixins.toBoolean() || hasMixinDeps.toBoolean()) {
+ arguments += [
+ "--tweakClass", "org.spongepowered.asm.launch.MixinTweaker"
+ ]
+ jvmArguments += [
+ "-Dmixin.debug=true", "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true"
+ ]
+ }
+
+ if(developmentEnvironmentUserName) {
+ arguments += [
+ "--username",
+ developmentEnvironmentUserName
+ ]
+ }
+
+ args(arguments)
+ jvmArgs(jvmArguments)
+}
+
+runServer {
+ def arguments = []
+ def jvmArguments = []
+
+ if (usesMixins.toBoolean()) {
+ arguments += [
+ "--mods=" + Paths.get("$projectDir").resolve(minecraft.runDir).normalize().relativize(Paths.get("$projectDir/build/libs/$archivesBaseName-${version}.jar"))
+ ]
+ }
+
+ if (usesMixins.toBoolean() || hasMixinDeps.toBoolean()) {
+ arguments += [
+ "--tweakClass", "org.spongepowered.asm.launch.MixinTweaker"
+ ]
+ jvmArguments += [
+ "-Dmixin.debug=true", "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true"
+ ]
+ }
+
+ args(arguments)
+ jvmArgs(jvmArguments)
+}
+
+tasks.withType(JavaExec).configureEach {
+ javaLauncher.set(
+ javaToolchains.launcherFor {
+ languageVersion = projectJavaVersion
+ }
+ )
+}
+
+processResources {
+ // this will ensure that this task is redone when the versions change.
+ inputs.property "version", project.version
+ inputs.property "mcversion", project.minecraft.version
+
+ // replace stuff in mcmod.info, nothing else
+ from(sourceSets.main.resources.srcDirs) {
+ include 'mcmod.info'
+
+ // replace modVersion and minecraftVersion
+ expand "minecraftVersion": project.minecraft.version,
+ "modVersion": modVersion,
+ "modId": modId,
+ "modName": modName
+ }
+
+ if(usesMixins.toBoolean()) {
+ from mixinRefMap
+ }
+
+ // copy everything else that's not the mcmod.info
+ from(sourceSets.main.resources.srcDirs) {
+ exclude 'mcmod.info'
+ }
+}
+
+def getManifestAttributes() {
+ def manifestAttributes = [:]
+ if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) {
+ manifestAttributes += ["FMLCorePluginContainsFMLMod": true]
+ }
+
+ if(accessTransformersFile) {
+ manifestAttributes += ["FMLAT" : accessTransformersFile.toString()]
+ }
+
+ if(coreModClass) {
+ manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass]
+ }
+
+ if(usesMixins.toBoolean()) {
+ String[] configs = [];
+ if (!mixinPlugin.isEmpty()) {
+ configs += ["mixins.${modId}.json"];
+ }
+ if (!mixinConfigs.isEmpty()) {
+ configs += [mixinConfigs];
+ }
+ manifestAttributes += [
+ "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker",
+ "MixinConfigs" : String.join(",", configs),
+ "ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean()
+ ]
+ }
+ return manifestAttributes
+}
+
+task sourcesJar(type: Jar) {
+ from (sourceSets.main.allSource)
+ from (file("$projectDir/LICENSE"))
+ getArchiveClassifier().set('sources')
+}
+
+task shadowDevJar(type: ShadowJar) {
+ if (remapStubs.toBoolean()) {
+ dependsOn(removeStub)
+ }
+ project.configurations.shadeCompile.each { dep ->
+ from(project.zipTree(dep)) {
+ exclude 'META-INF', 'META-INF/**'
+ }
+ }
+
+ from sourceSets.main.output
+ getArchiveClassifier().set("dev")
+
+ manifest {
+ attributes(getManifestAttributes())
+ }
+
+ minimize() // This will only allow shading for actually used classes
+ configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile]
+}
+
+task relocateShadowDevJar(type: ConfigureShadowRelocation) {
+ target = tasks.shadowDevJar
+ prefix = modGroup + ".shadow"
+}
+
+task circularResolverJar(type: Jar) {
+ dependsOn(relocateShadowDevJar)
+ dependsOn(shadowDevJar)
+ enabled = false
+}
+
+task devJar(type: Jar) {
+ if (remapStubs.toBoolean()) {
+ dependsOn(removeStub)
+ }
+ project.configurations.shadeCompile.each { dep ->
+ from(project.zipTree(dep)) {
+ exclude 'META-INF', 'META-INF/**'
+ }
+ }
+
+ from sourceSets.main.output
+ getArchiveClassifier().set("dev")
+
+ manifest {
+ attributes(getManifestAttributes())
+ }
+
+ if(usesShadowedDependencies.toBoolean()) {
+ dependsOn(circularResolverJar)
+ enabled = false
+ }
+}
+
+task apiJar(type: Jar) {
+ from (sourceSets.main.allSource) {
+ include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
+ }
+
+ from (sourceSets.main.output) {
+ include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
+ }
+
+ from (sourceSets.main.resources.srcDirs) {
+ include("LICENSE")
+ }
+
+ getArchiveClassifier().set('api')
+}
+
+task copySrgs(type: Copy, dependsOn: 'genSrgs') {
+ from plugins.getPlugin('forge').delayedFile('{SRG_DIR}')
+ include '**/*.srg'
+ into layout.buildDirectory.file('srgs')
+}
+
+compileJava.dependsOn(copySrgs)
+
+artifacts {
+ archives sourcesJar
+ archives devJar
+ if(apiPackage) {
+ archives apiJar
+ }
+}
+
+// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID),
+// and isn't strictly needed with the POM so just disable it.
+tasks.withType(GenerateModuleMetadata) {
+ enabled = false
+}
+
+// workaround variable hiding in pom processing
+def projectConfigs = project.configurations
+
+// publishing
+
+def getMavenSettingsCredentials = {
+ String userHome = System.getProperty( "user.home" );
+ File mavenSettings = new File(userHome, ".m2/settings.xml")
+ def xmlSlurper = new XmlSlurper()
+ def output = xmlSlurper.parse(mavenSettings)
+ return output."servers"."server"
+}
+
+def getCredentials = {
+ String username = System.getenv("MAVEN_DEPLOY_USER")
+ String password = System.getenv("MAVEN_DEPLOY_PASSWORD")
+ if (username == null) {
+ try {
+ def entries = getMavenSettingsCredentials()
+ for (entry in entries) {
+ if (entry."id".text() == repositoryName) {
+ return [username: entry.username.text(), password: entry.password.text()]
+ }
+ }
+ } catch (Exception ignored){}
+ return [username: "none", password: "none"]
+ } else {
+ return [username: username, password: password]
+ }
+}
+
+//Publishing
+publishing {
+ publications {
+ maven(MavenPublication) {
+ from components.java
+ if (usesShadowedDependencies.toBoolean()) {
+ artifact source: shadowJar, classifier: ""
+ }
+ if (!project.hasProperty("noPublishedSources") || !noPublishedSources) {
+ artifact source: sourcesJar, classifier: "sources"
+ }
+ artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev"
+ if (apiPackage) {
+ artifact source: apiJar, classifier: "api"
+ }
+
+ groupId = mavenGroupId
+ artifactId = mavenArtifactId + "-mc" + minecraftVersion
+ version = modVersion
+
+ // remove extra garbage from minecraft and minecraftDeps configuration
+ pom.withXml {
+ def badArtifacts = [:].withDefault {[] as Set}
+ for (configuration in [projectConfigs.minecraft, projectConfigs.minecraftDeps]) {
+ for (dependency in configuration.allDependencies) {
+ badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name
+ }
+ }
+ // example for specifying extra stuff to ignore
+ // badArtifacts["org.example.group"] += "artifactName"
+
+ Node pomNode = asNode()
+ pomNode.dependencies.'*'.findAll() {
+ badArtifacts[it.groupId.text()].contains(it.artifactId.text())
+ }.each() {
+ it.parent().remove(it)
+ }
+ }
+ }
+ }
+
+ repositories {
+ if (repositoryURL.trim() != "") {
+ maven {
+ name = repositoryName
+ url = repositoryURL
+ def creds = getCredentials()
+ credentials {
+ username = creds?.username ?: "none"
+ password = creds?.password ?: "none"
+ }
+ }
+ }
+ }
+}
+
+tasks.withType(PublishToMavenRepository) { task ->
+ dependsOn("build")
+}
+
+publishToMavenLocal.dependsOn("build")
+
+if (project.changelog == "") {
+ File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md")
+ if (changelogFile.exists()) {
+ project.changelog = changelogFile.getText("UTF-8")
+ } else {
+ project.changelog = "No changelog was provided."
+ }
+}
+project.changelog = project.changelog.replace("{version}", modVersion)
+
+if (curseForgeProjectId != "" && System.getenv("CURSEFORGE_TOKEN") != null) {
+ apply plugin: 'com.matthewprenger.cursegradle'
+ curseforge {
+ apiKey = System.getenv("CURSEFORGE_TOKEN")
+ project {
+ id = curseForgeProjectId
+ changelogType = "markdown"
+ changelog = project.changelog
+ releaseType = modVersion.contains("-a") ? "alpha" : modVersion.contains("-b") ? "beta" : "release"
+ addGameVersion project.minecraft.version
+ addGameVersion "Forge"
+ mainArtifact(jar) {
+ displayName = "$modName version: $modVersion"
+ }
+ }
+ options {
+ javaIntegration = false
+ forgeGradleIntegration = false
+ }
+ }
+ if (curseForgeRelations.size() != 0) {
+ String[] deps = curseForgeRelations.split(";")
+ deps.each { dep ->
+ if (dep.size() == 0) {
+ return
+ }
+ String[] parts = dep.split(":")
+ String type = parts[0]
+ String name = parts[1]
+ addCurseForgeRelation(type, name)
+ }
+ }
+
+ if (usesMixins.toBoolean()) {
+ addCurseForgeRelation("requiredDependency", "gasstation")
+ }
+ tasks.curseforge.dependsOn(build)
+ tasks.publish.dependsOn(tasks.curseforge)
+}
+
+if (modrinthProjectId != "" && System.getenv("MODRINTH_TOKEN") != null) {
+ apply plugin: 'com.modrinth.minotaur'
+ modrinth {
+ token = System.getenv("MODRINTH_TOKEN")
+ projectId = modrinthProjectId
+ versionNumber = modVersion
+ versionType = modVersion.contains("-a") ? "alpha" : modVersion.contains("-b") ? "beta" : "release"
+ changelog = project.changelog
+ uploadFile = jar
+ gameVersions = [project.minecraft.version]
+ loaders = ["forge"]
+ }
+ if (modrinthDependencies.size() != 0) {
+ String[] deps = modrinthDependencies.split(";")
+ deps.each { dep ->
+ if (dep.size() == 0) {
+ return
+ }
+ String[] parts = dep.split(":")
+ String[] qual = parts[0].split("-")
+ String scope = qual[0]
+ String type = qual[1]
+ String name = parts[1]
+ addModrinthDep(scope, type, name)
+ }
+ }
+ if (usesMixins.toBoolean()) {
+ addModrinthDep("required", "project", "cdeAhgfp")
+ }
+ tasks.modrinth.dependsOn(build)
+ tasks.publish.dependsOn(tasks.modrinth)
+}
+
+def addModrinthDep(scope, type, name) {
+ com.modrinth.minotaur.dependencies.Dependency dep;
+ if (!(scope in ["required", "optional", "incompatible", "embedded"])) {
+ throw new Exception("Invalid modrinth dependency scope: " + scope)
+ }
+ switch (type) {
+ case "project":
+ dep = new ModDependency(name, scope)
+ break
+ case "version":
+ dep = new VersionDependency(name, scope)
+ break
+ default:
+ throw new Exception("Invalid modrinth dependency type: " + type)
+ }
+ project.modrinth.dependencies.add(dep)
+}
+
+def addCurseForgeRelation(type, name) {
+ if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) {
+ throw new Exception("Invalid CurseForge relation type: " + type)
+ }
+ CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact
+ CurseRelation rel = (artifact.curseRelations ?: (artifact.curseRelations = new CurseRelation()))
+ rel."$type"(name)
+}
+
+// Updating
+task updateBuildScript {
+ doLast {
+ if (performBuildScriptUpdate(projectDir.toString())) return
+
+ print("Build script already up-to-date!")
+ }
+}
+
+if (!project.getGradle().startParameter.isOffline() && !skipBuildScriptUpdateCheck.toBoolean() && isNewBuildScriptVersionAvailable(projectDir.toString())) {
+ if (autoUpdateBuildScript.toBoolean()) {
+ performBuildScriptUpdate(projectDir.toString())
+ } else {
+ out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'")
+ }
+}
+
+static URL availableBuildScriptUrl() {
+ new URL("https://raw.githubusercontent.com/FalsePattern/ExampleMod1.7.10/main/build.gradle")
+}
+
+boolean performBuildScriptUpdate(String projectDir) {
+ if (isNewBuildScriptVersionAvailable(projectDir)) {
+ def buildscriptFile = getFile("build.gradle")
+ availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } }
+ out.println("Build script updated. Please REIMPORT the project or RESTART your IDE!")
+ return true
+ }
+ return false
+}
+
+boolean isNewBuildScriptVersionAvailable(String projectDir) {
+ Map parameters = ["connectTimeout": 2000, "readTimeout": 2000]
+
+ String currentBuildScript = getFile("build.gradle").getText()
+ String currentBuildScriptHash = getVersionHash(currentBuildScript)
+ String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
+ String availableBuildScriptHash = getVersionHash(availableBuildScript)
+
+ boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash
+ return !isUpToDate
+}
+
+static String getVersionHash(String buildScriptContent) {
+ String versionLine = buildScriptContent.find("^//version: [a-z0-9]*")
+ if(versionLine != null) {
+ return versionLine.split(": ").last()
+ }
+ return ""
+}
+
+configure(updateBuildScript) {
+ group = 'forgegradle'
+ description = 'Updates the build script to the latest version'
+}
+
+// Parameter Deobfuscation
+
+task deobfParams {
+ doLast {
+
+ String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$mappingsChannel/$mappingsVersion"
+ String mcpZIP = "$mcpDir/mcp_$mappingsChannel-$mappingsVersion-${minecraftVersion}.zip"
+ String paramsCSV = "$mcpDir/params.csv"
+
+ download.run {
+ src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$mappingsChannel/$mappingsVersion-$minecraftVersion/mcp_$mappingsChannel-$mappingsVersion-${minecraftVersion}.zip"
+ dest mcpZIP
+ overwrite false
+ }
+
+ if(!file(paramsCSV).exists()) {
+ println("Extracting MCP archive ...")
+ unzip(mcpZIP, mcpDir)
+ }
+
+ println("Parsing params.csv ...")
+ Map params = new HashMap<>()
+ Files.lines(Paths.get(paramsCSV)).forEach{line ->
+ String[] cells = line.split(",")
+ if(cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) {
+ params.put(cells[0], cells[1])
+ }
+ }
+
+ out.style(Style.Success).println("Modified ${replaceParams(file("$projectDir/src/main/java"), params)} files!")
+ out.style(Style.Failure).println("Don't forget to verify that the code still works as before!\n It could be broken due to duplicate variables existing now\n or parameters taking priority over other variables.")
+ }
+}
+
+static int replaceParams(File file, Map params) {
+ int fileCount = 0
+
+ if(file.isDirectory()) {
+ for(File f : file.listFiles()) {
+ fileCount += replaceParams(f, params)
+ }
+ return fileCount
+ }
+ println("Visiting ${file.getName()} ...")
+ try {
+ String content = new String(Files.readAllBytes(file.toPath()))
+ int hash = content.hashCode()
+ params.forEach{key, value ->
+ content = content.replaceAll(key, value)
+ }
+ if(hash != content.hashCode()) {
+ Files.write(file.toPath(), content.getBytes("UTF-8"))
+ return 1
+ }
+ } catch(Exception e) {
+ e.printStackTrace()
+ }
+ return 0
+}
+
+// Credit: bitsnaps (https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681)
+static unzip(String zipFileName, String outputDir) {
+ byte[] buffer = new byte[16384]
+ ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName))
+ ZipEntry zipEntry = zis.getNextEntry()
+ while (zipEntry != null) {
+ File newFile = new File(outputDir + File.separator, zipEntry.name)
+ if (zipEntry.isDirectory()) {
+ if (!newFile.isDirectory() && !newFile.mkdirs()) {
+ throw new IOException("Failed to create directory $newFile")
+ }
+ } else {
+ // fix for Windows-created archives
+ File parent = newFile.parentFile
+ if (!parent.isDirectory() && !parent.mkdirs()) {
+ throw new IOException("Failed to create directory $parent")
+ }
+ // write file content
+ FileOutputStream fos = new FileOutputStream(newFile)
+ int len = 0
+ while ((len = zis.read(buffer)) > 0) {
+ fos.write(buffer, 0, len)
+ }
+ fos.close()
+ }
+ zipEntry = zis.getNextEntry()
+ }
+ zis.closeEntry()
+ zis.close()
+}
+
+configure(deobfParams) {
+ group = 'forgegradle'
+ description = 'Rename all obfuscated parameter names inherited from Minecraft classes'
+}
+
+// Dependency Deobfuscation
+
+def deobfMaven(mavenDep) {
+ throw new GradleException("deobfMaven(mavenDep) is deprecated. " +
+ "You must use the new deobfMaven(repoURL, mavenDep) method instead." +
+ "The old method broke the buildscript when used.")
+}
+
+def deobfMaven(String repoURL, String mavenDep) {
+ if (!repoURL.endsWith("/")) {
+ repoURL += "/"
+ }
+ String[] parts = mavenDep.split(":")
+ parts[0] = parts[0].replace('.', '/')
+ def jarURL = repoURL + parts[0] + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar"
+ return deobf(jarURL)
+}
+
+def deobf(String sourceURL) {
+ try {
+ URL url = new URL(sourceURL)
+ String fileName = url.getFile()
+
+ //get rid of directories:
+ int lastSlash = fileName.lastIndexOf("/")
+ if(lastSlash > 0) {
+ fileName = fileName.substring(lastSlash + 1)
+ }
+ //get rid of extension:
+ if(fileName.endsWith(".jar") || fileName.endsWith(".litemod")) {
+ fileName = fileName.substring(0, fileName.lastIndexOf("."))
+ }
+
+ String hostName = url.getHost()
+ if(hostName.startsWith("www.")) {
+ hostName = hostName.substring(4)
+ }
+ List parts = Arrays.asList(hostName.split("\\."))
+ Collections.reverse(parts)
+ hostName = String.join(".", parts)
+
+ return deobf(sourceURL, "$hostName/$fileName")
+ } catch(Exception e) {
+ return deobf(sourceURL, "deobf/${sourceURL.hashCode()}")
+ }
+}
+
+// The method above is to be preferred. Use this method if the filename is not at the end of the URL.
+def deobf(String sourceURL, String rawFileName) {
+ String bon2Version = "2.5.1"
+ String fileName = URLDecoder.decode(rawFileName, "UTF-8")
+ String cacheDir = "$project.gradle.gradleUserHomeDir/caches"
+ String bon2Dir = "$cacheDir/forge_gradle/deobf"
+ String bon2File = "$bon2Dir/BON2-${bon2Version}.jar"
+ String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar"
+ String deobfFile = "$cacheDir/modules-2/files-2.1/${fileName}-deobf.jar"
+
+ if(file(deobfFile).exists()) {
+ return files(deobfFile)
+ }
+
+ String mappingsVer
+ if(remoteMappings) {
+ String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion"
+ String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip"
+
+ zipMappings(mappingsZIP, remoteMappings, bon2Dir)
+
+ mappingsVer = "snapshot_$id"
+ } else {
+ mappingsVer = "${mappingsChannel}_$mappingsVersion"
+ }
+
+ download.run {
+ src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-CUSTOM-all.jar"
+ dest bon2File
+ quiet true
+ overwrite false
+ }
+
+ download.run {
+ src sourceURL
+ dest obfFile
+ quiet true
+ overwrite false
+ }
+
+ exec {
+ commandLine Paths.get(System.getProperty("java.home"), "bin", "java").toAbsolutePath().toString(), '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch'
+ workingDir bon2Dir
+ standardOutput = new FileOutputStream("${deobfFile}.log")
+ }
+
+ return files(deobfFile)
+}
+
+def zipMappings(String zipPath, String url, String bon2Dir) {
+ File zipFile = new File(zipPath)
+ if(zipFile.exists()) {
+ return
+ }
+
+ String fieldsCache = "$bon2Dir/data/fields.csv"
+ String methodsCache = "$bon2Dir/data/methods.csv"
+
+ download.run {
+ src "${url}fields.csv"
+ dest fieldsCache
+ quiet true
+ }
+ download.run {
+ src "${url}methods.csv"
+ dest methodsCache
+ quiet true
+ }
+
+ zipFile.getParentFile().mkdirs()
+ ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))
+
+ zos.putNextEntry(new ZipEntry("fields.csv"))
+ Files.copy(Paths.get(fieldsCache), zos)
+ zos.closeEntry()
+
+ zos.putNextEntry(new ZipEntry("methods.csv"))
+ Files.copy(Paths.get(methodsCache), zos)
+ zos.closeEntry()
+
+ zos.close()
+}
+
+// Helper methods
+
+def checkPropertyExists(String propertyName) {
+ if (!project.hasProperty(propertyName)) {
+ throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/FalsePattern/ExampleMod1.7.10/blob/main/gradle.properties")
+ }
+}
+
+def propertyDefaultIfUnset(String propertyName, defaultValue) {
+ if (!project.hasProperty(propertyName)) {
+ System.err.println("Your gradle.properties is missing the $propertyName entry. It has been automatically set to \"$defaultValue\" as fallback. You can find all properties and their description here: https://github.com/FalsePattern/ExampleMod1.7.10/blob/main/gradle.properties")
+ }
+ if (!project.hasProperty(propertyName) || project.property(propertyName) == "") {
+ project.ext.setProperty(propertyName, defaultValue)
+ }
+}
+
+def getFile(String relativePath) {
+ return new File(projectDir, relativePath)
+}
+
+if(file("addon_final.gradle").exists()) {
+ apply from: "addon_final.gradle"
+}
\ No newline at end of file
diff --git a/dependencies.gradle b/dependencies.gradle
new file mode 100644
index 0000000..2c40c12
--- /dev/null
+++ b/dependencies.gradle
@@ -0,0 +1,9 @@
+dependencies {
+ compileOnly("org.projectlombok:lombok:[1.18.24,1.19)") {
+ transitive = false
+ }
+ annotationProcessor("org.projectlombok:lombok:[1.18.24,1.19)")
+
+ implementation("com.falsepattern:falsepatternlib-mc1.7.10:[0.10.15,0.11):dev")
+
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..518680d
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,214 @@
+# Mod settings
+#region mod
+
+modName = ChunkAPI
+
+# This is a case-sensitive string to identify your mod. Convention is to use lower case.
+modId = fplib_chunkapi
+
+# The "root package" of your mod. All of your mod classes *should* be placed under this package for simplicity.
+modGroup = com.falsepattern.chunk
+
+# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can
+# leave this property empty.
+# Example value: apiPackage = api + modGroup = com.falsepattern.chunk -> com.falsepattern.chunk.api
+apiPackage = api
+
+# WHY is there no version field?
+# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the
+# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/
+# However, if you really want to, you can use the VERSION environment variable to override this.
+
+minecraftVersion = 1.7.10
+forgeVersion = 10.13.4.1614
+
+# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you
+# restart Minecraft in development. Choose this dependent on your mod:
+# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name
+# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty
+developmentEnvironmentUserName = Developer
+
+#endregion mod
+
+# Publishing settings
+#region publishing
+
+# Note: Both the modrinth and the curseforge publications are invoked by the "publish" gradle task
+# (when the respective publication's project ID is set up correctly, of course). You don't need to individually run
+# each of them.
+
+# Maven publishing
+#region maven
+
+# The maven server to upload the artifacts to
+repositoryURL = https://mvn.falsepattern.com/releases/
+
+# What name is the login information inside ~/.m2/settings.xml stored under
+# (see https://gist.github.com/FalsePattern/82d93e3cfab01f671cc5f4a95931cfe3 for an example)
+# You can also use the MAVEN_DEPLOY_USER and MAVEN_DEPLOY_PASSWORD environment variables to set this information!
+repositoryName = mavenpattern
+
+# What the artifact should be called. These will be the "name" of the published package, suffixed with the minecraft
+# version with a -mc prefix (groupid:artifactid-mcminecraftVersion:version:qualifier).
+# For instance, the default values this example ships with would turn into com.falsepattern:mymodid-mc1.7.10:version
+# The version is determined automatically from the git version.
+mavenGroupId = com.falsepattern
+mavenArtifactId = chunkapi
+
+#endregion maven
+
+# Modrinth publishing
+#region modrinth
+
+# Publishing to modrinth requires you to set the MODRINTH_TOKEN environment variable to your current modrinth API token.
+
+# The project's ID on Modrinth. Can be either the slug or the ID.
+# Leave this empty if you don't want to publish on Modrinth.
+modrinthProjectId =
+
+# The project's dependencies on Modrinth. You can use this to refer to other projects on Modrinth.
+# Syntax: scope1-type1:name1;scope2-type2:name2;...
+# Where scope can be one of [required, optional, incompatible, embedded],
+# type can be one of [project, version],
+# and the name is the Modrinth project or version slug/id of the other mod.
+# Example: required-project:fplib;incompatible-project:gregtech
+# Note: GasStation is automatically set as a required dependency if usesMixins = true
+modrinthDependencies =
+
+#endregion modrinth
+
+# CurseForge publishing
+#region curseforge
+
+# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens.
+
+# The project's numeric ID on CurseForge. You can find this in the About Project box.
+# Leave this empty if you don't want to publish on CurseForge.
+curseForgeProjectId =
+
+# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge.
+# Syntax: type1:name1;type2:name2;...
+# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible],
+# and the name is the CurseForge project id of the other mod.
+# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft
+# Note: GasStation is automatically set as a required dependency if usesMixins = true
+curseForgeRelations =
+
+#endregion curseforge
+
+# This will be inserted as the changelog text in the Modrinth/CurseForge publications.
+# If the text contains "{version}", it will be replaced with the current mod version. This is useful when the changelog
+# is just a URL pointing to a GitHub release tag.
+# If left empty, the changelog will be attempted to be read from the file at the CHANGELOG_FILE environment variable,
+# or the CHANGELOG.md file in the project root if the variable is not set.
+# If neither this property, nor the file, nor the environment variable (or the file it points to) exist, the changelog
+# will be set to "No changelog was provided.".
+# Example: https://github.com/myname/mymod/releases/tag/{version}
+changelog =
+
+# endregion publishing
+
+# Buildscript automatic update checker settings
+#region autoupdates
+
+# Will update your build.gradle automatically whenever an update is available
+autoUpdateBuildScript = false
+# Disable checking of buildscript updates.
+skipBuildScriptUpdateCheck = false
+
+#endregion autoupdates
+
+# Gradle token strings
+#region gradletokens
+
+# Define a source file of your project with:
+# public static final String VERSION = "GRADLETOKEN_VERSION";
+# The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's
+# version in @Mod([...], version = VERSION, [...])
+# Leave these properties empty to skip individual token replacements
+# Multiple source files can be defined here by providing a comma-seperated list: Class1.java,Class2.java,Class3.java
+replaceGradleTokenInFile = Tags.java
+gradleTokenModId = GRADLETOKEN_MODID
+gradleTokenModName = GRADLETOKEN_MODNAME
+gradleTokenVersion = GRADLETOKEN_VERSION
+gradleTokenGroupName = GRADLETOKEN_GROUPNAME
+
+#endregion gradletokens
+
+# Mixins
+#region mixins
+
+# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
+# When this is enabled, the mixinPlugin, mixinPluginPreInit, mixinsPackage, and mixinConfigs properties become active.
+usesMixins = true
+# Enable this if one of the dependencies uses mixins. Note: if usesMixins is true, this property is ignored. Only use this
+# if a dependency requires mixins BUT this mod doesn't.
+hasMixinDeps = false
+# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
+mixinPlugin = mixin.plugin.MixinPlugin
+# Whether you want the plugin to be configured as a PREINIT mixin
+mixinPluginPreInit = false
+# The minimum SpongePowered Mixins version required by the plugin. Internal default is 0.8.5 (GasStation)
+mixinPluginMinimumVersion =
+# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
+mixinsPackage = mixin.mixins
+# Specify any custom mixin .json configs here. If you have multiple, comma-separate them. If you don't want to load
+# any jsons manually, leave this empty. You can use custom configs even if you already have a plugin added.
+# note: mixins..json is used by the mixinPlugin's autogenerated config. Additionally, the refmap from the mixinsPackage
+# is always put into mixins..refmap.json.
+# example: mixins.foo.json,mixins.bar.json
+mixinConfigs =
+
+#endregion mixins
+
+# Coremod and access transformers
+#region core
+
+# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/
+# Example value: mymodid_at.cfg
+accessTransformersFile =
+
+# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
+# This parameter is for legacy compatibility only
+# Example value: coreModClass = asm.FMLPlugin + modGroup = com.falsepattern.chunk -> com.falsepattern.chunk.asm.FMLPlugin
+coreModClass =
+
+#endregion core
+
+# Dependency deobfuscation settings (advanced)
+#region ddeobf
+
+# These 3 entries specify the location where the SRG mappings should be fetched from. Only set these if you know
+# what you're doing. The defaults inside the buildscript should just work without any extra configuration.
+remoteMappings =
+mappingsChannel =
+mappingsVersion =
+
+#endregion ddeobf
+
+# Miscellaneous settings
+#region misc
+
+# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
+# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
+containsMixinsAndOrCoreModOnly = false
+
+# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated in your jar. It is your
+# responsibility check the licence and request permission for distribution, if required.
+usesShadowedDependencies = false
+
+# If enabled, class stubbing will be enabled. In this mode, all classes with a package named "stubpackage" in their
+# path will be removed, and all classes that refer to said classes will be modified so that the "stubpackage" will map
+# to the root package instead. This is useful for referring to compile-time inaccessible classes, such as classes in the
+# default package
+remapStubs = false
+
+# Set this to true if you want to publish a proprietary mod without visible source code.
+#noPublishedSources =
+
+# Optional parameter to customize the produced artifacts. Use this to preserver artifact naming when migrating older
+# projects. New projects should not use this parameter.
+#customArchiveBaseName =
+
+#endregion misc
+
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..5c2d1cf
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..3ab0b72
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..83f2acf
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,188 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# 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
+#
+# https://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.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..9618d8d
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,100 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/repositories.gradle b/repositories.gradle
new file mode 100644
index 0000000..b79651c
--- /dev/null
+++ b/repositories.gradle
@@ -0,0 +1,6 @@
+repositories {
+ maven {
+ name = "mvnpattern"
+ url = "https://mvn.falsepattern.com/releases"
+ }
+}
diff --git a/src/main/java/com/falsepattern/chunk/ChunkAPI.java b/src/main/java/com/falsepattern/chunk/ChunkAPI.java
new file mode 100644
index 0000000..17ee8f6
--- /dev/null
+++ b/src/main/java/com/falsepattern/chunk/ChunkAPI.java
@@ -0,0 +1,11 @@
+package com.falsepattern.chunk;
+
+import cpw.mods.fml.common.Mod;
+
+@Mod(modid = Tags.MODID,
+ version = Tags.VERSION,
+ name = Tags.MODNAME,
+ acceptedMinecraftVersions = "[1.7.10]",
+ dependencies = "required-after:falsepatternlib@[0.10.15,);")
+public class ChunkAPI {
+}
\ No newline at end of file
diff --git a/src/main/java/com/falsepattern/chunk/Common.java b/src/main/java/com/falsepattern/chunk/Common.java
new file mode 100644
index 0000000..f2152f3
--- /dev/null
+++ b/src/main/java/com/falsepattern/chunk/Common.java
@@ -0,0 +1,11 @@
+package com.falsepattern.chunk;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * Non-minecraft stuff to avoid accidental classloading in spaghetti code
+ */
+public class Common {
+ public static final Logger LOG = LogManager.getLogger(Tags.MODID);
+}
diff --git a/src/main/java/com/falsepattern/chunk/Tags.java b/src/main/java/com/falsepattern/chunk/Tags.java
new file mode 100644
index 0000000..46e1f2b
--- /dev/null
+++ b/src/main/java/com/falsepattern/chunk/Tags.java
@@ -0,0 +1,8 @@
+package com.falsepattern.chunk;
+
+public class Tags {
+ public static final String MODID = "GRADLETOKEN_MODID";
+ public static final String MODNAME = "GRADLETOKEN_MODNAME";
+ public static final String VERSION = "GRADLETOKEN_VERSION";
+ public static final String GROUPNAME = "GRADLETOKEN_GROUPNAME";
+}
\ No newline at end of file
diff --git a/src/main/java/com/falsepattern/chunk/mixin/plugin/Mixin.java b/src/main/java/com/falsepattern/chunk/mixin/plugin/Mixin.java
new file mode 100644
index 0000000..b376a4b
--- /dev/null
+++ b/src/main/java/com/falsepattern/chunk/mixin/plugin/Mixin.java
@@ -0,0 +1,47 @@
+/*
+ * FalseTweaks
+ *
+ * Copyright (C) 2022 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice, this permission notice and the word "SNEED"
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.falsepattern.chunk.mixin.plugin;
+
+import com.falsepattern.lib.mixin.IMixin;
+import com.falsepattern.lib.mixin.ITargetedMod;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+@RequiredArgsConstructor
+public enum Mixin implements IMixin {
+ // @formatter:off
+ ;
+ // @formatter:on
+
+ @Getter
+ private final Side side;
+ @Getter
+ private final Predicate> filter;
+ @Getter
+ private final String mixin;
+}
+
diff --git a/src/main/java/com/falsepattern/chunk/mixin/plugin/MixinPlugin.java b/src/main/java/com/falsepattern/chunk/mixin/plugin/MixinPlugin.java
new file mode 100644
index 0000000..32edb43
--- /dev/null
+++ b/src/main/java/com/falsepattern/chunk/mixin/plugin/MixinPlugin.java
@@ -0,0 +1,46 @@
+/*
+ * FalseTweaks
+ *
+ * Copyright (C) 2022 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice, this permission notice and the word "SNEED"
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.falsepattern.chunk.mixin.plugin;
+
+import com.falsepattern.chunk.Tags;
+import com.falsepattern.lib.mixin.IMixin;
+import com.falsepattern.lib.mixin.IMixinPlugin;
+import com.falsepattern.lib.mixin.ITargetedMod;
+import lombok.Getter;
+import org.apache.logging.log4j.Logger;
+
+public class MixinPlugin implements IMixinPlugin {
+ @Getter
+ private final Logger logger = IMixinPlugin.createLogger(Tags.MODNAME);
+
+ @Override
+ public ITargetedMod[] getTargetedModEnumValues() {
+ return TargetedMod.values();
+ }
+
+ @Override
+ public IMixin[] getMixinEnumValues() {
+ return Mixin.values();
+ }
+}
diff --git a/src/main/java/com/falsepattern/chunk/mixin/plugin/TargetedMod.java b/src/main/java/com/falsepattern/chunk/mixin/plugin/TargetedMod.java
new file mode 100644
index 0000000..2ba3f0a
--- /dev/null
+++ b/src/main/java/com/falsepattern/chunk/mixin/plugin/TargetedMod.java
@@ -0,0 +1,42 @@
+/*
+ * FalseTweaks
+ *
+ * Copyright (C) 2022 FalsePattern
+ * All Rights Reserved
+ *
+ * The above copyright notice, this permission notice and the word "SNEED"
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.falsepattern.chunk.mixin.plugin;
+
+import com.falsepattern.lib.mixin.ITargetedMod;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.function.Predicate;
+
+@RequiredArgsConstructor
+public enum TargetedMod implements ITargetedMod {
+ ;
+
+ @Getter
+ private final String modName;
+ @Getter
+ private final boolean loadInDevelopment;
+ @Getter
+ private final Predicate condition;
+}
diff --git a/src/main/resources/LICENSE b/src/main/resources/LICENSE
new file mode 100644
index 0000000..cf3b250
--- /dev/null
+++ b/src/main/resources/LICENSE
@@ -0,0 +1,63 @@
+#-------------------------------------------------------------------------------
+# @author FalsePattern
+#
+# Copyright 2023
+#
+# All rights reserved.
+# Distribution of the software in any form is only allowed with
+# explicit, prior permission from the owner.
+#-------------------------------------------------------------------------------
+@author FalsePattern
+
+
+This code is the property of and owned and copyrighted by FalsePattern.
+This code is provided under a modified visible-source license
+that is as follows:
+
+
+API Code:
+==============================
+API code is identifiable as being in an "API" package in the respective
+repository or mod, and is intended to allow some level of inter-mod
+interactions without creating hard dependencies on the mod proper. This code
+is exempt from the below restrictions for "Mod Code", as it by nature will
+require some level of copying and redistribution.
+
+The only restrictions imposed on API code are that it remain clearly marked
+with its original authorship and source, that it be used for the purpose
+described previously, and that it not be modified from the original without
+first contacting FalsePattern.
+
+
+Mod Code:
+==============================
+Any and all users are permitted to use the source for educational purposes,
+or to create derivative works for private use only. GitHub forks and direct
+downloads are considered derivative works.
+
+Unless given explicit written permission - verifiable electronic writing is
+acceptable - no user may redistribute this source code nor any derivative
+works. These pre-approved works must prominently contain this copyright notice.
+
+Derivative mods using any or all of the source code or assets are
+EXPRESSLY FORBIDDEN.
+
+Additionally, no attempt may be made to achieve monetary gain from this code
+by anyone except the original author. In the case of pre-approved derivative
+works, any monetary gains made will be shared between the original author and
+the other developer(s), proportional to the ratio of derived to original code.
+
+Finally, any and all displays, duplicates or derivatives of this code must be
+prominently marked as such, and must contain attribution to the original
+author, including a link to the original source. Any attempts to claim credit
+for this code will be treated as intentional theft.
+
+Due to the Mojang and Minecraft Mod Terms of Service and Licensing
+Restrictions, compiled versions of this code must be provided for free.
+However, with the exception of pre-approved derivative works, only the original
+author's modpacks may distribute compiled binary versions of this code.
+
+==============================
+
+Failure to comply with these restrictions is a violation of copyright law and
+will be dealt with accordingly.
\ No newline at end of file
diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info
new file mode 100644
index 0000000..96fab70
--- /dev/null
+++ b/src/main/resources/mcmod.info
@@ -0,0 +1,16 @@
+[
+ {
+ "modid": "${modId}",
+ "name": "${modName}",
+ "description": "A chunk data hooking library.",
+ "version": "${modVersion}",
+ "mcversion": "${minecraftVersion}",
+ "url": "https://github.com/FalsePattern/ChunkAPI",
+ "updateUrl": "",
+ "authorList": ["FalsePattern"],
+ "credits": "",
+ "logoFile": "",
+ "screenshots": [],
+ "dependencies": []
+ }
+]
diff --git a/src/main/resources/mixins.fplib_chunkapi.json b/src/main/resources/mixins.fplib_chunkapi.json
new file mode 100644
index 0000000..f05b1b9
--- /dev/null
+++ b/src/main/resources/mixins.fplib_chunkapi.json
@@ -0,0 +1,10 @@
+{
+ "required": true,
+ "minVersion": "0.8.5",
+ "package": "com.falsepattern.chunk.mixin.mixins",
+ "plugin": "com.falsepattern.chunk.mixin.plugin.MixinPlugin",
+ "refmap": "mixins.fplib_chunkapi.refmap.json",
+ "target": "@env(DEFAULT)",
+ "compatibilityLevel": "JAVA_8"
+}
+