diff --git a/psd/tool_items.psd b/psd/tool_items.psd index 30df8a14..915f175e 100644 Binary files a/psd/tool_items.psd and b/psd/tool_items.psd differ diff --git a/src/main/java/ru/betterend/item/EndHammer.java b/src/main/java/ru/betterend/item/EndHammer.java new file mode 100644 index 00000000..e67a5622 --- /dev/null +++ b/src/main/java/ru/betterend/item/EndHammer.java @@ -0,0 +1,89 @@ +package ru.betterend.item; + +import java.util.UUID; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.ImmutableMultimap.Builder; + +import io.netty.util.internal.ThreadLocalRandom; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.Material; +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.ItemStack; +import net.minecraft.item.ToolItem; +import net.minecraft.item.ToolMaterial; +import net.minecraft.item.Vanishable; +import net.minecraft.tag.BlockTags; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +public class EndHammer extends ToolItem implements Vanishable { + + public final static UUID ATTACK_KNOCKBACK_MODIFIER_ID = MathHelper.randomUuid(ThreadLocalRandom.current()); + + private final float attackDamage; + private final Multimap attributeModifiers; + + public EndHammer(ToolMaterial material, float attackDamage, float attackSpeed, double knockback, Settings settings) { + super(material, settings); + + this.attackDamage = attackDamage + material.getAttackDamage(); + Builder builder = ImmutableMultimap.builder(); + builder.put(EntityAttributes.GENERIC_ATTACK_DAMAGE, new EntityAttributeModifier(ATTACK_DAMAGE_MODIFIER_ID, "Weapon modifier", this.attackDamage, EntityAttributeModifier.Operation.ADDITION)); + builder.put(EntityAttributes.GENERIC_ATTACK_SPEED, new EntityAttributeModifier(ATTACK_SPEED_MODIFIER_ID, "Weapon modifier", attackSpeed, EntityAttributeModifier.Operation.ADDITION)); + builder.put(EntityAttributes.GENERIC_ATTACK_KNOCKBACK, new EntityAttributeModifier(ATTACK_KNOCKBACK_MODIFIER_ID, "Weapon modifier", knockback, EntityAttributeModifier.Operation.ADDITION)); + this.attributeModifiers = builder.build(); + } + + public float getAttackDamage() { + return this.attackDamage; + } + + public boolean canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) { + return !miner.isCreative() || state.getMaterial().equals(Material.STONE); + } + + public float getMiningSpeedMultiplier(ItemStack stack, BlockState state) { + if (state.isOf(Blocks.COBWEB)) { + return 15.0F; + } else { + Material material = state.getMaterial(); + return material != Material.PLANT && material != Material.REPLACEABLE_PLANT && material != Material.UNUSED_PLANT && !state.isIn(BlockTags.LEAVES) && material != Material.GOURD ? 1.0F : 1.5F; + } + } + + public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attacker) { + stack.damage(1, attacker, ((entity) -> { + entity.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND); + })); + + return true; + } + + public boolean postMine(ItemStack stack, World world, BlockState state, BlockPos pos, LivingEntity miner) { + if (state.getHardness(world, pos) != 0.0F) { + stack.damage(2, miner, ((entity) -> { + entity.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND); + })); + } + + return true; + } + + public boolean isEffectiveOn(BlockState state) { + return state.getMaterial().equals(Material.STONE); + } + + public Multimap getAttributeModifiers(EquipmentSlot slot) { + return slot == EquipmentSlot.MAINHAND ? this.attributeModifiers : super.getAttributeModifiers(slot); + } +} diff --git a/src/main/java/ru/betterend/mixin/common/PlayerEntityMixin.java b/src/main/java/ru/betterend/mixin/common/PlayerEntityMixin.java new file mode 100644 index 00000000..25957ae6 --- /dev/null +++ b/src/main/java/ru/betterend/mixin/common/PlayerEntityMixin.java @@ -0,0 +1,66 @@ +package ru.betterend.mixin.common; + +import java.util.Collection; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +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.util.math.MathHelper; +import net.minecraft.world.World; + +@Mixin(PlayerEntity.class) +public abstract class PlayerEntityMixin extends LivingEntity { + + protected PlayerEntityMixin(EntityType entityType, World world) { + super(entityType, world); + } + + @ModifyArg(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;takeKnockback(FDD)V", ordinal = 0)) + private float increaseKnockback(float value, double x, double z) { + PlayerEntity player = (PlayerEntity) (Object) this; + value += this.getKnockback(player.getMainHandStack().getItem()); + return value; + } + + @Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;onAttacking(Lnet/minecraft/entity/Entity;)V", shift = Shift.BEFORE)) + public void attack(Entity target, CallbackInfo cinfo) { + if (target instanceof LivingEntity) { + PlayerEntity player = (PlayerEntity) (Object) this; + int baseKnockback = EnchantmentHelper.getKnockback(player); + if (isSprinting() && getAttackCooldownProgress(0.5F) > 0.9F) { + baseKnockback++; + } + if (baseKnockback == 0) { + Item tool = player.getMainHandStack().getItem(); + LivingEntity livingTarget = (LivingEntity) target; + livingTarget.takeKnockback((float) this.getKnockback(tool), MathHelper.sin(yaw * 0.017453292F), -MathHelper.cos(yaw * 0.017453292F)); + } + } + } + + @Shadow + abstract float getAttackCooldownProgress(float base); + + private double getKnockback(Item tool) { + if (tool == null) return 0.0D; + Collection modifiers = tool.getAttributeModifiers(EquipmentSlot.MAINHAND).get(EntityAttributes.GENERIC_ATTACK_KNOCKBACK); + if (modifiers.size() > 0) { + return modifiers.iterator().next().getValue(); + } + return 0.0D; + } +} diff --git a/src/main/java/ru/betterend/registry/ItemRegistry.java b/src/main/java/ru/betterend/registry/ItemRegistry.java index bfe23815..f6771232 100644 --- a/src/main/java/ru/betterend/registry/ItemRegistry.java +++ b/src/main/java/ru/betterend/registry/ItemRegistry.java @@ -13,12 +13,14 @@ import net.minecraft.item.Items; import net.minecraft.item.ShovelItem; import net.minecraft.item.SwordItem; import net.minecraft.item.ToolItem; +import net.minecraft.item.ToolMaterials; import net.minecraft.tag.Tag; import net.minecraft.util.registry.Registry; import ru.betterend.BetterEnd; import ru.betterend.item.EndArmorMaterial; import ru.betterend.item.EndAxe; +import ru.betterend.item.EndHammer; import ru.betterend.item.EndHoe; import ru.betterend.item.EndPickaxe; import ru.betterend.item.EndToolMaterial; @@ -55,6 +57,7 @@ public class ItemRegistry { public static ToolItem AETERNIUM_PICKAXE = registerTool("aeternium_pickaxe", new EndPickaxe(EndToolMaterial.AETERNIUM, 1, -2.8F, new Item.Settings().group(CreativeTab.END_TAB))); public static ToolItem AETERNIUM_AXE = registerTool("aeternium_axe", new EndAxe(EndToolMaterial.AETERNIUM, 5.0F, -3.0F, new Item.Settings().group(CreativeTab.END_TAB))); public static ToolItem AETERNIUM_HOE = registerTool("aeternium_hoe", new EndHoe(EndToolMaterial.AETERNIUM, -3, 0.0F, new Item.Settings().group(CreativeTab.END_TAB))); + public static ToolItem IRON_HAMMER = registerTool("iron_hammer", new EndHammer(ToolMaterials.IRON, 4.0F, -3.0F, 0.2D, new Item.Settings().group(CreativeTab.END_TAB))); protected static Item registerItem(String name, Item item) { if (item != Items.AIR) { diff --git a/src/main/resources/assets/betterend/models/item/iron_hammer.json b/src/main/resources/assets/betterend/models/item/iron_hammer.json new file mode 100644 index 00000000..f738e323 --- /dev/null +++ b/src/main/resources/assets/betterend/models/item/iron_hammer.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "betterend:item/iron_hammer" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/betterend/textures/item/iron_hammer.png b/src/main/resources/assets/betterend/textures/item/iron_hammer.png new file mode 100644 index 00000000..713b5191 Binary files /dev/null and b/src/main/resources/assets/betterend/textures/item/iron_hammer.png differ diff --git a/src/main/resources/betterend.mixins.common.json b/src/main/resources/betterend.mixins.common.json index da0d80df..aaafc761 100644 --- a/src/main/resources/betterend.mixins.common.json +++ b/src/main/resources/betterend.mixins.common.json @@ -10,6 +10,7 @@ "TagGroupLoaderMixin", "CraftingScreenHandlerMixin", "GenerationSettingsMixin", + "PlayerEntityMixin", "BiomeMixin", "TagAccessor" ],