diff --git a/StaffMod/src/main/kotlin/opekope2/avm_staff/api/item/StaffItem.kt b/StaffMod/src/main/kotlin/opekope2/avm_staff/api/item/StaffItem.kt index 85ff30acb..521321daf 100644 --- a/StaffMod/src/main/kotlin/opekope2/avm_staff/api/item/StaffItem.kt +++ b/StaffMod/src/main/kotlin/opekope2/avm_staff/api/item/StaffItem.kt @@ -28,12 +28,14 @@ import java.util.stream.Stream * Staff item. */ class StaffItem(settings: Settings) : Item(settings) { + private val ItemStack?.handlerOfItemOrDefault: StaffItemHandler + get() = this?.handlerOfItem ?: StaffItemHandler.DEFAULT + override fun getAttributeModifiers( stack: ItemStack, slot: EquipmentSlot ): Multimap { - return stack.itemInStaff?.handlerOfItem?.getAttributeModifiers(stack, slot) - ?: super.getAttributeModifiers(stack, slot) + return stack.itemInStaff.handlerOfItemOrDefault.getAttributeModifiers(stack, slot) } override fun onItemEntityDestroyed(entity: ItemEntity) { @@ -43,41 +45,39 @@ class StaffItem(settings: Settings) : Item(settings) { } override fun getMaxUseTime(stack: ItemStack): Int { - return stack.itemInStaff?.handlerOfItem?.maxUseTime ?: super.getMaxUseTime(stack) + return stack.itemInStaff.handlerOfItemOrDefault.maxUseTime } override fun use(world: World, user: PlayerEntity, hand: Hand): TypedActionResult { val staffStack = user.getStackInHand(hand) - return staffStack.itemInStaff?.handlerOfItem?.use(staffStack, world, user, hand) ?: super.use(world, user, hand) + return staffStack.itemInStaff.handlerOfItemOrDefault.use(staffStack, world, user, hand) } override fun usageTick(world: World, user: LivingEntity, stack: ItemStack, remainingUseTicks: Int) { - stack.itemInStaff?.handlerOfItem?.usageTick(stack, world, user, remainingUseTicks) + stack.itemInStaff.handlerOfItemOrDefault.usageTick(stack, world, user, remainingUseTicks) } override fun onStoppedUsing(stack: ItemStack, world: World, user: LivingEntity, remainingUseTicks: Int) { - stack.itemInStaff?.handlerOfItem?.onStoppedUsing(stack, world, user, remainingUseTicks) + stack.itemInStaff.handlerOfItemOrDefault.onStoppedUsing(stack, world, user, remainingUseTicks) } override fun finishUsing(stack: ItemStack, world: World, user: LivingEntity): ItemStack { - return stack.itemInStaff?.handlerOfItem?.finishUsing(stack, world, user) - ?: super.finishUsing(stack, world, user) + return stack.itemInStaff.handlerOfItemOrDefault.finishUsing(stack, world, user) } override fun useOnBlock(context: ItemUsageContext): ActionResult { - return context.stack.itemInStaff?.handlerOfItem?.useOnBlock( + return context.stack.itemInStaff.handlerOfItemOrDefault.useOnBlock( context.stack, context.world, context.player ?: return ActionResult.PASS, context.blockPos, context.side, context.hand - ) ?: super.useOnBlock(context) + ) } override fun useOnEntity(stack: ItemStack, user: PlayerEntity, entity: LivingEntity, hand: Hand): ActionResult { - return stack.itemInStaff?.handlerOfItem?.useOnEntity(stack, user.world, user, entity, hand) - ?: super.useOnEntity(stack, user, entity, hand) + return stack.itemInStaff.handlerOfItemOrDefault.useOnEntity(stack, user.world, user, entity, hand) } override fun getName(stack: ItemStack): Text { diff --git a/StaffMod/src/main/kotlin/opekope2/avm_staff/api/item/StaffItemHandler.kt b/StaffMod/src/main/kotlin/opekope2/avm_staff/api/item/StaffItemHandler.kt index 25df62f51..019de5909 100644 --- a/StaffMod/src/main/kotlin/opekope2/avm_staff/api/item/StaffItemHandler.kt +++ b/StaffMod/src/main/kotlin/opekope2/avm_staff/api/item/StaffItemHandler.kt @@ -14,6 +14,7 @@ import net.minecraft.entity.EquipmentSlot import net.minecraft.entity.LivingEntity import net.minecraft.entity.attribute.EntityAttribute import net.minecraft.entity.attribute.EntityAttributeModifier +import net.minecraft.entity.attribute.EntityAttributes import net.minecraft.entity.player.PlayerEntity import net.minecraft.item.Item import net.minecraft.item.ItemStack @@ -27,6 +28,8 @@ import net.minecraft.world.World import net.minecraft.world.event.GameEvent import opekope2.avm_staff.api.initializer.IStaffModInitializationContext import opekope2.avm_staff.api.initializer.IStaffModInitializer +import opekope2.avm_staff.util.attackDamage +import opekope2.avm_staff.util.attackSpeed /** * Provides functionality for a staff, when an item is inserted into it. @@ -348,6 +351,19 @@ abstract class StaffItemHandler { staffStack: ItemStack, slot: EquipmentSlot ): Multimap { - return ImmutableMultimap.of() + return if (slot == EquipmentSlot.MAINHAND) DEFAULT_ATTRIBUTE_MODIFIERS + else ImmutableMultimap.of() + } + + companion object { + private val DEFAULT_ATTRIBUTE_MODIFIERS = ImmutableMultimap.of( + EntityAttributes.GENERIC_ATTACK_DAMAGE, + attackDamage(4.0), + EntityAttributes.GENERIC_ATTACK_SPEED, + attackSpeed(2.0) + ) + + @JvmField + val DEFAULT: StaffItemHandler = object : StaffItemHandler() {} } } diff --git a/StaffMod/src/main/kotlin/opekope2/avm_staff/internal/staff_item_handler/SnowBlockItemHandler.kt b/StaffMod/src/main/kotlin/opekope2/avm_staff/internal/staff_item_handler/SnowBlockItemHandler.kt new file mode 100644 index 000000000..0ff244fd5 --- /dev/null +++ b/StaffMod/src/main/kotlin/opekope2/avm_staff/internal/staff_item_handler/SnowBlockItemHandler.kt @@ -0,0 +1,68 @@ +// Copyright (c) 2024 opekope2 +// Staff Mod is licensed under the MIT license: https://github.com/opekope2/StaffMod/blob/main/LICENSE + +package opekope2.avm_staff.internal.staff_item_handler + +import com.mojang.serialization.Codec +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.entity.projectile.thrown.SnowballEntity +import net.minecraft.item.ItemStack +import net.minecraft.sound.SoundCategory +import net.minecraft.sound.SoundEvents +import net.minecraft.util.Hand +import net.minecraft.util.Identifier +import net.minecraft.util.TypedActionResult +import net.minecraft.world.World +import opekope2.avm_staff.api.config.IConfiguration +import opekope2.avm_staff.api.initializer.IStaffModInitializationContext +import opekope2.avm_staff.api.item.StaffItemHandler + +class SnowBlockItemHandler : StaffItemHandler() { + override val maxUseTime = 72000 + + override fun use( + staffStack: ItemStack, + world: World, + user: PlayerEntity, + hand: Hand + ): TypedActionResult { + user.setCurrentHand(hand) + return TypedActionResult.pass(staffStack) + } + + override fun usageTick(staffStack: ItemStack, world: World, user: LivingEntity, remainingUseTicks: Int) { + if (world.isClient) return + + world.playSound( + null, + user.x, + user.y, + user.z, + SoundEvents.ENTITY_SNOWBALL_THROW, + SoundCategory.NEUTRAL, + 0.5f, + 0.4f / (world.getRandom().nextFloat() * 0.4f + 0.8f) + ) + + world.spawnEntity(SnowballEntity(world, user).apply { + // TODO speed + setVelocity(user, user.pitch, user.yaw, 0f, 4f, 1f) + }) + } + + // TODO + private class Configuration : IConfiguration + + companion object { + private val CONFIG_CODEC: Codec = Codec.unit(::Configuration) + + fun registerStaffItemHandler(context: IStaffModInitializationContext) { + context.registerStaffItemHandler( + Identifier("snow_block"), + SnowBlockItemHandler(), + CONFIG_CODEC + ) + } + } +} diff --git a/StaffMod/src/main/kotlin/opekope2/avm_staff/internal/staff_item_handler/VanillaStaffItemHandlers.kt b/StaffMod/src/main/kotlin/opekope2/avm_staff/internal/staff_item_handler/VanillaStaffItemHandlers.kt new file mode 100644 index 000000000..3233c222d --- /dev/null +++ b/StaffMod/src/main/kotlin/opekope2/avm_staff/internal/staff_item_handler/VanillaStaffItemHandlers.kt @@ -0,0 +1,11 @@ +// Copyright (c) 2024 opekope2 +// Staff Mod is licensed under the MIT license: https://github.com/opekope2/StaffMod/blob/main/LICENSE + +package opekope2.avm_staff.internal.staff_item_handler + +import opekope2.avm_staff.api.initializer.IStaffModInitializationContext + +@Suppress("unused") +fun register(context: IStaffModInitializationContext) { + SnowBlockItemHandler.registerStaffItemHandler(context) +} diff --git a/StaffMod/src/main/kotlin/opekope2/avm_staff/util/AttributeUtil.kt b/StaffMod/src/main/kotlin/opekope2/avm_staff/util/AttributeUtil.kt new file mode 100644 index 000000000..182d14d2b --- /dev/null +++ b/StaffMod/src/main/kotlin/opekope2/avm_staff/util/AttributeUtil.kt @@ -0,0 +1,46 @@ +// Copyright (c) 2024 opekope2 +// Staff Mod is licensed under the MIT license: https://github.com/opekope2/StaffMod/blob/main/LICENSE + +@file: JvmName("AttributeUtil") + +package opekope2.avm_staff.util + +import net.minecraft.entity.attribute.EntityAttributeModifier +import net.minecraft.item.Item + +private const val PLAYER_BASE_ATTACK_DAMAGE = 1.0 +private const val PLAYER_BASE_ATTACK_SPEED = 4.0 + +/** + * Creates an [EntityAttributeModifier], which changes the attack damage to [totalAttackDamage] after subtracting the + * player's base attack damage. + * + * @param totalAttackDamage The desired amount of damage in half hearts + */ +fun attackDamage(totalAttackDamage: Double): EntityAttributeModifier = EntityAttributeModifier( + Item.ATTACK_DAMAGE_MODIFIER_ID, + "Weapon modifier", + totalAttackDamage - PLAYER_BASE_ATTACK_DAMAGE, + EntityAttributeModifier.Operation.ADDITION +) + +/** + * Creates an [EntityAttributeModifier], which changes the attack speed to [totalAttackSpeed] after subtracting the + * player's base attack speed. + * + * @param totalAttackSpeed The desired attack speed in attack/second + */ +fun attackSpeed(totalAttackSpeed: Double): EntityAttributeModifier = EntityAttributeModifier( + Item.ATTACK_SPEED_MODIFIER_ID, + "Weapon modifier", + totalAttackSpeed - PLAYER_BASE_ATTACK_SPEED, + EntityAttributeModifier.Operation.ADDITION +) + +/** + * Creates an [EntityAttributeModifier], which changes the attack speed to the reciprocal of [totalEquipTime] after + * subtracting the player's base attack speed. + * + * @param totalEquipTime The desired equip time in seconds + */ +fun equipTime(totalEquipTime: Double): EntityAttributeModifier = attackSpeed(1.0 / totalEquipTime) diff --git a/StaffMod/src/main/resources/fabric.mod.json b/StaffMod/src/main/resources/fabric.mod.json index e9cc8a761..ed474b510 100644 --- a/StaffMod/src/main/resources/fabric.mod.json +++ b/StaffMod/src/main/resources/fabric.mod.json @@ -27,6 +27,12 @@ "adapter": "kotlin", "value": "opekope2.avm_staff.internal.client.StaffModClient" } + ], + "avm-staff": [ + { + "adapter": "kotlin", + "value": "opekope2.avm_staff.internal.item_handler.VanillaStaffItemHandlersKt::register" + } ] }, "mixins": [ diff --git a/gradle.properties b/gradle.properties index dcd19e138..996878a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,12 +7,12 @@ kotlin.code.style=official org.gradle.jvmargs=-Xmx1G org.gradle.warning.mode=all ########################################################################## -loom_version=1.4-SNAPSHOT +loom_version=1.5-SNAPSHOT loader_version=0.15.3 java_version=17 ########################################################################## # Mod Properties -mod_version=0.1.1-alpha.2 +mod_version=0.2.0-beta maven_group=opekope2.avm_staff ########################################################################## # Kotlin Dependencies