Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 68 additions & 48 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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<JavaCompile> {
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<KotlinCompile> {
kotlinOptions.jvmTarget = targetJavaVersion.toString()
filesMatching("fabric.mod.json") {
expand(
mapOf(
"version" to project.version,
"minecraft_version" to minecraftVersion,
"loader_version" to loaderVersion
)
)
}
}

tasks.withType<JavaCompile>().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<MavenPublication>("mavenJava") {
artifactId = property("archives_base_name") as String
from(components["java"])
}
}
}
27 changes: 16 additions & 11 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -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
15 changes: 3 additions & 12 deletions libs.versions.toml
Original file line number Diff line number Diff line change
@@ -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" }
fabric-loom = { id = "net.fabricmc.fabric-loom", version.ref = "fabric-loom" }
166 changes: 107 additions & 59 deletions src/main/kotlin/com/theendercore/trowel/Trowel.kt
Original file line number Diff line number Diff line change
@@ -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<Pair<Int, ItemStack>>, 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<Pair<Int, ItemStack>>,
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
}
}
}
Loading