diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index f24c21d..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,133 +0,0 @@
-plugins {
-	id "fabric-loom" version "1.6-SNAPSHOT"
-}
-
-sourceSets {
-    main {
-        resources {
-            srcDirs += ['src/main/generated']
-        }
-    }
-
-    testmod {
-        compileClasspath += main.compileClasspath
-        runtimeClasspath += main.runtimeClasspath
-    }
-}
-
-loom {
-    accessWidenerPath = file("src/main/resources/neoskies.accesswidener")
-
-    runs {
-        datagenServer {
-            server()
-            name "Data Generation"
-            vmArg "-Dfabric-api.datagen"
-            vmArg "-Dfabric-api.datagen.output-dir=${file("src/main/generated")}"
-            vmArg "-Dfabric-api.datagen.modid=neoskies"
-
-            ideConfigGenerated = true
-            runDir "build/datagen"
-        }
-
-        testmodServer {
-            server()
-            name = "Testmod Server"
-            source sourceSets.testmod
-        }
-
-        testmodClient {
-            client()
-            name = "Testmod Client"
-            runDir("run_client")
-            source sourceSets.testmod
-        }
-    }
-}
-
-archivesBaseName = project.archives_base_name
-version = project.mod_version
-group = project.maven_group
-
-repositories {
-    mavenLocal()
-	maven { url "https://maven.nucleoid.xyz" }
-	maven { url "https://maven.awakenedredstone.com" }
-	maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
-	maven { url "https://maven.ladysnake.org/releases" }
-    maven { url "https://maven.isxander.dev/releases" }
-    maven { url "https://jitpack.io" }
-    maven {
-        name = "Modrinth"
-        url = "https://api.modrinth.com/maven"
-        content {
-            includeGroup "maven.modrinth"
-        }
-    }
-}
-
-dependencies {
-    //region Fabric
-	minecraft "com.mojang:minecraft:${project.minecraft_version}"
-	mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
-	modImplementation "net.fabricmc:fabric-loader:${project.fabric_loader}"
-	modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api}"
-    //endregion
-    // region Cardinal Components
-    modImplementation "org.ladysnake.cardinal-components-api:cardinal-components-api:${project.cardinal_components_api}"
-	include "org.ladysnake.cardinal-components-api:cardinal-components-base:${project.cardinal_components_api}"
-	include "org.ladysnake.cardinal-components-api:cardinal-components-world:${project.cardinal_components_api}"
-    // endregion
-    // region Nucleoid
-    modImplementation include("xyz.nucleoid:fantasy:${project.fantasy}")
-    modImplementation include("xyz.nucleoid:stimuli:${project.stimuli}")
-    modImplementation include("xyz.nucleoid:server-translations-api:${project.server_translations_api}")
-    //endregion
-    // region Patbox
-    modImplementation include("eu.pb4:sgui:${project.server_gui}")
-    modImplementation include("eu.pb4:placeholder-api:${project.placeholder_api}")
-    modImplementation include("eu.pb4:common-economy-api:${project.common_economy_api}")
-    modImplementation include("eu.pb4:common-protection-api:${project.common_protection_api}")
-    //region Polymer
-    modImplementation include("eu.pb4:polymer-core:${project.polymer}")
-    modImplementation include("eu.pb4:polymer-resource-pack:${project.polymer}")
-    modImplementation include("eu.pb4:polymer-virtual-entity:${project.polymer}")
-    //endregion
-    //endregion
-    // region Others
-    modImplementation include("maven.modrinth:particleanimationlib:0.0.2+1.20")
-    modImplementation include("me.lucko:fabric-permissions-api:${project.fabric_permission_api}")
-    //endregion
-    // region Non mod dependencies
-    include api("blue.endless:jankson:${project.jankson_version}")
-    //endregion
-
-    // region Tests
-    testmodImplementation sourceSets.main.output
-    //endregion
-}
-
-processResources {
-	inputs.property "version", project.version
-	filesMatching("fabric.mod.json") {
-		expand "version": project.version
-	}
-}
-
-tasks.withType(JavaCompile).configureEach {
-	it.options.encoding = "UTF-8"
-    //noinspection GroovyAssignabilityCheck
-    it.options.release = 21
-}
-
-java {
-	sourceCompatibility = JavaVersion.VERSION_21
-	targetCompatibility = JavaVersion.VERSION_21
-	withSourcesJar()
-}
-
-jar {
-	from("LICENSE") {
-		rename { "${it}_${project.archivesBaseName}" }
-	}
-}
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..c627313
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,214 @@
+import java.io.File
+import com.modrinth.minotaur.dependencies.ModDependency
+
+plugins {
+    id("signing")
+    id("maven-publish")
+    id("fabric-loom") version "1.6-SNAPSHOT"
+    id("com.modrinth.minotaur") version "2.+"
+}
+
+val CHANGELOG: String =
+    if (file("CHANGELOG.md").exists()) {
+        file("CHANGELOG.md").readText()
+    } else {
+        "No changelog provided"
+    }
+
+fun file(path: String): File {
+    return rootProject.file(path)
+}
+
+sourceSets {
+    main {
+        resources {
+            srcDirs("src/main/generated")
+        }
+    }
+
+    create("testmod") {
+        compileClasspath += sourceSets.main.get().compileClasspath
+        runtimeClasspath += sourceSets.main.get().runtimeClasspath
+    }
+}
+
+loom {
+    accessWidenerPath.set(file("src/main/resources/neoskies.accesswidener"))
+
+    runs {
+        create("datagenServer") {
+            server()
+            name = "Data Generation"
+            vmArg("-Dfabric-api.datagen")
+            vmArg("-Dfabric-api.datagen.output-dir=${file("src/main/generated")}")
+            vmArg("-Dfabric-api.datagen.modid=neoskies")
+
+            //ideConfigGenerated = true
+            runDir = "build/datagen"
+        }
+
+        create("testmodServer") {
+            server()
+            name = "Testmod Server"
+            source(sourceSets.getByName("testmod"))
+        }
+
+        create("testmodClient") {
+            client()
+            name = "Testmod Client"
+            runDir("run_client")
+            source(sourceSets.getByName("testmod"))
+        }
+    }
+}
+
+var archivesBaseName: String = property("archives_base_name").toString()
+base {
+    archivesName.set(property("archives_base_name").toString())
+}
+version = property("mod_version")!!
+group = property("maven_group")!!
+
+repositories {
+    mavenLocal()
+	maven("https://maven.nucleoid.xyz")
+	maven("https://maven.awakenedredstone.com")
+	maven("https://oss.sonatype.org/content/repositories/snapshots")
+	maven("https://maven.ladysnake.org/releases")
+    maven("https://maven.isxander.dev/releases")
+    maven("https://jitpack.io")
+    maven {
+        name = "Modrinth"
+        url = uri("https://api.modrinth.com/maven")
+        content {
+            includeGroup("maven.modrinth")
+        }
+    }
+}
+
+dependencies {
+    //region Fabric
+	minecraft("com.mojang:minecraft:${property("minecraft_version")}")
+	mappings("net.fabricmc:yarn:${property("yarn_mappings")}:v2")
+	modImplementation("net.fabricmc:fabric-loader:${property("fabric_loader")}")
+	modImplementation("net.fabricmc.fabric-api:fabric-api:${property("fabric_api")}")
+    //endregion
+    // region Cardinal Components
+    modImplementation("org.ladysnake.cardinal-components-api:cardinal-components-api:${property("cardinal_components_api")}")
+	include("org.ladysnake.cardinal-components-api:cardinal-components-base:${property("cardinal_components_api")}")
+	include("org.ladysnake.cardinal-components-api:cardinal-components-world:${property("cardinal_components_api")}")
+    // endregion
+    // region Nucleoid
+    modImplementation(include("xyz.nucleoid:fantasy:${property("fantasy")}") as Any)
+    modImplementation(include("xyz.nucleoid:stimuli:${property("stimuli")}") as Any)
+    modImplementation(include("xyz.nucleoid:server-translations-api:${property("server_translations_api")}") as Any)
+    //endregion
+    // region Patbox
+    modImplementation(include("eu.pb4:sgui:${property("server_gui")}") as Any)
+    modImplementation(include("eu.pb4:placeholder-api:${property("placeholder_api")}") as Any)
+    modImplementation(include("eu.pb4:common-economy-api:${property("common_economy_api")}") as Any)
+    modImplementation(include("eu.pb4:common-protection-api:${property("common_protection_api")}") as Any)
+    //region Polymer
+    modImplementation(include("eu.pb4:polymer-core:${property("polymer")}") as Any)
+    modImplementation(include("eu.pb4:polymer-resource-pack:${property("polymer")}") as Any)
+    modImplementation(include("eu.pb4:polymer-virtual-entity:${property("polymer")}") as Any)
+    //endregion
+    //endregion
+    // region Others
+    modImplementation(include("maven.modrinth:particleanimationlib:0.0.2+1.20") as Any)
+    modImplementation(include("me.lucko:fabric-permissions-api:${property("fabric_permission_api")}") as Any)
+    //endregion
+    // region Non mod dependencies
+    include(api("blue.endless:jankson:${property("jankson_version")}") as Any)
+    //endregion
+
+    // region Tests
+    "testmodImplementation"(sourceSets.main.get().output)
+    //endregion
+}
+
+tasks.processResources {
+    val map = mapOf(
+        "version" to version
+    )
+
+    inputs.properties(map)
+
+    filesMatching("fabric.mod.json") {
+        expand(map)
+    }
+}
+
+tasks.withType<JavaCompile> {
+    options.encoding = "UTF-8"
+    options.release = 21
+}
+
+java {
+	sourceCompatibility = JavaVersion.VERSION_21
+	targetCompatibility = JavaVersion.VERSION_21
+	withSourcesJar()
+    withJavadocJar()
+}
+
+tasks.jar {
+    from("LICENSE") {
+        rename { "${it}_${property("archivesBaseName")}" }
+    }
+}
+
+publishing {
+    repositories {
+        maven {
+            name = "maven"
+            url = uri(project.mavenRepositoryUrl)
+            credentials {
+                username = project.mavenRepositoryUsername
+                password = project.mavenRepositoryPassword
+            }
+        }
+    }
+    publications {
+        create<MavenPublication>("main") {
+            from(components["java"])
+            pom.default()
+        }
+    }
+}
+
+signing {
+    useGpgCmd()
+    sign(publishing.publications["main"])
+}
+
+modrinth {
+    val projectVersion: String = property("mod_version").toString()
+    val projectVersionNumber: List<String> = projectVersion.split(Regex("-"), 2)
+
+    var releaseName = "Release ${projectVersionNumber[0]}"
+    if (projectVersion.contains("beta")) {
+        val projectBeta: List<String> = projectVersionNumber[1].split(Regex("\\."), 2)
+        releaseName = "${projectVersionNumber[0]} - Beta ${projectBeta[1]}"
+        versionType = "beta"
+    } else if (projectVersion.contains("alpha")) {
+        val projectAlpha: List<String> = projectVersionNumber[1].split(Regex("\\."), 2)
+        releaseName = "${projectVersionNumber[0]} - Alpha ${projectAlpha[1]}"
+        versionType = "alpha"
+    } else if (projectVersion.contains("rc")) {
+        val projectRC: List<String> = projectVersionNumber[1].split(Regex("\\."), 2)
+        releaseName = "${projectVersionNumber[0]} - Release Candidate ${projectRC[1]}"
+        versionType = "beta"
+    }
+
+    token = System.getenv("MODRINTH_TOKEN")
+    projectId = "YowGXm51"
+    versionName = releaseName
+    changelog = CHANGELOG
+    uploadFile = tasks.getByName("remapJar")
+    syncBodyFrom = file("README.md").readText()
+    dependencies = listOf(
+        ModDependency("fabric-api", "required"),
+        ModDependency("luckperms", "optional"),
+        ModDependency("placeholder-api", "embedded")
+    )
+}
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
new file mode 100644
index 0000000..b6413e3
--- /dev/null
+++ b/buildSrc/build.gradle.kts
@@ -0,0 +1,7 @@
+plugins {
+	`kotlin-dsl`
+}
+
+repositories {
+	mavenCentral()
+}
diff --git a/buildSrc/src/main/kotlin/globals.kt b/buildSrc/src/main/kotlin/globals.kt
new file mode 100644
index 0000000..9efc07d
--- /dev/null
+++ b/buildSrc/src/main/kotlin/globals.kt
@@ -0,0 +1,10 @@
+import org.gradle.api.Project
+
+val Project.mavenRepositoryUrl: String
+	get() = System.getenv("MAVEN_REPO") ?: ""
+
+val Project.mavenRepositoryUsername: String
+	get() = System.getenv("MAVEN_AUTH_USERNAME") ?: ""
+
+val Project.mavenRepositoryPassword: String
+	get() = System.getenv("MAVEN_AUTH_KEY") ?: ""
diff --git a/buildSrc/src/main/kotlin/project.kt b/buildSrc/src/main/kotlin/project.kt
new file mode 100644
index 0000000..7395af6
--- /dev/null
+++ b/buildSrc/src/main/kotlin/project.kt
@@ -0,0 +1,38 @@
+import org.gradle.api.publish.maven.MavenPom
+import org.gradle.api.publish.maven.MavenPomDeveloperSpec
+
+fun MavenPom.default() {
+	url.set("https://awakenedredstone.com")
+	issueManagement {
+		system.set("GitHub")
+		url.set("https://github.com/Awakened-Redstone/neoskies/issues")
+	}
+	inceptionYear.set("2024")
+	developers { all }
+	licenses {
+		license {
+			name.set("GNU Lesser General Public License version 3")
+			distribution.set("repo")
+			url.set("https://opensource.org/license/lgpl-3-0")
+		}
+	}
+	scm {
+		connection.set("scm:git:https://github.com/Awakened-Redstone/neoskies.git")
+		developerConnection.set("scm:git:git@github.com:Awakened-Redstone/neoskies.git")
+		url.set("https://github.com/Awakened-Redstone/neoskies")
+	}
+}
+
+val MavenPomDeveloperSpec.all: Unit
+	get() {
+        AwakenedRedstone()
+	}
+
+fun MavenPomDeveloperSpec.AwakenedRedstone() {
+	developer {
+		id.set("Awakened-Redstone")
+		name.set("Awakened Redstone")
+		email.set("git@awakenedredstone.com")
+		roles.addAll("owner", "maintainer")
+	}
+}
diff --git a/settings.gradle b/settings.gradle.kts
similarity index 64%
rename from settings.gradle
rename to settings.gradle.kts
index cf0fb6c..198d1c4 100644
--- a/settings.gradle
+++ b/settings.gradle.kts
@@ -2,6 +2,6 @@ pluginManagement {
 	repositories {
 		mavenCentral()
 		gradlePluginPortal()
-		maven { url "https://maven.fabricmc.net" }
+		maven("https://maven.fabricmc.net")
 	}
 }