This commit is contained in:
Ran-Mewo
2026-03-29 19:29:01 +11:00
parent 5f228f0567
commit 215e1d46d0
27 changed files with 657 additions and 1163 deletions
+4 -680
View File
@@ -1,684 +1,8 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
import org.apache.tools.zip.ZipEntry
import javax.annotation.Nonnull
import org.apache.tools.zip.ZipOutputStream
import java.util.function.Function
import java.util.function.Predicate
plugins { plugins {
id "java" id 'root'
id 'io.github.pacifistmc.forgix' version '2.+'
// Plugin to put dependencies inside our final jar
id "com.github.johnrengelman.shadow" version '8.1.1' apply false
// Plugin to create merged jars
id "io.github.pacifistmc.forgix" version "1.3.4"
// Manifold preprocessor
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
// Architectury is used here only as a replacement for forge's own loom
id "dev.architectury.loom" version "1.13-SNAPSHOT" apply false
} }
forgix {
/** autoRun = true
* Creates the list of preprocessors to use.
*
* @param mcVers array of all MC versions
* @param mcIndex array index of the currently active MC version
*/
def writeBuildGradlePredefine(List<String> mcVers, int mcIndex)
{
// Build the list of preprocessors to use
StringBuilder sb = new StringBuilder();
sb.append("# DON'T TOUCH THIS FILE, This is handled by the build script\n");
for (int i = 0; i < mcVers.size(); i++)
{
String verStr = mcVers[i].replace(".", "_");
sb.append("MC_" + verStr + "=" + i.toString() + "\n");
if (mcIndex == i)
{
sb.append("MC_VER=" + i.toString() + "\n");
}
}
// Check if this is a development build
if (mod_version.toLowerCase().contains("dev"))
{
// WARNING: only use this for logging, we don't want to have confusion
// when a method doesn't work correctly in the release build.
sb.append("DEV_BUILD=\n");
}
new File(projectDir, "build.properties").text = sb.toString()
}
// Transfers the values set in settings.gradle to the rest of the project
project.gradle.ext.getProperties().each { prop ->
rootProject.ext.set(prop.key, prop.value)
//println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
}
// Sets up manifold stuff
writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex)
// Sets up the version string (the name we use for our jar)
rootProject.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version // + "-" + new Date().format("yyyy_MM_dd_HH_mm")
class NativeTransformer implements Transformer {
private Predicate<String> fileMatcher
private Function<String, String> filePathMapper
private final HashMap<String, String> replacements = new HashMap()
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
private var nativeRelocator
public File rootDir
void matchFiles(Predicate<String> matcher) {
fileMatcher = matcher
}
void mapPaths(Function<String, String> mapper) {
filePathMapper = mapper
}
void relocateNative(String target, String replacement) {
if (replacement.length() > target.length()) {
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
}
replacements.put(target, replacement)
}
@Override
boolean canTransformResource(@Nonnull FileTreeElement element) {
return fileMatcher.test(element.name)
}
@Override
void transform(@Nonnull TransformerContext context) {
byte[] content = context.is.readAllBytes()
if (nativeRelocator == null) {
nativeRelocator = new NativeRelocator(rootDir.toPath().resolve("relocate_natives"))
}
try {
String path = filePathMapper != null
? filePathMapper.apply(context.path)
: context.path
content = nativeRelocator.processBinary(path, content, replacements)
rewrittenFiles.put(path, content)
}
catch (Throwable e) {
throw new GradleException("Failed to relocate", e)
}
}
@Override
boolean hasTransformedResource() { return !rewrittenFiles.isEmpty() }
@Override
void modifyOutputStream(@Nonnull ZipOutputStream os, boolean preserveFileTimestamps) {
for (Map.Entry<String, byte[]> rewrittenFile : rewrittenFiles.entrySet()) {
os.putNextEntry(new ZipEntry(rewrittenFile.key))
os.write(rewrittenFile.value)
}
}
}
subprojects { p ->
// Does the same as "p == project(":common") || p == project(":fabric") || p == project(":quilt") || p == project(":forge") || p == project("WhateverWeAddLaterOn")"
// Useful later on so we dont have duplicated code
def isMinecraftSubProject = p != project(":core") && p != project(":api")
// Apply plugins
apply plugin: "java"
apply plugin: "com.github.johnrengelman.shadow"
if (isMinecraftSubProject)
apply plugin: "systems.manifold.manifold-gradle-plugin"
// Apply forge's loom
if ((findProject(":forge") && p == project(":forge")) ||
(findProject(":neoforge") && p == project(":neoforge"))
)
{
apply plugin: "dev.architectury.loom"
}
// Set the manifold version (may not be required tough)
manifold {
manifoldVersion = rootProject.manifold_version
}
// set up custom configurations (configurations are a way to handle dependencies)
configurations {
// extends the shadowJar configuration
shadowMe
// have implemented dependencies automatically embedded in the final jar
implementation.extendsFrom(shadowMe)
// Configuration fpr core & api
coreProjects
shadowMe.extendsFrom(coreProjects)
// FIXME this additional configuration is necessary because forge
// needs forgeRuntimeLibrary, although adding it to shadowMe
// causes runtime issues where the libraries aren't properly added
forgeShadowMe
// this should match shadowMe pretty closely
implementation.extendsFrom(forgeShadowMe)
shadowMe.extendsFrom(forgeShadowMe)
forgeRuntimeLibrary.extendsFrom(forgeShadowMe)
if (isMinecraftSubProject && p != project(":common")) {
// Shadow common
common
shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
if (findProject(":forge"))
developmentForge.extendsFrom common
if (findProject(":neoforge"))
developmentNeoForge.extendsFrom common
compileClasspath.extendsFrom coreProjects
runtimeClasspath.extendsFrom coreProjects
if (findProject(":forge"))
developmentForge.extendsFrom coreProjects
if (findProject(":neoforge"))
developmentNeoForge.extendsFrom coreProjects
}
}
dependencies {
//=====================//
// shared dependencies //
//=====================//
// Manifold
if (isMinecraftSubProject) {
annotationProcessor("systems.manifold:manifold-preprocessor:${rootProject.manifold_version}")
}
// Log4j
if (p == project(":core"))
{
// the standalone core jar needs logging shaded otherwise it won't run
forgeShadowMe("org.apache.logging.log4j:log4j-api:${rootProject.log4j_version}")
forgeShadowMe("org.apache.logging.log4j:log4j-core:${rootProject.log4j_version}")
}
else
{
// When running in MC, MC already includes logging
implementation("org.apache.logging.log4j:log4j-api:${rootProject.log4j_version}")
implementation("org.apache.logging.log4j:log4j-core:${rootProject.log4j_version}")
}
// JOML
if (project.hasProperty("embed_joml") && embed_joml == "true")
forgeShadowMe("org.joml:joml:${rootProject.joml_version}")
else
implementation("org.joml:joml:${rootProject.joml_version}")
// JUnit tests
implementation("org.junit.jupiter:junit-jupiter:5.8.2")
implementation("org.junit.jupiter:junit-jupiter-engine:5.8.2")
implementation("junit:junit:4.13")
// FastUtil
// Note: MC 1.16 uses 8.2.1, and versions after use 8.5.12
// We cannot relocate this library since we call some MC classes that reference it
implementation("it.unimi.dsi:fastutil:${rootProject.fastutil_version}")
forgeShadowMe("com.github.luben:zstd-jni:${rootProject.zstd_version}")
// Compression
forgeShadowMe("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
forgeShadowMe("org.tukaani:xz:${rootProject.xz_version}") // LZMA
// Sqlite Database
forgeShadowMe("org.xerial:sqlite-jdbc:${rootProject.sqlite_jdbc_version}")
// NightConfig (includes Toml & Json)
forgeShadowMe("com.electronwill.night-config:toml:${rootProject.nightconfig_version}")
forgeShadowMe("com.electronwill.night-config:json:${rootProject.nightconfig_version}")
// SVG (not needed atm)
// forgeShadowMe("com.formdev:svgSalamander:${rootProject.svgSalamander_version}")
// Netty
implementation("io.netty:netty-buffer:${rootProject.netty_version}")
//==========================//
// conditional dependencies //
//==========================//
// Add core
if (isMinecraftSubProject) {
coreProjects(project(":core")) {
// Remove Junit test libraries
exclude group: "org.junit.jupiter", module: "junit-jupiter"
exclude group: "org.junit.jupiter", module: "junit-jupiter-engine"
exclude group: "junit", module: "junit"
// Removed dependencies
transitive false
}
}
// Add the api
if (p != project(":api")) {
coreProjects(project(":api")) {
// Remove Junit test libraries
exclude group: "org.junit.jupiter", module: "junit-jupiter"
exclude group: "org.junit.jupiter", module: "junit-jupiter-engine"
exclude group: "junit", module: "junit"
// Removed dependencies
transitive false
}
}
// Add common
if (isMinecraftSubProject && p != project(":common")) {
// Common
common(project(":common")) { transitive false }
shadowCommon(project(":common")) { transitive false }
}
}
shadowJar {
configurations = [project.configurations.shadowMe]
if (isMinecraftSubProject && p != project(":common")) {
configurations.push(project.configurations.shadowCommon) // Shadow the common subproject
relocate "com.seibel.distanthorizons.common", "loaderCommon.${p.name}.com.seibel.distanthorizons.common" // Move the loader files to a different location
}
def librariesLocation = "DistantHorizons.libraries"
// Compression (LZ4)
relocate "net.jpountz", "${librariesLocation}.jpountz"
// Logging
relocate "org.slf4j", "${librariesLocation}.slf4j"
// Sqlite Database
// librariesLocation isn't used because it's too long for replacing paths in native libraries
// Allowing strings larger than the original string would require shifting the entire binary's contents
relocate "org.sqlite", "dh_sqlite", {
exclude "org/sqlite/native/**"
}
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
transform(NativeTransformer) {
rootDir = project.rootDir
matchFiles { it.startsWith("org/sqlite") }
mapPaths { it.replace("org/sqlite", "dh_sqlite") }
relocateNative "org/sqlite", "dh_sqlite"
relocateNative "org_sqlite", "dh_1sqlite"
}
// ZStd
// librariesLocation isn't used because it's too long for replacing paths in native libraries
// Allowing strings larger than the original string would require shifting the entire binary's contents
relocate "com.github.luben", "dhcomgithubluben"
relocate "libzstd-jni", "libzstd-jni_dh"
relocate "zstd-jni", "zstd-jni_dh"
transform(NativeTransformer) {
rootDir = project.rootDir
matchFiles { it.contains("libzstd-jni") && !it.contains("aix/ppc64") }
mapPaths { it.replace("libzstd-jni", "libzstd-jni_dh") }
relocateNative "com/github/luben", "dhcomgithubluben"
relocateNative "com_github_luben", "dhcomgithubluben"
}
// JOML
if (project.hasProperty("embed_joml") && embed_joml == "true")
relocate "org.joml", "${librariesLocation}.joml"
// NightConfig (includes Toml & Json)
relocate "com.electronwill.nightconfig", "${librariesLocation}.electronwill.nightconfig"
// Netty
// Don't relocate, it causes problems with using MC's FriendlyByteBufs
// relocate "io.netty", "${librariesLocation}.netty"
mergeServiceFiles()
}
// Using jar.finalizedBy(shadowJar) causes issues so we do this scuffed bypass
jar.dependsOn(shadowJar)
// Put stuff from gradle.properties into the mod info
// Note: these resources are only included in the mod jars, the core and API jars don't include these files
processResources {
def resourceTargets = [ // Location of where to inject the properties
// Holds info like git commit
"build_info.json",
// Properties for each of the loaders
"fabric.mod.json",
"quilt.mod.json",
"META-INF/mods.toml",
"META-INF/neoforge.mods.toml",
// The mixins for each of the loaders
//"DistantHorizons."+ p.name +".fabricLike.mixins.json"
]
def intoTargets = ["$buildDir/resources/main/"] // Location of the built resources folder
// Fix forge version numbering system as it is weird
// For whatever reason forge uses [1.18, 1.18.1, 1.18.2) instead of the standard ["1.18", "1.18.1", "1.18.2"]
def compatible_forgemc_versions = "${compatible_minecraft_versions}".replaceAll("\"", "").replaceAll("]", ",)")
// println compatible_forgemc_versions
// Quilt's custom contributors system
// This has to be like
// "Person": "Developer", "Another person": "Developer"
def quilt_contributors = []
def mod_author_list = mod_authors.replaceAll("\"", "").replace("[", "").replace("]", "").split(",")
for (dev in mod_author_list) {
quilt_contributors.push("\"${dev.strip()}\": \"Developer\"")
}
quilt_contributors.reverse()
//println quilt_contributors.join(", ")
// These "hasProperty"'s are so that they can be passed through the cli (ie in the CI)
try {
if (infoGitCommit == "null")
infoGitCommit = 'git rev-parse --verify HEAD'.execute().text.trim()
if (infoGitBranch == "null")
infoGitBranch = 'git symbolic-ref --short HEAD'.execute().text.trim()
} catch (Exception e) {
infoGitCommit = infoGitBranch = "Git not found"
println "Git or Git project not found"
}
// The left side is what gets replaced in the mod info and the right side is where to get it from in the gradle.properties
def replaceProperties = [
version : mod_version,
mod_name : mod_readable_name,
group : maven_group,
authors : mod_authors,
description : mod_description,
homepage : mod_homepage,
source : mod_source,
issues : mod_issues,
discord : mod_discord,
minecraft_version : minecraft_version,
compatible_minecraft_versions: compatible_minecraft_versions,
compatible_forgemc_versions : compatible_forgemc_versions,
java_version : java_version,
quilt_contributors : "{"+quilt_contributors.join(", ")+"}",
info_git_commit : infoGitBranch,
info_git_branch : infoGitCommit,
info_build_source : infoBuildSource,
fabric_incompatibility_list : fabric_incompatibility_list,
fabric_recommend_list : fabric_recommend_list,
neoforge_version_range : neoforge_version_range,
]
// replace any properties in the sub-projects with the values defined here
inputs.properties replaceProperties
replaceProperties.put "project", project
filesMatching(resourceTargets) {
expand replaceProperties
}
intoTargets.each { target ->
if (file(target).exists()) {
copy {
from(sourceSets.main.resources) {
include resourceTargets
expand replaceProperties
}
into target
}
}
}
// ==================== Delete un-needed files ====================
// Jank solution to remove all unused accesswideners
// (neo)forge (well, mainly architectury) requires the original accesswidener file, meaning we require this jank solution to keep it
exclude { file ->
if (file.name.contains(".distanthorizons.accesswidener") && file.name != "${accessWidenerVersion}.distanthorizons.accesswidener") {
return true
}
return false
}
}
// Adds the standalone jar's entrypoint
jar {
from "LICENSE.txt"
manifest {
attributes(
'Implementation-Title': rootProject.mod_name,
'Implementation-Version': rootProject.mod_version,
'Multi-Release': true, // needed for logging in the standalone core jar
'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain', // When changing the main of the jar change this line
)
}
}
// this can be un-commented if we ever wanted to make DH modular (AKA use a module-info.java file) again
/*
// Tells gradle where to look for other modules
// Why isn't the classpath added to the modules path by default?
if (p == project(":core")) {
compileJava {
inputs.property('moduleName', 'dhApi')
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath
]
classpath = files()
}
}
}
*/
}
allprojects { p ->
// Does the same as "p == project(":common") || p == project(":fabric") || p == project(":quilt") || p == project(":forge") || p == project("WhateverWeAddLaterOn")"
// Useful later on so we dont have duplicated code
def isMinecraftSubProject = p != project(":core") && p != project(":api")
apply plugin: "java"
apply plugin: "maven-publish"
// Sets the name of the jar, the version will contain the name of the project if it isn't the root project
archivesBaseName = rootProject.mod_name
version = (project == rootProject ? "" : project.name + "-") + rootProject.versionStr
group = rootProject.maven_group
// this is the text that appears at the top of the overview (home) page
// and is used when bookmarking a page
javadoc.title = rootProject.mod_name + "-" + project.name
// Some annotations arent "technically" part of the official java standard,
// so we define it ourself here
javadoc {
configure( options ) {
tags(
'todo:X"',
'apiNote:a:API Note:',
'implSpec:a:Implementation Requirements:',
'implNote:a:Implementation Note:'
)
}
}
repositories {
// Mojang overrides (added to fix downloading the wrong LWJGL libs on M1 Mac's and potentially other arm64 based machines)
maven { url "https://libraries.minecraft.net/" }
// The central repo
mavenCentral()
// Used for Google's Collect library
maven { url "https://repo.enonic.com/public/" }
// For parchment mappings
// versions can be found here: https://ldtteam.jfrog.io/ui/native/parchmentmc-public/org/parchmentmc/data/
maven { url "https://maven.parchmentmc.org" }
// For Architectury API
maven { url "https://maven.architectury.dev" }
// For Git repositories
maven { url "https://jitpack.io" }
// For Manifold Preprocessor
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
// Required for importing Modrinth mods
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
content {
includeGroup "maven.modrinth"
}
}
// Required for importing CursedForge mods
maven {
url "https://www.cursemaven.com"
content {
includeGroup "curse.maven"
}
}
// VanillaGradle and Mixins in common
maven { url "https://repo.spongepowered.org/maven/" }
// Canvas mod
maven { url "https://maven.vram.io/" }
// ModMenu mod
maven { url "https://maven.terraformersmc.com/" }
// neoforge
maven { url "https://maven.neoforged.net/releases/" }
// These 3 are for importing mods that arnt on CursedForge, Modrinth, GitHub, GitLab or anywhere opensource
flatDir {
dirs "${rootDir}/mods/fabric"
content {
includeGroup "fabric-mod"
}
}
flatDir {
dirs "${rootDir}/mods/quilt"
content {
includeGroup "quilt-mod"
}
}
flatDir {
dirs "${rootDir}/mods/forge"
content {
includeGroup "forge-mod"
}
}
}
// Adds some dependencies that are in vanilla but not in core
if (p == project(":core")) {
OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem;
// Set the OS lwjgl is using to the current os
project.ext.lwjglNatives = "natives-" + os.toFamilyName()
dependencies {
// All of these dependencies are in Vanilla Minecraft, but we need to depend on them as we arent importing Minecraft in the core
// Imports most of lwjgl's libraries
implementation platform("org.lwjgl:lwjgl-bom:${rootProject.lwjgl_version}")
// REMEMBER: Don't shadow stuff here, these are just the libs that are included in Minecraft so that the core can use them
implementation "org.lwjgl:lwjgl"
implementation "org.lwjgl:lwjgl-assimp"
implementation "org.lwjgl:lwjgl-glfw"
// OpenGL is removed since DH now handles rendering in the "Common" project
// so we can use OpenGL for old MC versions and Blaze3D (IE Vulkan) for newer ones
// implementation "org.lwjgl:lwjgl-openal"
// implementation "org.lwjgl:lwjgl-opengl"
implementation "org.lwjgl:lwjgl-stb"
implementation "org.lwjgl:lwjgl-tinyfd"
runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-assimp::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
// runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives"
// runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-tinyfd::$lwjglNatives"
implementation "org.joml:joml:${rootProject.joml_version}"
// Some other dependencies
implementation("org.jetbrains:annotations:16.0.2")
implementation("com.google.code.findbugs:jsr305:3.0.2")
implementation("com.google.common:google-collect:0.5")
implementation("com.google.guava:guava:31.1-jre")
}
}
task copyCommonLoaderResources(type: Copy) {
from project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener")
into(file(p.file("build/resources/main")))
rename "${accessWidenerVersion}.distanthorizons.accesswidener", "distanthorizons.accesswidener"
}
task copyCoreResources(type: Copy) {
from fileTree(project(":core").file("src/main/resources"))
into p.file("build/resources/main")
}
tasks.withType(JavaCompile) {
if (isMinecraftSubProject) {
options.release = rootProject.java_version as Integer
} else {
options.release = 8; // Core & Api should use Java 8 no matter what
}
options.encoding = "UTF-8"
}
java {
withSourcesJar()
}
} }
+24
View File
@@ -0,0 +1,24 @@
plugins {
id 'groovy-gradle-plugin'
}
repositories {
gradlePluginPortal()
mavenCentral()
maven { url = 'https://maven.wagyourtail.xyz/releases' }
maven { url = 'https://maven.outlands.top/releases' }
maven { url = 'https://maven.wagyourtail.xyz/snapshots' }
maven { url = 'https://maven.architectury.dev/' }
maven { url = 'https://maven.fabricmc.net/' }
maven { url = 'https://maven.neoforged.net/releases/' }
maven { url = 'https://maven.minecraftforge.net/' }
maven { url = 'https://repo.spongepowered.org/repository/maven-public/' }
maven { url = 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
dependencies {
implementation 'com.gradleup.shadow:shadow-gradle-plugin:9.0.0'
implementation 'xyz.wagyourtail.unimined:xyz.wagyourtail.unimined.gradle.plugin:1.4.16-kappa'
implementation 'xyz.wagyourtail:manifold-gradle:1.0.0-SNAPSHOT'
implementation 'xyz.wagyourtail.jvmdowngrader:xyz.wagyourtail.jvmdowngrader.gradle.plugin:1.3.4'
}
+450
View File
@@ -0,0 +1,450 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.ResourceTransformer
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
import org.apache.tools.zip.ZipEntry
import org.apache.tools.zip.ZipOutputStream
import javax.annotation.Nonnull
import java.util.function.Function
import java.util.function.Predicate
// Convention plugin for all MC-facing subprojects (common + loaders).
// Common uses this directly; loaders use it via unimined-fabric/forge/neoforge.
// IMPORTANT: unimined MUST be applied before shadow/jvmdowngrader
// so its afterEvaluate runs first and can modify configs.
plugins {
id 'java'
id 'maven-publish'
id 'xyz.wagyourtail.unimined'
id 'com.gradleup.shadow'
id 'xyz.wagyourtail.manifold'
id 'xyz.wagyourtail.jvmdowngrader'
}
def isNotCommonProject = project.name != "common"
// ==================== Version Properties ====================
project.gradle.ext.getProperties().each { prop ->
rootProject.ext.set(prop.key, prop.value)
}
manifold {
version = rootProject.manifold_version
}
// ==================== Repositories ====================
repositories {
maven { url "https://libraries.minecraft.net/" }
mavenCentral()
maven { url "https://repo.enonic.com/public/" }
maven { url "https://maven.parchmentmc.org" }
maven { url "https://maven.architectury.dev" }
maven { url "https://jitpack.io" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
content { includeGroup "maven.modrinth" }
}
maven {
url "https://www.cursemaven.com"
content { includeGroup "curse.maven" }
}
maven { url "https://repo.spongepowered.org/maven/" }
maven { url "https://maven.terraformersmc.com/" }
maven { url "https://maven.neoforged.net/releases/" }
flatDir {
dirs "${rootDir}/mods/fabric"
content { includeGroup "fabric-mod" }
}
flatDir {
dirs "${rootDir}/mods/quilt"
content { includeGroup "quilt-mod" }
}
flatDir {
dirs "${rootDir}/mods/forge"
content { includeGroup "forge-mod" }
}
}
// ==================== Java Config ====================
tasks.withType(JavaCompile).configureEach {
options.release = rootProject.java_version as Integer
options.encoding = "UTF-8"
}
java {
sourceCompatibility = JavaVersion.toVersion(gradle.ext.java_version as Integer)
targetCompatibility = JavaVersion.toVersion(gradle.ext.java_version as Integer)
withSourcesJar()
}
// ==================== Loader-Only Config ====================
if (isNotCommonProject) {
base { archivesName = rootProject.mod_name }
rootProject.ext.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version
version = project.name + "-" + rootProject.versionStr
group = rootProject.maven_group
javadoc.title = rootProject.mod_name + "-" + project.name
javadoc {
configure(options) {
tags(
'todo:X"',
'apiNote:a:API Note:',
'implSpec:a:Implementation Requirements:',
'implNote:a:Implementation Note:'
)
}
}
tasks.withType(GenerateModuleMetadata).configureEach {
enabled = false
}
tasks.withType(Test).configureEach {
enabled = false
}
compileTestJava.enabled = false
tasks.withType(Sign).configureEach {
enabled = false
}
jar {
from "LICENSE.txt"
manifest {
attributes(
'Implementation-Title': rootProject.mod_name,
'Implementation-Version': rootProject.mod_version,
'Multi-Release': true,
'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain',
)
}
}
}
// ==================== Unimined Minecraft Config ====================
unimined.minecraft(sourceSets.main, true) {
version gradle.ext.minecraft_version
mappings {
mojmap()
devNamespace "mojmap"
}
}
if (isNotCommonProject) {
// Mixin remapping and common project wiring
unimined.minecraft(sourceSets.main, true) {
mods.modImplementation {
mixinRemap {
reset()
enableBaseMixin()
enableMixinExtra()
}
}
}
dependencies {
implementation(project(":common"))
}
processResources {
from project(":common").sourceSets.main.resources
}
tasks.withType(JavaCompile).configureEach {
source(project(":common").sourceSets.main.allSource)
}
} else {
// Common: fabric for compilation + access widener, no jar remapping or runs
unimined.minecraft {
fabric {
loader gradle.ext.fabric_loader_version
accessWidener project.file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
}
defaultRemapJar = false
runs.off = true
}
}
// ==================== Configurations ====================
evaluationDependsOn(":core")
configurations {
shadowMe
coreProjects
shadowMe.extendsFrom(coreProjects)
implementation.extendsFrom(shadowMe)
common
implementation.extendsFrom(common)
}
// ==================== Dependencies ====================
// Copy core's compileOnly deps so MC-provided deps are visible without redeclaring them.
project(":core").configurations.compileOnly.allDependencies.each { dep ->
if (!(dep instanceof ProjectDependency))
dependencies.add("compileOnly", dep)
}
dependencies {
// Manifold preprocessor & strings
annotationProcessor(manifold.module("preprocessor"))
annotationProcessor(manifold.module("strings"))
// NightConfig: implementation in core (bundled) but Unimined strips it from compile classpath
compileOnly("com.electronwill.night-config:toml:${rootProject.nightconfig_version}")
// Core & API projects — bundled into shadow jar
coreProjects(project(":core"))
coreProjects(project(":api"))
// JOML: shadow for old MC versions that don't bundle it (core has it compileOnly already)
if (project.hasProperty("embed_joml") && embed_joml == "true")
shadowMe("org.joml:joml:${rootProject.joml_version}")
// Common project dependency
if (isNotCommonProject)
common(project(":common")) { transitive false }
}
// ==================== NativeTransformer ====================
class NativeTransformer implements ResourceTransformer {
private Predicate<String> fileMatcher
private Function<String, String> filePathMapper
private final HashMap<String, String> replacements = new HashMap()
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
private nativeRelocator
public File rootDir
void matchFiles(Predicate<String> matcher) {
fileMatcher = matcher
}
void mapPaths(Function<String, String> mapper) {
filePathMapper = mapper
}
void relocateNative(String target, String replacement) {
if (replacement.length() > target.length()) {
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
}
replacements.put(target, replacement)
}
@Override
boolean canTransformResource(@Nonnull FileTreeElement element) {
return fileMatcher != null && fileMatcher.test(element.relativePath.pathString)
}
@Override
void transform(@Nonnull TransformerContext context) {
byte[] content = context.inputStream.readAllBytes()
if (nativeRelocator == null) {
nativeRelocator = new NativeRelocator(rootDir.toPath().resolve("relocate_natives"))
}
try {
String path = filePathMapper != null
? filePathMapper.apply(context.path)
: context.path
content = nativeRelocator.processBinary(path, content, replacements)
rewrittenFiles.put(path, content)
}
catch (Throwable e) {
throw new GradleException("Failed to relocate", e)
}
}
@Override
boolean hasTransformedResource() { return !rewrittenFiles.isEmpty() }
@Override
void modifyOutputStream(@Nonnull ZipOutputStream os, boolean preserveFileTimestamps) {
for (Map.Entry<String, byte[]> rewrittenFile : rewrittenFiles.entrySet()) {
os.putNextEntry(new ZipEntry(rewrittenFile.key))
os.write(rewrittenFile.value)
}
}
}
// ==================== Shadow JAR (loaders only) ====================
if (isNotCommonProject) {
shadowJar {
configurations = [project.configurations.shadowMe]
relocate "com.seibel.distanthorizons.common", "loaderCommon.${project.name}.com.seibel.distanthorizons.common"
def librariesLocation = "DistantHorizons.libraries"
// LZ4
relocate "net.jpountz", "${librariesLocation}.jpountz"
// SLF4J
relocate "org.slf4j", "${librariesLocation}.slf4j"
// SQLite
relocate "org.sqlite", "dh_sqlite", { exclude "org/sqlite/native/**" }
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
transform(NativeTransformer) {
rootDir = project.rootDir
matchFiles { it.startsWith("org/sqlite") }
mapPaths { it.replace("org/sqlite", "dh_sqlite") }
relocateNative "org/sqlite", "dh_sqlite"
relocateNative "org_sqlite", "dh_1sqlite"
}
// ZStd
relocate "com.github.luben", "dhcomgithubluben"
relocate "libzstd-jni", "libzstd-jni_dh"
relocate "zstd-jni", "zstd-jni_dh"
transform(NativeTransformer) {
rootDir = project.rootDir
matchFiles { it.contains("libzstd-jni") && !it.contains("aix/ppc64") }
mapPaths { it.replace("libzstd-jni", "libzstd-jni_dh") }
relocateNative "com/github/luben", "dhcomgithubluben"
relocateNative "com_github_luben", "dhcomgithubluben"
}
// JOML (conditional)
if (project.hasProperty("embed_joml") && embed_joml == "true")
relocate "org.joml", "${librariesLocation}.joml"
// NightConfig
relocate "com.electronwill.nightconfig", "${librariesLocation}.electronwill.nightconfig"
mergeServiceFiles()
}
afterEvaluate {
tasks.named("remapJar").configure {
dependsOn(shadowJar)
inputFile.set(shadowJar.archiveFile)
}
// Make run tasks use the shadow jar so relocated deps (NightConfig, etc.) work in dev.
// Without this, NeoForge's bundled NightConfig 3.8.x conflicts with DH's 3.6.6.
tasks.withType(JavaExec).configureEach { runTask ->
dependsOn(shadowJar)
classpath = files(shadowJar.archiveFile) + classpath.filter { file ->
!file.path.contains(project.buildDir.path) &&
!file.path.contains("core${File.separator}build") &&
!file.path.contains("api${File.separator}build") &&
!file.path.contains("common${File.separator}build")
}
}
}
}
// ==================== Process Resources (loaders only) ====================
if (isNotCommonProject) {
processResources {
def resourceTargets = [
"build_info.json",
"fabric.mod.json",
"quilt.mod.json",
"META-INF/mods.toml",
"META-INF/neoforge.mods.toml",
]
def compatible_forgemc_versions = "${rootProject.compatible_minecraft_versions}".replaceAll("\"", "").replaceAll("]", ",)")
// Quilt contributors
def quilt_contributors = []
def mod_author_list = rootProject.mod_authors.replaceAll("\"", "").replace("[", "").replace("]", "").split(",")
for (dev in mod_author_list) {
quilt_contributors.push("\"${dev.strip()}\": \"Developer\"")
}
quilt_contributors.reverse()
try {
if (rootProject.infoGitCommit == "null")
rootProject.ext.infoGitCommit = 'git rev-parse --verify HEAD'.execute().text.trim()
if (rootProject.infoGitBranch == "null")
rootProject.ext.infoGitBranch = 'git symbolic-ref --short HEAD'.execute().text.trim()
} catch (Exception e) {
rootProject.ext.infoGitCommit = "Git not found"
rootProject.ext.infoGitBranch = "Git not found"
}
def replaceProperties = [
version : rootProject.mod_version,
mod_name : rootProject.mod_readable_name,
group : rootProject.maven_group,
authors : rootProject.mod_authors,
description : rootProject.mod_description,
homepage : rootProject.mod_homepage,
source : rootProject.mod_source,
issues : rootProject.mod_issues,
discord : rootProject.mod_discord,
minecraft_version : rootProject.minecraft_version,
compatible_minecraft_versions: rootProject.compatible_minecraft_versions,
compatible_forgemc_versions : compatible_forgemc_versions,
java_version : rootProject.java_version,
quilt_contributors : "{" + quilt_contributors.join(", ") + "}",
info_git_commit : rootProject.infoGitBranch,
info_git_branch : rootProject.infoGitCommit,
info_build_source : rootProject.infoBuildSource,
fabric_incompatibility_list : rootProject.fabric_incompatibility_list,
fabric_recommend_list : rootProject.fabric_recommend_list,
neoforge_version_range : rootProject.neoforge_version_range,
]
inputs.properties replaceProperties
replaceProperties.put "project", project
filesMatching(resourceTargets) {
expand replaceProperties
}
// Remove unused access wideners
exclude { file ->
if (file.name.contains(".distanthorizons.accesswidener") && file.name != "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener") {
return true
}
return false
}
}
// ==================== Resource Copy Tasks ====================
task copyCommonLoaderResources(type: Copy) {
from project(":common").file("src/main/resources/${rootProject.accessWidenerVersion}.distanthorizons.accesswidener")
into(file(project.file("build/resources/main")))
rename "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener", "distanthorizons.accesswidener"
}
task copyCoreResources(type: Copy) {
from fileTree(project(":core").file("src/main/resources"))
into project.file("build/resources/main")
}
// ==================== JVMDowngrader ====================
jvmdg.downgradeTo = JavaVersion.toVersion(rootProject.java_version)
downgradeJar.archiveClassifier.set(null)
shadeDowngradedApi.archiveClassifier.set(null)
}
+44
View File
@@ -0,0 +1,44 @@
plugins {
id 'java'
}
// Transfer version properties from settings.gradle to project
project.gradle.ext.getProperties().each { prop ->
rootProject.ext.set(prop.key, prop.value)
}
// Version string for archives
rootProject.ext.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version
rootProject.allprojects {
version = (it == rootProject ? "" : it.name + "-") + rootProject.versionStr
group = rootProject.maven_group
}
// Create build.properties with preprocessor definitions
def writePreprocessorDefinitions() {
StringBuilder sb = new StringBuilder()
sb.append("# DON'T TOUCH THIS FILE, This is handled by the build script\n")
gradle.ext.mcVers.eachWithIndex { ver, idx ->
sb.append("MC_${ver.replace('.', '_')}=${idx}\n")
if (gradle.ext.mcIndex == idx)
sb.append("MC_VER=${idx}\n")
}
if (rootProject.mod_version.toLowerCase().contains("dev")) {
sb.append("DEV_BUILD=\n")
}
new File(rootDir, "build.properties").text = sb.toString()
}
writePreprocessorDefinitions()
// Wire JVMDowngrader to process remapped jars
gradle.projectsEvaluated {
rootProject.subprojects.each {
if (it.tasks.findByName('remapJar') == null) return
it.tasks.downgradeJar.inputFile = it.tasks.remapJar.archiveFile
it.tasks.jar.finalizedBy(it.tasks.remapJar)
it.tasks.remapJar.finalizedBy(it.tasks.shadeDowngradedApi)
}
}
@@ -0,0 +1,13 @@
plugins {
id 'dh-loader'
}
unimined.minecraft {
fabric {
loader gradle.ext.fabric_loader_version
accessWidener project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
}
}
runClient.javaLauncher = null
runServer.javaLauncher = null
@@ -0,0 +1,17 @@
plugins {
id 'dh-loader'
}
def awFile = project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
unimined.minecraft {
forge {
loader gradle.ext.forge_version
useToolchains = false
mixinConfig("DistantHorizons.forge.mixins.json")
accessTransformer aw2at(awFile)
}
}
runClient.javaLauncher = null
runServer.javaLauncher = null
@@ -0,0 +1,16 @@
plugins {
id 'dh-loader'
}
def awFile = project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
unimined.minecraft {
neoForged {
loader gradle.ext.neoforge_version
useToolchains = false
accessTransformer aw2at(awFile)
}
}
runClient.javaLauncher = null
runServer.javaLauncher = null
+1 -39
View File
@@ -1,41 +1,3 @@
// temporary fix for broken spongepowered version
buildscript {
configurations.configureEach {
resolutionStrategy {
force 'org.spongepowered:vanillagradle:0.2.1-20240507.024226-82'
// newer versions can be found by going to the link:
// https://repo.spongepowered.org/#browse/browse:maven-public:org%2Fspongepowered%2Fvanillagradle%2F0.2.1-SNAPSHOT
}
}
}
plugins { plugins {
id "org.spongepowered.gradle.vanilla" version "0.2.1-SNAPSHOT" id 'dh-loader'
} }
minecraft {
accessWideners(project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener"))
version(rootProject.minecraft_version)
}
dependencies {
// So mixins can be written in common
compileOnly group:'org.spongepowered', name:'mixin', version:'0.8.5'
}
publishing {
publications {
mavenCommon(MavenPublication) {
artifactId = rootProject.mod_readable_name
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
}
}
+14 -139
View File
@@ -1,110 +1,24 @@
plugins { plugins {
id "fabric-loom" version "1.10-SNAPSHOT" id 'unimined-fabric'
}
loom {
accessWidenerPath = project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener")
// "runs" isn't required, but when we do need it then it can be useful
runs {
client {
client()
setConfigName("Fabric Client")
ideConfigGenerated(true) // When true a run configuration file will be generated for IDE's. By default only set to true for the root project.
runDir("../run/client")
vmArgs(
// https://github.com/FabricMC/fabric-loom/issues/915#issuecomment-1609154390
"-Dminecraft.api.auth.host=https://nope.invalid",
"-Dminecraft.api.account.host=https://nope.invalid",
"-Dminecraft.api.session.host=https://nope.invalid",
"-Dminecraft.api.services.host=https://nope.invalid",
// https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
"-Dio.netty.leakDetection.level=advanced",
"-XX:+UseZGC",
"-XX:+ZGenerational"
)
programArgs(
"--username", "Dev",
// "--renderDebugLabels" is a Mojang command to show render names in RenderDoc
"--renderDebugLabels",
// "--tracy" is a Mojang command to allow individual frames to be debugged using Tracy https://github.com/wolfpld/tracy/releases/tag/v0.13.1
"--tracy")
}
server {
server()
setConfigName("Fabric Server")
ideConfigGenerated(true)
runDir("../run/server")
vmArgs("-Dio.netty.leakDetection.level=advanced")
}
}
}
remapJar {
inputFile = shadowJar.archiveFile
dependsOn shadowJar
} }
configurations { // ==================== Dependencies ====================
// The addModJar basically embeds the mod to the built jar
addModJar
include.extendsFrom addModJar
modImplementation.extendsFrom addModJar
}
def addMod(path, enabled) { def addMod(path, enabled) {
if (enabled == "2") if (enabled == "2")
dependencies { modImplementation(path) } dependencies { modImplementation(path) }
else if (enabled == "1") else if (enabled == "1")
dependencies { modCompileOnly(path) } dependencies { compileOnly(path) }
} }
dependencies { dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
mappings loom.layered() {
// Mojmap mappings
officialMojangMappings()
// Parchment mappings (it adds parameter mappings & javadoc)
parchment("org.parchmentmc.data:parchment-${rootProject.parchment_version}@zip")
}
// Fabric loader // Fabric loader
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
// Fabric API (bundled as jar-in-jar so users don't need to install it separately)
// annotationProcessor "javax.annotation:javax.annotation-api:1.3.2" modImplementation "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
// implementation("javax.annotation:javax.annotation-api:1.3.2") include "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
// runtimeOnly "javax.annotation:javax.annotation-api:1.3.2"
// compileOnly "javax.annotation:javax.annotation-api:1.3.2"
// modImplementation "javax.annotation:javax.annotation-api:1.3.2"
// Fabric API
addModJar(fabricApi.module("fabric-api-base", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-lifecycle-events-v1", rootProject.fabric_api_version))
if (buildVersionBefore(minecraft_version, "1.21.9"))
{
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
}
else // > 1.21.9
{
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-resource-loader-v1", rootProject.fabric_api_version))
}
addModJar(fabricApi.module("fabric-events-interaction-v0", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-rendering-v1", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-entity-events-v1", rootProject.fabric_api_version))
if (buildVersionBefore(minecraft_version, "1.19.2"))
addModJar(fabricApi.module("fabric-command-api-v1", rootProject.fabric_api_version))
else
addModJar(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version))
// used by mod menu in MC 1.20.6+
addModJar(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-key-binding-api-v1", rootProject.fabric_api_version))
// Mod Menu // Mod Menu
addMod("com.terraformersmc:modmenu:${rootProject.modmenu_version}", rootProject.enable_mod_menu) addMod("com.terraformersmc:modmenu:${rootProject.modmenu_version}", rootProject.enable_mod_menu)
@@ -117,11 +31,7 @@ dependencies {
// Sodium // Sodium
addMod("maven.modrinth:sodium:${rootProject.sodium_version}", rootProject.enable_sodium) addMod("maven.modrinth:sodium:${rootProject.sodium_version}", rootProject.enable_sodium)
if (rootProject.enable_sodium == "2") { if (rootProject.enable_sodium == "2") implementation "org.joml:joml:1.10.2"
implementation "org.joml:joml:1.10.2"
modImplementation(fabricApi.module("fabric-rendering-data-attachment-v1", rootProject.fabric_api_version))
modImplementation(fabricApi.module("fabric-rendering-fluids-v1", rootProject.fabric_api_version))
}
// Lithium // Lithium
addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium) addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium)
@@ -133,65 +43,32 @@ dependencies {
addMod("com.github.quiqueck:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib) addMod("com.github.quiqueck:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib)
// Canvas // Canvas
addMod("io.vram:canvas-fabric-${project.canvas_version}", rootProject.enable_canvas) addMod("io.vram:canvas-fabric-${rootProject.canvas_version}", rootProject.enable_canvas)
// Immersive Portals // Immersive Portals
if (rootProject.enable_immersive_portals == "1") { if (rootProject.enable_immersive_portals == "1") {
modCompileOnly("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${project.immersive_portals_version}") modCompileOnly("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}")
} }
else if (rootProject.enable_immersive_portals == "2") { else if (rootProject.enable_immersive_portals == "2") {
modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${project.immersive_portals_version}") { modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api") exclude(group: "net.fabricmc.fabric-api")
transitive(false) transitive(false)
} }
modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:${project.immersive_portals_version}") { modImplementation("com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api") exclude(group: "net.fabricmc.fabric-api")
transitive(false) transitive(false)
} }
modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:build:${project.immersive_portals_version}") { modImplementation("com.github.iPortalTeam.ImmersivePortalsMod:build:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api") exclude(group: "net.fabricmc.fabric-api")
transitive(false) transitive(false)
} }
modImplementation("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}")
api("com.github.LlamaLad7:MixinExtras:0.2.0-beta.4") api("com.github.LlamaLad7:MixinExtras:0.2.0-beta.4")
annotationProcessor("com.github.LlamaLad7:MixinExtras:0.2.0-beta.4") annotationProcessor("com.github.LlamaLad7:MixinExtras:0.2.0-beta.4")
} }
} }
private static boolean buildVersionBefore(String minecraft_version, String compareVersion)
{
int sortValue = sortSemanticVersionOldestToNewest(minecraft_version, compareVersion);
return sortValue == -1;
}
/**
* input format: "major.minor.patch"
* needed so we can sort versions with different length strings
* IE: 1.21.1 should come before 1.21.10
*/
private static int sortSemanticVersionOldestToNewest(String version1, String version2)
{
String[] parts1 = version1.split("\\.");
String[] parts2 = version2.split("\\.");
int major1 = Integer.parseInt(parts1[0]);
int major2 = Integer.parseInt(parts2[0]);
if (major1 != major2)
{
return Integer.compare(major1, major2);
}
int minor1 = Integer.parseInt(parts1[1]);
int minor2 = Integer.parseInt(parts2[1]);
if (minor1 != minor2)
{
return Integer.compare(minor1, minor2);
}
int patch1 = Integer.parseInt(parts1[2]);
int patch2 = Integer.parseInt(parts2[2]);
return Integer.compare(patch1, patch2);
}
// ==================== Tasks ====================
task deleteResources(type: Delete) { task deleteResources(type: Delete) {
delete file("build/resources/main") delete file("build/resources/main")
@@ -202,14 +79,12 @@ processResources {
dependsOn(copyCommonLoaderResources) dependsOn(copyCommonLoaderResources)
} }
runClient { tasks.named('runClient') {
dependsOn(copyCoreResources) dependsOn(copyCoreResources)
dependsOn(copyCommonLoaderResources) dependsOn(copyCommonLoaderResources)
// jvmArgs([ "-XX:-OmitStackTraceInFastThrow", minecraftMemoryJavaArg ])
finalizedBy(deleteResources) finalizedBy(deleteResources)
} }
sourcesJar { sourcesJar {
def commonSources = project(":common").sourcesJar def commonSources = project(":common").sourcesJar
dependsOn commonSources dependsOn commonSources
+17 -87
View File
@@ -1,107 +1,38 @@
plugins { plugins {
// Note: This is only needed for multi-loader projects id 'unimined-forge'
// The main architectury loom version is set at the start of the root build.gradle
id "architectury-plugin" version "3.4-SNAPSHOT"
} }
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_21
architectury { // ==================== Mod Dependency Helper ====================
platformSetupLoomIde()
forge()
}
//loom {
// forge {
// convertAccessWideners.set(true)
// extraAccessWideners.add("lod.accesswidener")
// mixinConfigs("DistantHorizons.mixins.json")
// }
//}
loom {
silentMojangMappingsLicense() // Shut the licencing warning
accessWidenerPath = project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener")
forge {
convertAccessWideners = true
extraAccessWideners.add loom.accessWidenerPath.get().asFile.name
mixinConfigs = [
"DistantHorizons.forge.mixins.json"
]
}
// "runs" isn't required, but when we do need it then it can be useful
runs {
client {
client()
setConfigName("Forge Client")
ideConfigGenerated(false) // When true a run configuration file will be generated for IDE's. By default only set to true for the root project.
runDir("../run/client")
vmArgs(
// https://github.com/FabricMC/fabric-loom/issues/915#issuecomment-1609154390
"-Dminecraft.api.auth.host=https://nope.invalid",
"-Dminecraft.api.account.host=https://nope.invalid",
"-Dminecraft.api.session.host=https://nope.invalid",
"-Dminecraft.api.services.host=https://nope.invalid",
// https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
"-Dio.netty.leakDetection.level=advanced"
)
programArgs("--username", "Dev")
}
server {
server()
setConfigName("Forge Server")
ideConfigGenerated(false)
runDir("../run/server")
vmArgs("-Dio.netty.leakDetection.level=advanced")
}
}
}
remapJar {
inputFile = shadowJar.archiveFile
dependsOn shadowJar
}
def addMod(path, enabled) { def addMod(path, enabled) {
if (enabled == "2") if (enabled == "2")
dependencies { implementation(path) } dependencies { modImplementation(path) }
else if (enabled == "1") else if (enabled == "1")
dependencies { modCompileOnly(path) } dependencies { compileOnly(path) }
} }
// ==================== Dependencies ====================
dependencies { dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" // TerraForged
mappings loom.layered() {
// Mojmap mappings
officialMojangMappings()
// Parchment mappings (it adds parameter mappings & javadoc)
parchment("org.parchmentmc.data:parchment-${rootProject.parchment_version}@zip")
}
// Forge
forge "net.minecraftforge:forge:${rootProject.minecraft_version}-${rootProject.forge_version}"
addMod("curse.maven:TerraForged-363820:${rootProject.terraforged_version}", rootProject.enable_terraforged) addMod("curse.maven:TerraForged-363820:${rootProject.terraforged_version}", rootProject.enable_terraforged)
// TerraFirmaCraft
addMod("curse.maven:TerraFirmaCraft-302973:4616004", rootProject.enable_terrafirmacraft) addMod("curse.maven:TerraFirmaCraft-302973:4616004", rootProject.enable_terrafirmacraft)
// TODO: Check if this is still needed and if so ensure this code works for MC 26.1+
if ( // Only run on MC 1.20.6 or later // (potential) hack fix for MC 1.20.6 and later, force jopt-simple to be exactly 5.0.4 because Mojang ships that version, but some transitive dependencies request 6.0+
// FIXME: Add an environment variable for the Major, Minor, and Patch version number of Minecraft def mcParts = rootProject.minecraft_version.split("\\.")
minecraft_version.split("\\.")[1].toInteger() >= 20 && if (mcParts[1].toInteger() >= 20 && (mcParts.length > 2 && mcParts[2].toInteger() >= 6)) {
( implementation('net.sf.jopt-simple:jopt-simple:5.0.4')
minecraft_version.split("\\.").length > 1 && // Incase there isn't a minor version
minecraft_version.split("\\.")[2].toInteger() >= 6
)
) {
// (potential) hack fix, force jopt-simple to be exactly 5.0.4 because Mojang ships that version, but some transitive dependencies request 6.0+
implementation('net.sf.jopt-simple:jopt-simple:5.0.4') //{ version { strictly '5.0.4' } }
} }
} }
// ==================== Tasks ====================
task deleteResources(type: Delete) { task deleteResources(type: Delete) {
delete file("build/resources/main") delete file("build/resources/main")
} }
@@ -119,4 +50,3 @@ tasks.named('runClient') {
dependsOn(tasks.named('copyAllResources')) dependsOn(tasks.named('copyAllResources'))
finalizedBy(deleteResources) finalizedBy(deleteResources)
} }
-1
View File
@@ -1 +0,0 @@
loom.platform=forge
-5
View File
@@ -34,11 +34,6 @@ fastutil_version=8.2.1
log4j_version=2.23.1 log4j_version=2.23.1
joml_version=1.10.2 joml_version=1.10.2
# Architectury config
# this is necessary for MC 1.21.3 because including Sodium and Iris throws "Mod was built with a newer version of Loom (1.8.9), you are using Loom (1.7.415)"
loom.ignoreDependencyLoomVersionValidation=true
# These are here so they can be changed with cmd arguments # These are here so they can be changed with cmd arguments
# If they are null, they would be automatically set # If they are null, they would be automatically set
# (This is mainly used for the CI) # (This is mainly used for the CI)
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
+12 -79
View File
@@ -1,110 +1,43 @@
plugins { plugins {
// Note: This is only needed for multi-loader projects id 'unimined-neoforge'
// The main architectury loom version is set at the start of the root build.gradle
id "architectury-plugin" version "3.4-SNAPSHOT"
}
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
architectury {
platformSetupLoomIde()
neoForge()
}
loom {
silentMojangMappingsLicense() // Shut the licencing warning
accessWidenerPath = project(":common").file("src/main/resources/${accessWidenerVersion}.distanthorizons.accesswidener")
neoForge {
// Access wideners are defined in the `remapJar.atAccessWideners`
// Mixins are defined in the `mods.toml`
}
mixin {
// Mixins are defined in the `mods.toml`
}
// "runs" isn't required, but when we do need it then it can be useful
runs {
client {
client()
setConfigName("NeoForge Client")
ideConfigGenerated(false) // When true a run configuration file will be generated for IDE's. By default only set to true for the root project.
runDir("../run/client")
vmArgs(
"-Dio.netty.leakDetection.level=advanced",
"-XX:+UseZGC") // https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
programArgs(
"--username", "Dev",
// "--renderDebugLabels" is a Mojang command to show render names in RenderDoc
"--renderDebugLabels",
// "--tracy" is a Mojang command to allow individual frames to be debugged using Tracy https://github.com/wolfpld/tracy/releases/tag/v0.13.1
"--tracy")
}
server {
server()
setConfigName("NeoForge Server")
ideConfigGenerated(false)
runDir("../run/server")
vmArgs("-Dio.netty.leakDetection.level=advanced")
}
}
} }
// ==================== Mod Dependency Helper ====================
def addMod(path, enabled) { def addMod(path, enabled) {
if (enabled == "2") if (enabled == "2")
dependencies { implementation(path) } dependencies { modImplementation(path) }
else if (enabled == "1") else if (enabled == "1")
dependencies { modCompileOnly(path) } dependencies { compileOnly(path) }
} }
dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
mappings loom.layered()
{
// Mojmap mappings
officialMojangMappings()
// Parchment mappings (it adds parameter mappings & javadoc)
parchment("org.parchmentmc.data:parchment-${rootProject.parchment_version}@zip")
}
// Neoforge
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
// ==================== Dependencies ====================
dependencies {
// Iris // Iris
addMod("maven.modrinth:iris:${rootProject.neo_iris_version}", rootProject.neo_enable_iris) addMod("maven.modrinth:iris:${rootProject.neo_iris_version}", rootProject.neo_enable_iris)
} }
// ==================== Tasks ====================
task deleteResources(type: Delete) { task deleteResources(type: Delete) {
delete file("build/resources/main") delete file("build/resources/main")
} }
tasks.register('copyAllResources') { processResources {
dependsOn(copyCoreResources) dependsOn(copyCoreResources)
dependsOn(copyCommonLoaderResources) dependsOn(copyCommonLoaderResources)
} }
processResources {
dependsOn(tasks.named('copyAllResources'))
}
tasks.named('runClient') { tasks.named('runClient') {
dependsOn(tasks.named('copyAllResources')) dependsOn(copyCoreResources)
dependsOn(copyCommonLoaderResources)
finalizedBy(deleteResources) finalizedBy(deleteResources)
} }
remapJar {
inputFile = shadowJar.archiveFile
dependsOn shadowJar
atAccessWideners.add("distanthorizons.accesswidener")
}
sourcesJar { sourcesJar {
def commonSources = project(":common").sourcesJar def commonSources = project(":common").sourcesJar
dependsOn commonSources dependsOn commonSources
-1
View File
@@ -1 +0,0 @@
loom.platform=neoForge
+33 -120
View File
@@ -1,49 +1,5 @@
pluginManagement { // Throw an error if the core sub-project wasn't cloned
repositories { if (!file("./coreSubProjects/LICENSE.txt").exists()) {
maven {
name "Fabric"
url "https://maven.fabricmc.net/"
}
maven {
name "Forge"
url "https://maven.minecraftforge.net/"
}
maven {
name "NeoForge Releases"
url "https://maven.neoforged.net/releases/"
}
maven {
name "NeoForge Snapshot"
url "https://maven.neoforged.net/snapshots/"
}
maven {
name "Architectury"
url "https://maven.architectury.dev/"
}
maven {
name "Quilt"
url "https://maven.quiltmc.org/repository/release"
}
maven { // Used for Vanilla Minecraft's libraries
name "Sponge"
url "https://repo.spongepowered.org/repository/maven-public/"
}
maven {
name "ParchmentMC"
url "https://maven.parchmentmc.org"
}
mavenCentral()
gradlePluginPortal()
// Not needed, but useful for debugging gradle plugins
mavenLocal()
}
}
// Throw an error and a little help message if the user forgot to clone the core sub-project
if (!file("./coreSubProjects/LICENSE.txt").exists()) { // the LICENCE.txt file should always, and only exist if the core-sub-project was cloned
println(''' println('''
It seems that the core sub project was not included... It seems that the core sub project was not included...
please make sure that when you were cloning the repo, you were using the `--recurse-submodules` flag on git. please make sure that when you were cloning the repo, you were using the `--recurse-submodules` flag on git.
@@ -55,98 +11,55 @@ If you still need help with compiling, please read the Readme.md
} }
def loadVersionProperties() {
def mcVers = fileTree("versionProperties").files.collect { it.name.replaceAll("\\.properties", "") }
.sort { a, b ->
def aParts = a.tokenize('.'); def bParts = b.tokenize('.')
for (int i = 0; i < Math.min(aParts.size(), bParts.size()); i++) {
def aNum = aParts[i].isInteger() ? aParts[i].toInteger() : aParts[i]
def bNum = bParts[i].isInteger() ? bParts[i].toInteger() : bParts[i]
def compare = aNum <=> bNum
if (compare != 0) return compare
}
return aParts.size() <=> bParts.size()
}
def mcVersion = hasProperty("mcVer") ? mcVer : ""
def mcIndex = mcVers.indexOf(mcVersion)
/** Loads the VersionProperties fiel for the currently selected Minecraft version. */ if (mcIndex == -1) {
def loadProperties() def defaultVersion = "1.20.1"
{ println "No mcVer set or invalid. Defaulting to ${defaultVersion}."
def defaultMcVersion = "1.20.1" // 1.20.1 is our current most stable version so we use that if no version was defined println "Tip: Use -PmcVer=\"${defaultVersion}\" to set the MC version."
mcVersion = defaultVersion
def mcVersion = "" mcIndex = mcVers.indexOf(defaultVersion)
def mcVers = fileTree("versionProperties").files.name // Get all the files in "versionProperties" assert mcIndex != -1 : "Default MC version ${defaultVersion} not found in ${mcVers}"
for (int i = 0; i < mcVers.size(); i++)
{
String version = mcVers[i];
version = version.replaceAll("\\.properties", "") // As we are getting the file names, we should remove the ".properties" at the end to get the versions
mcVers[i] = version;
} }
mcVers.sort((a,b) -> sortSemanticVersionOldestToNewest(a,b)) // Sort so it always goes from oldest to newest println "Available MC versions: ${mcVers}"
println "Loading properties file: ${mcVersion}.properties"
int mcIndex = -1
println "Avalible MC versions: ${mcVers}"
if (hasProperty("mcVer"))
{
mcVersion = mcVer
mcIndex = mcVers.indexOf(mcVer)
}
if (mcIndex == -1)
{
println "No mcVer set or the set mcVer is invalid! Defaulting to ${defaultMcVersion}."
println "Tip: Use -PmcVer=\"${defaultMcVersion}\" in cmd arg to set mcVer."
mcVersion = defaultMcVersion
mcIndex = mcVers.indexOf(defaultMcVersion)
assert mcIndex != -1
}
println "Loading properties file at " + mcVersion + ".properties"
def props = new Properties() def props = new Properties()
props.load(new FileInputStream("$rootDir/versionProperties/"+"$mcVersion"+".properties")) props.load(new FileInputStream("$rootDir/versionProperties/${mcVersion}.properties"))
props.each { prop -> props.each { key, value -> gradle.ext.set(key, value) }
gradle.ext.set(prop.key, prop.value)
// println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
}
gradle.ext.mcVers = mcVers gradle.ext.mcVers = mcVers
gradle.ext.mcIndex = mcIndex gradle.ext.mcIndex = mcIndex
} }
/** loadVersionProperties()
* input format: "major.minor.patch"
* needed so we can sort versions with different length strings
* IE: 1.21.1 should come before 1.21.10
*/
private static int sortSemanticVersionOldestToNewest(String version1, String version2)
{
String[] parts1 = version1.split("\\.");
String[] parts2 = version2.split("\\.");
int major1 = Integer.parseInt(parts1[0]);
int major2 = Integer.parseInt(parts2[0]);
if (major1 != major2)
{
return Integer.compare(major1, major2);
}
int minor1 = Integer.parseInt(parts1[1]);
int minor2 = Integer.parseInt(parts2[1]);
if (minor1 != minor2)
{
return Integer.compare(minor1, minor2);
}
int patch1 = Integer.parseInt(parts1[2]);
int patch2 = Integer.parseInt(parts2[2]);
return Integer.compare(patch1, patch2);
}
loadProperties()
// Minecraft-independent sub-projects
// Minecraft independent sub-projects
include("core") include("core")
project(":core").projectDir = file('coreSubProjects/core') project(":core").projectDir = file('coreSubProjects/core')
include("api") include("api")
project(":api").projectDir = file('coreSubProjects/api') project(":api").projectDir = file('coreSubProjects/api')
// Minecraft dependent sub-projects // Minecraft-dependent sub-projects
include("common") include("common")
// Enables or disables the subprojects depending on whats in the versionProperties/mcVer.properties ((String) gradle.builds_for).split(",").each { loader ->
for (loader in ((String) gradle.builds_for).split(",")) { def loaderName = loader.trim()
def loaderName = loader.strip() // Strip it in case a space is added before or after the comma println "Adding loader: ${loaderName}"
println "Adding loader " + loaderName
include(loaderName) include(loaderName)
} }
+1 -1
View File
@@ -47,7 +47,7 @@ fabric_api_version=0.97.8+1.20.6
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=20.6.136 neoforge_version=136
neoforge_version_range=[*,) neoforge_version_range=[*,)
# NeoForge mod versions # NeoForge mod versions
+1 -1
View File
@@ -47,7 +47,7 @@ fabric_api_version=0.115.0+1.21.1
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.1.216 neoforge_version=216
neoforge_version_range=[*,) neoforge_version_range=[*,)
# NeoForge mod versions # NeoForge mod versions
+1 -1
View File
@@ -45,7 +45,7 @@ fabric_api_version=0.138.3+1.21.10
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.10.56-beta neoforge_version=56-beta
neoforge_version_range=[21.10.6-beta,) neoforge_version_range=[21.10.6-beta,)
# NeoForge mod versions # NeoForge mod versions
+1 -1
View File
@@ -45,7 +45,7 @@ fabric_api_version=0.139.4+1.21.11
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.11.38-beta neoforge_version=38-beta
neoforge_version_range=[*,) neoforge_version_range=[*,)
# NeoForge mod versions # NeoForge mod versions
+1 -1
View File
@@ -47,7 +47,7 @@ fabric_api_version=0.110.0+1.21.3
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.3.86 neoforge_version=86
neoforge_version_range=[*,) neoforge_version_range=[*,)
# NeoForge mod versions # NeoForge mod versions
+1 -1
View File
@@ -46,7 +46,7 @@ fabric_api_version=0.110.5+1.21.4
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.4.147 neoforge_version=147
# version range may not be necessary, but having compiled DH for an older version caused issues with shaders # version range may not be necessary, but having compiled DH for an older version caused issues with shaders
neoforge_version_range=[21.4.147,) neoforge_version_range=[21.4.147,)
+1 -1
View File
@@ -46,7 +46,7 @@ fabric_api_version=0.119.5+1.21.5
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.5.87 neoforge_version=87
neoforge_version_range=[*,) neoforge_version_range=[*,)
# NeoForge mod versions # NeoForge mod versions
+1 -1
View File
@@ -45,7 +45,7 @@ fabric_api_version=0.127.0+1.21.6
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.6.20-beta neoforge_version=20-beta
# around 6.19 neo changed how their render API works, failing to meet this causes the game to crash # around 6.19 neo changed how their render API works, failing to meet this causes the game to crash
neoforge_version_range=[21.6.19-beta,) neoforge_version_range=[21.6.19-beta,)
+1 -1
View File
@@ -45,7 +45,7 @@ fabric_api_version=0.133.4+1.21.8
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.8.52 neoforge_version=52
# around 6.19 neo changed how their render API works, failing to meet this causes the game to crash # around 6.19 neo changed how their render API works, failing to meet this causes the game to crash
neoforge_version_range=[*,) neoforge_version_range=[*,)
+1 -1
View File
@@ -45,7 +45,7 @@ fabric_api_version=0.134.0+1.21.9
# NeoForge loader # NeoForge loader
forge_version= forge_version=
neoforge_version=21.9.15-beta neoforge_version=15-beta
# sometime before 21.9.15-beta Neoforge changed how their rendering API events handle levels # sometime before 21.9.15-beta Neoforge changed how their rendering API events handle levels
# so we can't support both versions at once # so we can't support both versions at once
neoforge_version_range=[21.9.15-beta,) neoforge_version_range=[21.9.15-beta,)