diff --git a/build.gradle.kts b/build.gradle.kts index 841cac4..9eff7b5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,81 +1,101 @@ -@file:Suppress("PropertyName", "VariableNaming") - -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { alias(libs.plugins.fabric.loom) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlinx.serialization) - alias(libs.plugins.iridium) - alias(libs.plugins.iridium.publish) - alias(libs.plugins.iridium.upload) + `maven-publish` } -group = property("maven_group")!! -version = property("mod_version")!! -base.archivesName.set(property("archives_base_name") as String) -description = property("description") as String +group = property("maven_group") as String +version = property("mod_version") as String + +val minecraftVersion = providers.gradleProperty("minecraft_version").get() +val loaderVersion = providers.gradleProperty("loader_version").get() -val modid: String by project -val mod_name: String by project -val modrinth_id: String? by project -val curse_id: String? by project +base { + archivesName.set(property("archives_base_name") as String) +} repositories { - maven("https://teamvoided.org/releases") mavenCentral() + maven("https://maven.fabricmc.net/") } +dependencies { + minecraft( + "com.mojang:minecraft:${property("minecraft_version")}" + ) -modSettings { - modId(modid) - modName(mod_name) + implementation( + "net.fabricmc:fabric-loader:${property("loader_version")}" + ) - entrypoint("main", "com.theendercore.trowel.TrowelMod") -} + implementation( + "net.fabricmc.fabric-api:fabric-api:${property("fabric_api_version")}" + ) -dependencies { - modImplementation(fileTree("libs")) + implementation( + "net.fabricmc:fabric-language-kotlin:1.13.13+kotlin.2.4.10" + ) } loom { runs { - create("TestWorld") { + named("client") { client() - ideConfigGenerated(true) runDir("run") - programArgs("--quickPlaySingleplayer", "test") + } + + named("server") { + server() + runDir("run-server") } } } -tasks { - val targetJavaVersion = 17 - withType { - options.encoding = "UTF-8" - options.release.set(targetJavaVersion) - } +tasks.processResources { + inputs.property("version", project.version) + inputs.property("minecraft_version", minecraftVersion) + inputs.property("loader_version", loaderVersion) - withType { - kotlinOptions.jvmTarget = targetJavaVersion.toString() + filesMatching("fabric.mod.json") { + expand( + mapOf( + "version" to project.version, + "minecraft_version" to minecraftVersion, + "loader_version" to loaderVersion + ) + ) } +} + +tasks.withType().configureEach { + options.encoding = "UTF-8" + options.release.set(25) +} - java { - toolchain.languageVersion.set(JavaLanguageVersion.of(JavaVersion.toVersion(targetJavaVersion).toString())) - withSourcesJar() +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.fromTarget("25")) } + + jvmToolchain(25) } -uploadConfig { -// debugMode = true - modrinthId = modrinth_id - curseId = curse_id - - changeLog = "- fixed bug with rechisel\n- update to 20.6" - // FabricApi - modrinthDependency("P7dR8mSH", uploadConfig.REQUIRED) - curseDependency("fabric-api", uploadConfig.REQUIRED) - // Fabric Language Kotlin - modrinthDependency("Ha28R6CL", uploadConfig.REQUIRED) - curseDependency("fabric-language-kotlin", uploadConfig.REQUIRED) +java { + withSourcesJar() + + toolchain { + languageVersion.set(JavaLanguageVersion.of(25)) + } } + +publishing { + publications { + create("mavenJava") { + artifactId = property("archives_base_name") as String + from(components["java"]) + } + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 571cea8..a3d90f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,16 +1,21 @@ -org.gradle.jvmargs=-Xmx4000m +org.gradle.jvmargs=-Xmx4G +org.gradle.parallel=true kotlin.code.style=official -loom_version=1.0-SNAPSHOT -maven_group = org.theendercore -mod_version = 1.3.0-1.20 -modid = trowel -mod_name = Trowel -description = A fabric port of Quarks Trowel item. +minecraft_version=26.2 +loader_version=0.19.3 +loom_version=1.17-SNAPSHOT +fabric_api_version=0.154.2+26.2 -# Modrinth and CurseForge Ids for this project -modrinth_id = o8YrbYfv -curse_id = 868403 +maven_group=org.theendercore +mod_version=1.4.1+26.2 +archives_base_name=trowel -archives_base_name = Template +modid=trowel +mod_name=Trowel +description=A Fabric port of Quark's Trowel item. + +# Modrinth and CurseForge IDs +modrinth_id=o8YrbYfv +curse_id=868403 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 48c0a02..9937dae 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/libs.versions.toml b/libs.versions.toml index 177d76a..6be74fb 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -1,17 +1,8 @@ [versions] -kotlin = "2.0.0" -fabric-loom = "1.6-SNAPSHOT" -iridium = "3.2.0" - -#farrow = "1.0.0+arrow.1.2.3" - -[libraries] -#farrow = { module = "net.wiredtomato:farrow", version.ref = "farrow" } +kotlin = "2.3.20" +fabric-loom = "1.17-SNAPSHOT" [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } -fabric-loom = { id = "fabric-loom", version.ref = "fabric-loom" } -iridium = { id = "org.teamvoided.iridium", version.ref = "iridium"} -iridium-publish = { id = "iridium.project.publish-script", version.ref = "iridium"} -iridium-upload = { id = "iridium.mod.upload-script", version.ref = "iridium" } \ No newline at end of file +fabric-loom = { id = "net.fabricmc.fabric-loom", version.ref = "fabric-loom" } \ No newline at end of file diff --git a/src/main/kotlin/com/theendercore/trowel/Trowel.kt b/src/main/kotlin/com/theendercore/trowel/Trowel.kt index 12b68e6..1b1610f 100644 --- a/src/main/kotlin/com/theendercore/trowel/Trowel.kt +++ b/src/main/kotlin/com/theendercore/trowel/Trowel.kt @@ -1,75 +1,123 @@ package com.theendercore.trowel -import net.minecraft.block.ShapeContext -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.entity.player.PlayerInventory -import net.minecraft.item.* -import net.minecraft.sound.SoundCategory -import net.minecraft.util.ActionResult -import net.minecraft.util.hit.BlockHitResult - -class Trowel : Item(Settings().maxCount(1)) { - override fun useOnBlock(c: ItemUsageContext): ActionResult { - if (c.world.isClient) return ActionResult.PASS - - val player = c.player ?: return ActionResult.PASS - val inv = player.inventory ?: return ActionResult.PASS - - val placeable = (0..8).mapNotNull { - val stack = inv.getStack(it) - if (isPlaceable(stack) && stack != null) (it to stack) - else null - } +import net.minecraft.sounds.SoundSource +import net.minecraft.world.InteractionResult +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.BlockItem +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.context.BlockPlaceContext +import net.minecraft.world.item.context.UseOnContext +import net.minecraft.world.phys.BlockHitResult - if (placeable.isEmpty()) return ActionResult.PASS - return place(placeable, inv, player, c, player.inventory.selectedSlot) - } +class Trowel(properties: Properties) : Item(properties) { + override fun useOn(context: UseOnContext): InteractionResult { + val level = context.level - private fun place( - placeable: List>, inv: PlayerInventory, - player: PlayerEntity, c: ItemUsageContext, originalSlot: Int, - ): ActionResult { - if (placeable.isEmpty()) { - inv.selectedSlot = originalSlot - return ActionResult.FAIL + if (level.isClientSide) { + return InteractionResult.PASS } - placeable.random().let { (slot, stack) -> - inv.selectedSlot = slot - val placeCtx = newPlacementContext(player, stack, c) - if (canPlace(placeCtx, stack.item as BlockItem)) { - placeSound(placeCtx) - inv.selectedSlot = originalSlot - return ActionResult.SUCCESS + + val player = context.player ?: return InteractionResult.PASS + val inventory = player.inventory + + val placeable = (0..8).mapNotNull { slot -> + val stack = inventory.getItem(slot) + + if (isPlaceable(stack)) { + slot to stack + } else { + null } - return this.place(placeable.filter { it.first != slot }, inv, player, c, originalSlot) } + + if (placeable.isEmpty()) { + return InteractionResult.PASS + } + + val originalSlot = inventory.selectedSlot + + return placeRandomBlock( + placeable = placeable, + inventory = inventory, + player = player, + context = context, + originalSlot = originalSlot + ) } - private fun placeSound(c: ItemUsageContext) { - c.world.getBlockState(c.blockPos).let { - c.world.playSound( - null, c.blockPos, it.soundGroup.placeSound, - SoundCategory.BLOCKS, - (it.soundGroup.getVolume() + 1.0f) / 2.0f, - it.soundGroup.getPitch() * 0.8f - ) + private fun placeRandomBlock( + placeable: List>, + inventory: Inventory, + player: Player, + context: UseOnContext, + originalSlot: Int + ): InteractionResult { + if (placeable.isEmpty()) { + inventory.selectedSlot = originalSlot + return InteractionResult.FAIL } + + val selected = placeable.random() + val slot = selected.first + val stack = selected.second + + inventory.selectedSlot = slot + + val blockItem = stack.item as BlockItem + val hitResult = BlockHitResult( + context.clickLocation, + context.clickedFace, + context.clickedPos, + context.isInside + ) + + val placementContext = BlockPlaceContext( + player, + context.hand, + stack, + hitResult + ) + + val result = blockItem.place(placementContext) + + inventory.selectedSlot = originalSlot + + if (result.consumesAction()) { + playPlacementSound(placementContext, blockItem) + return result + } + + return placeRandomBlock( + placeable = placeable.filterNot { it.first == slot }, + inventory = inventory, + player = player, + context = context, + originalSlot = originalSlot + ) } - private fun newPlacementContext(player: PlayerEntity, stack: ItemStack, context: ItemUsageContext) = - ItemPlacementContext( - player, context.hand, stack, - BlockHitResult(context.hitPos, context.side, context.blockPos, context.hitsInsideBlock()) + private fun playPlacementSound( + context: BlockPlaceContext, + blockItem: BlockItem + ) { + val level = context.level + val blockState = blockItem.block.defaultBlockState() + val soundType = blockState.soundType + + level.playSound( + null, + context.clickedPos, + soundType.placeSound, + SoundSource.BLOCKS, + (soundType.volume + 1.0f) / 2.0f, + soundType.pitch * 0.8f ) + } - private fun isPlaceable(stack: ItemStack): Boolean = stack.item !is AirBlockItem && stack.item is BlockItem - private fun canPlace(ctx: ItemPlacementContext, stack: BlockItem): Boolean { - val state = stack.block.getPlacementState(stack.getPlacementContext(ctx)) ?: return false - val shapeContext = if (ctx.player == null) ShapeContext.absent() else ShapeContext.of(ctx.player) - return ctx.canPlace() - && state.canPlaceAt(ctx.world, ctx.blockPos) - && ctx.world.canPlace(state, ctx.blockPos, shapeContext) - && stack.useOnBlock(ctx).shouldIncrementStat() + private fun isPlaceable(stack: ItemStack): Boolean { + return !stack.isEmpty && stack.item is BlockItem } -} +} \ No newline at end of file diff --git a/src/main/kotlin/com/theendercore/trowel/TrowelMod.kt b/src/main/kotlin/com/theendercore/trowel/TrowelMod.kt index 2a6ba88..a69d0a1 100644 --- a/src/main/kotlin/com/theendercore/trowel/TrowelMod.kt +++ b/src/main/kotlin/com/theendercore/trowel/TrowelMod.kt @@ -1,28 +1,46 @@ package com.theendercore.trowel import net.fabricmc.api.ModInitializer -import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents -import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents.ModifyEntries -import net.minecraft.item.Item -import net.minecraft.item.ItemGroups -import net.minecraft.item.Items -import net.minecraft.registry.Registries -import net.minecraft.registry.Registry -import net.minecraft.util.Identifier +import net.fabricmc.fabric.api.creativetab.v1.CreativeModeTabEvents +import net.minecraft.core.Registry +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.core.registries.Registries +import net.minecraft.resources.Identifier +import net.minecraft.resources.ResourceKey +import net.minecraft.world.item.CreativeModeTabs +import net.minecraft.world.item.Item +import net.minecraft.world.item.Items import org.slf4j.Logger import org.slf4j.LoggerFactory @Suppress("MemberVisibilityCanBePrivate") object TrowelMod : ModInitializer { const val MODID = "trowel" + val log: Logger = LoggerFactory.getLogger(MODID) - val TROWEL: Item = Trowel() + + private val TROWEL_ID: Identifier = + Identifier.fromNamespaceAndPath(MODID, MODID) + + private val TROWEL_KEY: ResourceKey = + ResourceKey.create(Registries.ITEM, TROWEL_ID) + + val TROWEL: Item = Registry.register( + BuiltInRegistries.ITEM, + TROWEL_KEY, + Trowel( + Item.Properties() + .stacksTo(1) + .setId(TROWEL_KEY) + ) + ) + override fun onInitialize() { log.info("Seizing the means of block placement!") - Registry.register(Registries.ITEM, Identifier(MODID, MODID), TROWEL) - - ItemGroupEvents.modifyEntriesEvent(ItemGroups.TOOLS) - .register(ModifyEntries { it.addAfter(Items.SHEARS, TROWEL) }) + CreativeModeTabEvents.modifyOutputEvent(CreativeModeTabs.TOOLS_AND_UTILITIES) + .register { entries -> + entries.insertAfter(Items.SHEARS, TROWEL) + } } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/trowel/items/trowel.json b/src/main/resources/assets/trowel/items/trowel.json new file mode 100644 index 0000000..fee4207 --- /dev/null +++ b/src/main/resources/assets/trowel/items/trowel.json @@ -0,0 +1,6 @@ +{ + "model": { + "type": "minecraft:model", + "model": "trowel:item/trowel" + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..a168dd2 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,30 @@ +{ + "schemaVersion": 1, + "id": "trowel", + "version": "${version}", + "name": "Trowel", + "description": "A Fabric port of Quark's Trowel item.", + "authors": [ + "TheEnderCore" + ], + "contact": { + "sources": "https://github.com/golso4243/Trowel" + }, + "license": "MIT", + "environment": "*", + "entrypoints": { + "main": [ + { + "adapter": "kotlin", + "value": "com.theendercore.trowel.TrowelMod" + } + ] + }, + "depends": { + "fabricloader": ">=${loader_version}", + "minecraft": "${minecraft_version}", + "java": ">=25", + "fabric-api": "*", + "fabric-language-kotlin": "*" + } +} \ No newline at end of file