aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornea <romangraef@gmail.com>2022-07-12 14:20:22 +0200
committernea <romangraef@gmail.com>2022-07-12 14:20:22 +0200
commit372eec27e5e0c8ef796ed9e6bcdc68a10df84718 (patch)
tree425ab1a282196a68819da297c670e9170a8c514a
downloadFirmament-372eec27e5e0c8ef796ed9e6bcdc68a10df84718.tar.gz
Firmament-372eec27e5e0c8ef796ed9e6bcdc68a10df84718.tar.bz2
Firmament-372eec27e5e0c8ef796ed9e6bcdc68a10df84718.zip
initial
-rw-r--r--.gitignore27
-rw-r--r--README.md6
-rw-r--r--build.gradle.kts84
-rw-r--r--common/build.gradle.kts36
-rw-r--r--common/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt140
-rw-r--r--common/src/main/kotlin/net/examplemod/ExampleExpectPlatform.kt30
-rw-r--r--common/src/main/kotlin/net/examplemod/ExampleMod.kt31
-rw-r--r--common/src/main/kotlin/net/examplemod/mixin/MixinTitleScreen.kt23
-rw-r--r--common/src/main/resources/architectury.common.json3
-rw-r--r--common/src/main/resources/assets/examplemod/lang/en_us.json3
-rw-r--r--common/src/main/resources/notenoughupdates-common.mixins.json13
-rw-r--r--common/src/main/resources/notenoughupdates.accesswidener1
-rw-r--r--fabric/build.gradle.kts108
-rw-r--r--fabric/src/main/kotlin/net/examplemod/fabric/ExampleExpectPlatformImpl.kt13
-rw-r--r--fabric/src/main/kotlin/net/examplemod/fabric/ExampleModFabric.kt10
-rw-r--r--fabric/src/main/resources/fabric.mod.json34
-rw-r--r--fabric/src/main/resources/notenoughupdates.mixins.json12
-rw-r--r--forge/build.gradle.kts108
-rw-r--r--forge/gradle.properties1
-rw-r--r--forge/src/main/kotlin/net/examplemod/forge/ExampleExpectPlatformImpl.kt14
-rw-r--r--forge/src/main/kotlin/net/examplemod/forge/ExampleModForge.kt16
-rw-r--r--forge/src/main/resources/META-INF/mods.toml35
-rw-r--r--forge/src/main/resources/examplemod.mixins.json12
-rw-r--r--forge/src/main/resources/pack.mcmeta6
-rw-r--r--gradle.properties25
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin0 -> 59203 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xgradlew234
-rw-r--r--gradlew.bat89
-rw-r--r--quilt/build.gradle.kts118
-rw-r--r--quilt/gradle.properties1
-rw-r--r--quilt/src/main/kotlin/net/examplemod/fabric/ExampleExpectPlatformImpl.kt13
-rw-r--r--quilt/src/main/kotlin/net/examplemod/quilt/ExampleModQuilt.kt12
-rw-r--r--quilt/src/main/resources/quilt.mod.json45
-rw-r--r--settings.gradle.kts25
35 files changed, 1333 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0b1f198
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+.gradle
+/build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# Cache of project
+.gradletasknamecache
+
+# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
+# gradle/wrapper/gradle-wrapper.properties
+
+# IDEA
+/.idea/
+
+# Architectury-loom runClient
+/common/build/
+/forge/build/
+/fabric/build/
+/quilt/build/
+/forge/run/
+/fabric/run/
+/quilt/run/
+/run/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..afff4cf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+# architectury-template-kotlin-dsl
+architectury template with kotlin-dsl
+
+Based on [Architectury-templates(1.18.2-forge-fabric-quilt-mixin)](https://github.com/architectury/architectury-templates/releases)
+
+If you find bugs, please open a issues or PR to help me fix bugs. \ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..162f269
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,84 @@
+import net.fabricmc.loom.api.LoomGradleExtensionAPI
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+ java
+ `kotlin-dsl`
+ id("architectury-plugin") version "3.4-SNAPSHOT"
+ id("dev.architectury.loom") version "0.12.0.+" apply false
+}
+
+architectury {
+ minecraft = rootProject.property("minecraft_version").toString()
+}
+
+subprojects {
+ apply(plugin = "dev.architectury.loom")
+
+ val loom = project.extensions.getByName<LoomGradleExtensionAPI>("loom")
+
+
+ dependencies {
+ "minecraft"("com.mojang:minecraft:${project.property("minecraft_version")}")
+ // The following line declares the mojmap mappings, you may use other mappings as well
+ "mappings"(
+ loom.officialMojangMappings()
+ )
+ // The following line declares the yarn mappings you may select this one as well.
+ // "mappings"("net.fabricmc:yarn:1.18.2+build.3:v2")
+ }
+}
+
+allprojects {
+ apply(plugin = "java")
+ apply(plugin = "architectury-plugin")
+ apply(plugin = "maven-publish")
+ apply(plugin = "org.jetbrains.kotlin.jvm")
+
+ base.archivesName.set(rootProject.property("archives_base_name").toString())
+ //base.archivesBaseName = rootProject.property("archives_base_name").toString()
+ version = rootProject.property("mod_version").toString()
+ group = rootProject.property("maven_group").toString()
+
+ repositories {
+ // Add repositories to retrieve artifacts from in here.
+ // You should only use this when depending on other mods because
+ // Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
+ // See https://docs.gradle.org/current/userguide/declaring_repositories.html
+ // for more information about repositories.
+ maven("https://maven.terraformersmc.com/releases/")
+ maven("https://maven.shedaniel.me")
+ maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1")
+ maven("https://api.modrinth.com/maven") {
+ content {
+ includeGroup("maven.modrinth")
+ }
+ }
+ mavenLocal()
+ }
+
+ dependencies {
+ "compileClasspath"("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21")
+ implementation("io.github.moulberry:neurepoparser:0.0.1")
+ }
+
+ tasks.withType<JavaCompile> {
+ options.encoding = "UTF-8"
+ options.release.set(17)
+ }
+
+ java {
+ withSourcesJar()
+ toolchain.languageVersion.set(JavaLanguageVersion.of(17))
+ }
+
+ // could not set to 17, up to 16
+ val compileKotlin: KotlinCompile by tasks
+ compileKotlin.kotlinOptions {
+ jvmTarget = "16"
+ }
+ val compileTestKotlin: KotlinCompile by tasks
+ compileTestKotlin.kotlinOptions {
+ jvmTarget = "16"
+ }
+}
diff --git a/common/build.gradle.kts b/common/build.gradle.kts
new file mode 100644
index 0000000..17146d0
--- /dev/null
+++ b/common/build.gradle.kts
@@ -0,0 +1,36 @@
+plugins {
+ `maven-publish`
+}
+
+architectury {
+ val enabled_platforms: String by rootProject
+ common(enabled_platforms.split(","))
+}
+
+loom {
+ accessWidenerPath.set(file("src/main/resources/notenoughupdates.accesswidener"))
+}
+
+dependencies {
+ // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
+ // Do NOT use other classes from fabric loader
+ modImplementation("net.fabricmc:fabric-loader:${rootProject.property("fabric_loader_version")}")
+ // Remove the next line if you don't want to depend on the API
+ modApi("dev.architectury:architectury:${rootProject.property("architectury_version")}")
+ modCompileOnly("me.shedaniel:RoughlyEnoughItems-api:${rootProject.property("rei_version")}")
+ implementation(kotlin("stdlib-jdk8"))
+}
+
+publishing {
+ publications {
+ create<MavenPublication>("maven") {
+ artifactId = rootProject.property("archives_base_name").toString()
+ from(components.getByName("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.
+ }
+}
diff --git a/common/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt b/common/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt
new file mode 100644
index 0000000..de8c689
--- /dev/null
+++ b/common/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt
@@ -0,0 +1,140 @@
+package moe.nea.notenoughupdates.rei
+
+import com.mojang.blaze3d.vertex.PoseStack
+import io.github.moulberry.repo.NEURepository
+import me.shedaniel.math.Point
+import me.shedaniel.math.Rectangle
+import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer
+import me.shedaniel.rei.api.client.gui.widgets.Tooltip
+import me.shedaniel.rei.api.client.plugins.REIClientPlugin
+import me.shedaniel.rei.api.client.registry.entry.EntryRegistry
+import me.shedaniel.rei.api.common.entry.EntrySerializer
+import me.shedaniel.rei.api.common.entry.EntryStack
+import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext
+import me.shedaniel.rei.api.common.entry.type.EntryDefinition
+import me.shedaniel.rei.api.common.entry.type.EntryType
+import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
+import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
+import me.shedaniel.rei.api.common.util.EntryStacks
+import net.minecraft.core.Registry
+import net.minecraft.network.chat.Component
+import net.minecraft.network.chat.TextComponent
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.tags.TagKey
+import net.minecraft.world.item.Item
+import net.minecraft.world.item.ItemStack
+import net.minecraft.world.item.Items
+import net.minecraft.world.item.enchantment.Enchantments
+import java.nio.file.Path
+import java.util.stream.Stream
+
+
+class NEUReiPlugin : REIClientPlugin {
+
+ data class SBItem(val sbname: String, val backing: Item)
+ companion object {
+
+ fun EntryStack<NEUReiPlugin.SBItem>.asItemStack() =
+ EntryStack.of(VanillaEntryTypes.ITEM, ItemStack(this.value.backing).also {
+ it.enchant(Enchantments.BINDING_CURSE, 1)
+ it.hoverName = TextComponent(value.sbname)
+ })
+
+ val hehe = ResourceLocation("notenoughupdates", "skyblockitems")
+ }
+
+ object SBItemEntryDefinition : EntryDefinition<SBItem> {
+ override fun equals(o1: SBItem?, o2: SBItem?, context: ComparisonContext?): Boolean {
+ return o1 == o2
+ }
+
+ override fun getValueType(): Class<SBItem> = SBItem::class.java
+ override fun getType(): EntryType<SBItem> =
+ EntryType.deferred(hehe)
+
+ override fun getRenderer(): EntryRenderer<SBItem> = object : EntryRenderer<SBItem> {
+ override fun render(
+ entry: EntryStack<SBItem>,
+ matrices: PoseStack,
+ bounds: Rectangle,
+ mouseX: Int,
+ mouseY: Int,
+ delta: Float
+ ) {
+ VanillaEntryTypes.ITEM.definition.renderer
+ .render(
+ entry.asItemStack(),
+ matrices, bounds, mouseX, mouseY, delta
+ )
+ }
+
+ override fun getTooltip(entry: EntryStack<SBItem>, mouse: Point): Tooltip? {
+ return VanillaEntryTypes.ITEM.definition.renderer
+ .getTooltip(entry.asItemStack(), mouse)
+ }
+
+ }
+
+ override fun getSerializer(): EntrySerializer<SBItem>? {
+ return null
+ }
+
+ override fun getTagsFor(entry: EntryStack<SBItem>?, value: SBItem?): Stream<out TagKey<*>> {
+ return Stream.empty()
+ }
+
+ override fun asFormattedText(entry: EntryStack<SBItem>, value: SBItem): Component {
+ return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemStack(), ItemStack(value.backing))
+ }
+
+ override fun hash(entry: EntryStack<SBItem>, value: SBItem, context: ComparisonContext): Long {
+ return value.sbname.hashCode().toLong()
+ }
+
+ override fun wildcard(entry: EntryStack<SBItem>, value: SBItem): SBItem {
+ return value
+ }
+
+ override fun normalize(entry: EntryStack<SBItem>, value: SBItem): SBItem {
+ return value
+ }
+
+ override fun copy(entry: EntryStack<SBItem>?, value: SBItem): SBItem {
+ return value.copy()
+ }
+
+ override fun isEmpty(entry: EntryStack<SBItem>?, value: SBItem?): Boolean {
+ return false
+ }
+
+ override fun getIdentifier(entry: EntryStack<SBItem>?, value: SBItem): ResourceLocation? {
+ return ResourceLocation("skyblockitem", value.sbname)
+ }
+
+
+ }
+
+ val neuRepo = NEURepository.of(Path.of("NotEnoughUpdates-REPO")).also {
+ it.reload()
+ }
+
+ override fun registerEntryTypes(registry: EntryTypeRegistry) {
+ registry.register(hehe, SBItemEntryDefinition)
+ }
+
+ override fun registerEntries(registry: EntryRegistry) {
+ neuRepo.items.items.values.forEach {
+ println("Adding item: $it")
+ registry.addEntry(
+ EntryStack.of(
+ SBItemEntryDefinition, SBItem(
+ it.skyblockItemId.lowercase().replace(";", "__"), Registry.ITEM.get(ResourceLocation(it.minecraftItemId))
+ )
+ )
+ )
+ }
+ registry.addEntry(EntryStacks.of(ItemStack(Items.DIAMOND).also {
+ it.enchant(Enchantments.ALL_DAMAGE_PROTECTION, 10)
+ }))
+ }
+}
diff --git a/common/src/main/kotlin/net/examplemod/ExampleExpectPlatform.kt b/common/src/main/kotlin/net/examplemod/ExampleExpectPlatform.kt
new file mode 100644
index 0000000..4949054
--- /dev/null
+++ b/common/src/main/kotlin/net/examplemod/ExampleExpectPlatform.kt
@@ -0,0 +1,30 @@
+package net.examplemod
+
+import dev.architectury.injectables.annotations.ExpectPlatform
+import dev.architectury.platform.Platform
+import java.nio.file.Path
+
+object ExampleExpectPlatform {
+ /**
+ * We can use [Platform.getConfigFolder] but this is just an example of [ExpectPlatform].
+ *
+ *
+ * This must be a **public static** method. The platform-implemented solution must be placed under a
+ * platform sub-package, with its class suffixed with `Impl`.
+ *
+ *
+ * Example:
+ * Expect: net.examplemod.ExampleExpectPlatform#getConfigDirectory()
+ * Actual Fabric: net.examplemod.fabric.ExampleExpectPlatformImpl#getConfigDirectory()
+ * Actual Forge: net.examplemod.forge.ExampleExpectPlatformImpl#getConfigDirectory()
+ *
+ *
+ * [You should also get the IntelliJ plugin to help with @ExpectPlatform.](https://plugins.jetbrains.com/plugin/16210-architectury)
+ */
+ @ExpectPlatform
+ @JvmStatic
+ fun getConfigDirectory(): Path {
+ // Just throw an error, the content should get replaced at runtime.
+ throw AssertionError()
+ }
+}
diff --git a/common/src/main/kotlin/net/examplemod/ExampleMod.kt b/common/src/main/kotlin/net/examplemod/ExampleMod.kt
new file mode 100644
index 0000000..4f618ce
--- /dev/null
+++ b/common/src/main/kotlin/net/examplemod/ExampleMod.kt
@@ -0,0 +1,31 @@
+package net.examplemod
+
+import com.google.common.base.Suppliers
+import dev.architectury.registry.CreativeTabRegistry
+import dev.architectury.registry.registries.DeferredRegister
+import dev.architectury.registry.registries.Registries
+import dev.architectury.registry.registries.RegistrySupplier
+import net.minecraft.core.Registry
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.world.item.CreativeModeTab
+import net.minecraft.world.item.Item
+import net.minecraft.world.item.ItemStack
+import java.util.function.Supplier
+
+object ExampleMod {
+ const val MOD_ID = "examplemod"
+
+ // We can use this if we don't want to use DeferredRegister
+ @Suppress("unused")
+ val REGISTRIES: Supplier<Registries> = Suppliers.memoize { Registries.get(MOD_ID) }
+
+ // Registering a new creative tab
+ val EXAMPLE_TAB: CreativeModeTab = CreativeTabRegistry.create(ResourceLocation(MOD_ID, "example_tab")) { ItemStack(EXAMPLE_ITEM.get()) }
+ val ITEMS: DeferredRegister<Item> = DeferredRegister.create(MOD_ID, Registry.ITEM_REGISTRY)
+ val EXAMPLE_ITEM: RegistrySupplier<Item> = ITEMS.register("example_item") { Item(Item.Properties().tab(EXAMPLE_TAB)) }
+
+ fun init() {
+ ITEMS.register()
+ println(ExampleExpectPlatform.getConfigDirectory().toAbsolutePath().normalize().toString())
+ }
+}
diff --git a/common/src/main/kotlin/net/examplemod/mixin/MixinTitleScreen.kt b/common/src/main/kotlin/net/examplemod/mixin/MixinTitleScreen.kt
new file mode 100644
index 0000000..0b7e009
--- /dev/null
+++ b/common/src/main/kotlin/net/examplemod/mixin/MixinTitleScreen.kt
@@ -0,0 +1,23 @@
+package net.examplemod.mixin
+
+import net.minecraft.client.gui.screens.TitleScreen
+import org.objectweb.asm.Opcodes
+import org.spongepowered.asm.mixin.Mixin
+import org.spongepowered.asm.mixin.injection.At
+import org.spongepowered.asm.mixin.injection.Inject
+import org.spongepowered.asm.mixin.injection.Redirect
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo
+
+@Mixin(TitleScreen::class)
+class MixinTitleScreen {
+ @Inject(at = [At("HEAD")], method = ["init()V"])
+ private fun init(info: CallbackInfo) {
+ println("Hello from example architectury common mixin!")
+ }
+
+ @Redirect(method = ["render"], at = At("FIELD", target = "minceraftEasterEgg", opcode = Opcodes.GETFIELD))
+ private fun nextFloat(t: TitleScreen): Boolean {
+ return true
+ }
+
+}
diff --git a/common/src/main/resources/architectury.common.json b/common/src/main/resources/architectury.common.json
new file mode 100644
index 0000000..017e6cd
--- /dev/null
+++ b/common/src/main/resources/architectury.common.json
@@ -0,0 +1,3 @@
+{
+ "accessWidener": "notenoughupdates.accesswidener"
+}
diff --git a/common/src/main/resources/assets/examplemod/lang/en_us.json b/common/src/main/resources/assets/examplemod/lang/en_us.json
new file mode 100644
index 0000000..6bcd60e
--- /dev/null
+++ b/common/src/main/resources/assets/examplemod/lang/en_us.json
@@ -0,0 +1,3 @@
+{
+ "item.examplemod.example_item": "Example Item"
+} \ No newline at end of file
diff --git a/common/src/main/resources/notenoughupdates-common.mixins.json b/common/src/main/resources/notenoughupdates-common.mixins.json
new file mode 100644
index 0000000..d2e39dc
--- /dev/null
+++ b/common/src/main/resources/notenoughupdates-common.mixins.json
@@ -0,0 +1,13 @@
+{
+ "required": true,
+ "package": "net.examplemod.mixin",
+ "compatibilityLevel": "JAVA_16",
+ "client": [
+ "MixinTitleScreen"
+ ],
+ "mixins": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+} \ No newline at end of file
diff --git a/common/src/main/resources/notenoughupdates.accesswidener b/common/src/main/resources/notenoughupdates.accesswidener
new file mode 100644
index 0000000..236e6b1
--- /dev/null
+++ b/common/src/main/resources/notenoughupdates.accesswidener
@@ -0,0 +1 @@
+accessWidener v2 named
diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts
new file mode 100644
index 0000000..27900f6
--- /dev/null
+++ b/fabric/build.gradle.kts
@@ -0,0 +1,108 @@
+plugins {
+ id("com.github.johnrengelman.shadow") version "7.1.2"
+}
+
+architectury {
+ platformSetupLoomIde()
+ fabric()
+}
+
+loom {
+ accessWidenerPath.set(project(":common").loom.accessWidenerPath)
+}
+
+/**
+ * @see: https://docs.gradle.org/current/userguide/migrating_from_groovy_to_kotlin_dsl.html
+ * */
+val common: Configuration by configurations.creating
+val shadowCommon: Configuration by configurations.creating // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
+val developmentFabric: Configuration = configurations.getByName("developmentFabric")
+configurations {
+ compileClasspath.get().extendsFrom(configurations["common"])
+ runtimeClasspath.get().extendsFrom(configurations["common"])
+ developmentFabric.extendsFrom(configurations["common"])
+}
+
+dependencies {
+ modImplementation("net.fabricmc:fabric-loader:${rootProject.property("fabric_loader_version")}")
+ modApi("net.fabricmc.fabric-api:fabric-api:${rootProject.property("fabric_api_version")}")
+ // Remove the next line if you don't want to depend on the API
+ modApi("dev.architectury:architectury-fabric:${rootProject.property("architectury_version")}")
+
+ common(project(":common", configuration = "namedElements")) { isTransitive = false }
+ shadowCommon(project(":common", configuration = "transformProductionFabric")) { isTransitive = false }
+ common(kotlin("stdlib-jdk8"))
+ modRuntimeOnly("me.shedaniel:RoughlyEnoughItems-fabric:${rootProject.property("rei_version")}")
+ modRuntimeOnly("me.djtheredstoner:DevAuth-fabric:${rootProject.property("devauth_version")}")
+ modRuntimeOnly("maven.modrinth:modmenu:${rootProject.property("modmenu_version")}")
+}
+
+val javaComponent = components.getByName("java", AdhocComponentWithVariants::class)
+javaComponent.withVariantsFromConfiguration(configurations["sourcesElements"]) {
+ skip()
+}
+
+tasks {
+ processResources {
+ inputs.property("version", project.version)
+
+ filesMatching("fabric.mod.json") {
+ expand("version" to project.version)
+ }
+ }
+
+ shadowJar {
+ exclude("architectury.common.json")
+ /**
+ * magic!
+ * groovy -> kotlin dsl
+ * [project.configurations.shadowCommon] -> listOf(project.configurations["shadowCommon"])
+ * */
+ configurations = listOf(project.configurations["shadowCommon"])
+ archiveClassifier.set("dev-shadow")
+ }
+
+ remapJar {
+ injectAccessWidener.set(true)
+ /**
+ * magic!
+ * groovy -> kotlin dsl
+ * shadowJar.archiveFile -> shadowJar.flatMap { it.archiveFile }
+ * */
+ inputFile.set(shadowJar.flatMap { it.archiveFile })
+ dependsOn(shadowJar)
+ /**
+ * affect suffix of build jar name
+ * if { archiveClassifier.set("fabric") }
+ * name will be examplemod-1.0.0-fabric.jar
+ */
+ archiveClassifier.set("fabric")
+ }
+
+ jar {
+ archiveClassifier.set("dev")
+ }
+
+ sourcesJar {
+ val commonSources = project(":common").tasks.getByName("sourcesJar", Jar::class)
+ dependsOn(commonSources)
+ from(commonSources.archiveFile.map { zipTree(it) })
+ }
+
+
+
+ publishing {
+ publications {
+ create<MavenPublication>("mavenFabric") {
+ artifactId = "${rootProject.property("archives_base_name")}-${project.name}"
+ from(javaComponent)
+ }
+ }
+
+ // 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.
+ }
+ }
+}
+
diff --git a/fabric/src/main/kotlin/net/examplemod/fabric/ExampleExpectPlatformImpl.kt b/fabric/src/main/kotlin/net/examplemod/fabric/ExampleExpectPlatformImpl.kt
new file mode 100644
index 0000000..8982dfc
--- /dev/null
+++ b/fabric/src/main/kotlin/net/examplemod/fabric/ExampleExpectPlatformImpl.kt
@@ -0,0 +1,13 @@
+package net.examplemod.fabric
+
+import net.fabricmc.loader.api.FabricLoader
+import java.nio.file.Path
+import net.examplemod.ExampleExpectPlatform
+
+object ExampleExpectPlatformImpl {
+ /**
+ * This is our actual method to [ExampleExpectPlatform.getConfigDirectory].
+ */
+ @JvmStatic
+ fun getConfigDirectory(): Path = FabricLoader.getInstance().configDir
+} \ No newline at end of file
diff --git a/fabric/src/main/kotlin/net/examplemod/fabric/ExampleModFabric.kt b/fabric/src/main/kotlin/net/examplemod/fabric/ExampleModFabric.kt
new file mode 100644
index 0000000..c11491c
--- /dev/null
+++ b/fabric/src/main/kotlin/net/examplemod/fabric/ExampleModFabric.kt
@@ -0,0 +1,10 @@
+package net.examplemod.fabric
+
+import net.examplemod.ExampleMod.init
+import net.fabricmc.api.ModInitializer
+
+class ExampleModFabric : ModInitializer {
+ override fun onInitialize() {
+ init()
+ }
+} \ No newline at end of file
diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json
new file mode 100644
index 0000000..21eaec0
--- /dev/null
+++ b/fabric/src/main/resources/fabric.mod.json
@@ -0,0 +1,34 @@
+{
+ "schemaVersion": 1,
+ "id": "notenoughupdates",
+ "version": "${version}",
+ "name": "Not Enough Updates",
+ "description": "Not Enough Updates - A mod for Hypixel Skyblock",
+ "authors": [
+ "nea89"
+ ],
+ "contact": {
+ "homepage": "https://github.com/romangraef/TODO",
+ "sources": "https://github.com/romangraef/TODO"
+ },
+ "license": "LGPL-3.0",
+ "icon": "assets/notenoughupdates/icon.png",
+ "environment": "client",
+ "entrypoints": {
+ "main": [
+ "net.examplemod.fabric.ExampleModFabric"
+ ],
+ "rei": [
+ "moe.nea.notenoughupdates.rei.NEUReiPlugin"
+ ]
+ },
+ "mixins": [
+ "notenoughupdates.mixins.json",
+ "notenoughupdates-common.mixins.json"
+ ],
+ "depends": {
+ "fabric": "*",
+ "minecraft": ">=1.18.2",
+ "architectury": ">=4.2.50"
+ }
+}
diff --git a/fabric/src/main/resources/notenoughupdates.mixins.json b/fabric/src/main/resources/notenoughupdates.mixins.json
new file mode 100644
index 0000000..ab40cb1
--- /dev/null
+++ b/fabric/src/main/resources/notenoughupdates.mixins.json
@@ -0,0 +1,12 @@
+{
+ "required": true,
+ "package": "net.examplemod.mixin.fabric",
+ "compatibilityLevel": "JAVA_16",
+ "client": [
+ ],
+ "mixins": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+} \ No newline at end of file
diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts
new file mode 100644
index 0000000..47a56db
--- /dev/null
+++ b/forge/build.gradle.kts
@@ -0,0 +1,108 @@
+plugins {
+ id("com.github.johnrengelman.shadow") version "7.1.2"
+}
+
+architectury {
+ platformSetupLoomIde()
+ forge()
+}
+
+loom {
+ accessWidenerPath.set(project(":common").loom.accessWidenerPath)
+
+ forge {
+ convertAccessWideners.set(true)
+ extraAccessWideners.add(loom.accessWidenerPath.get().asFile.name)
+ }
+}
+
+/**
+ * @see: https://docs.gradle.org/current/userguide/migrating_from_groovy_to_kotlin_dsl.html
+ * */
+val common: Configuration by configurations.creating
+val shadowCommon: Configuration by configurations.creating // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
+val developmentForge: Configuration = configurations.getByName("developmentForge")
+configurations {
+ compileClasspath.get().extendsFrom(configurations["common"])
+ runtimeClasspath.get().extendsFrom(configurations["common"])
+ developmentForge.extendsFrom(configurations["common"])
+}
+
+dependencies {
+ forge("net.minecraftforge:forge:${rootProject.property("forge_version")}")
+ // Remove the next line if you don't want to depend on the API
+ modApi("dev.architectury:architectury-forge:${rootProject.property("architectury_version")}")
+ common(project(":common", configuration = "namedElements")) { isTransitive = false }
+ shadowCommon(project(":common", configuration = "transformProductionForge")) { isTransitive = false }
+ common(kotlin("stdlib-jdk8"))
+ modRuntimeOnly("me.shedaniel:RoughlyEnoughItems-forge:${rootProject.property("rei_version")}")
+}
+
+val javaComponent = components["java"] as AdhocComponentWithVariants
+javaComponent.withVariantsFromConfiguration(configurations["sourcesElements"]) {
+ skip()
+}
+
+tasks {
+ processResources {
+ inputs.property("version", project.version)
+<