Skip to content
Merged
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
11 changes: 10 additions & 1 deletion src/main/generated/data/minecraft/item/mace.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@
},
"attack_speed": 0.15,
"types": {
"minecraft:smashing": {}
"minecraft:smashing": {
"heavy_smash_attack_fall_distance": 5.0,
"hit_sounds": {
"in_air": "minecraft:item.mace.smash_air",
"on_ground_large_fall_distance": "minecraft:item.mace.smash_ground_heavy",
"on_ground_small_fall_distance": "minecraft:item.mace.smash_ground"
},
"knockback_power": 0.699999988079071,
"smash_attack_fall_distance": 1.5
}
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class ItematicDataComponentTypes {
public static final ComponentType<ChargeableShooterMethod.ChargedPowerRules> SHOOTER_CHARGED_POWER_RULES = DataComponentTypesAccessor.register("shooter_charged_power_rules", builder -> builder.codec(ChargeableShooterMethod.ChargedPowerRules.CODEC).packetCodec(ChargeableShooterMethod.ChargedPowerRules.PACKET_CODEC));
public static final ComponentType<RegistryEntry<SoundEvent>> SHOOTER_SHOOT_SOUND = DataComponentTypesAccessor.register("shooter_shoot_sound", builder -> builder.codec(SoundEvent.ENTRY_CODEC).packetCodec(SoundEvent.ENTRY_PACKET_CODEC));
public static final ComponentType<GliderDataComponent> GLIDER = DataComponentTypesAccessor.register("glider", builder -> builder.codec(GliderDataComponent.CODEC).packetCodec(GliderDataComponent.PACKET_CODEC).cache());
public static final ComponentType<SmashingWeaponDataComponent> SMASHING_WEAPON = DataComponentTypesAccessor.register("smashing_weapon", builder -> builder.codec(SmashingWeaponDataComponent.CODEC).packetCodec(SmashingWeaponDataComponent.PACKET_CODEC).cache());

private ItematicDataComponentTypes() {}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package net.errorcraft.itematic.component.type;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.errorcraft.itematic.serialization.ItematicCodecs;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.sound.SoundEvent;

public record SmashingWeaponDataComponent(HitSounds hitSounds, double smashAttackFallDistance, double heavySmashAttackFallDistance, double knockbackPower) {
public static final Codec<SmashingWeaponDataComponent> CODEC = RecordCodecBuilder.create(instance -> instance.group(
HitSounds.CODEC.fieldOf("hit_sounds").forGetter(SmashingWeaponDataComponent::hitSounds),
ItematicCodecs.POSITIVE_DOUBLE.fieldOf("smash_attack_fall_distance").forGetter(SmashingWeaponDataComponent::smashAttackFallDistance),
ItematicCodecs.POSITIVE_DOUBLE.fieldOf("heavy_smash_attack_fall_distance").forGetter(SmashingWeaponDataComponent::heavySmashAttackFallDistance),
ItematicCodecs.POSITIVE_DOUBLE.fieldOf("knockback_power").forGetter(SmashingWeaponDataComponent::knockbackPower)
).apply(instance, SmashingWeaponDataComponent::new));
public static final PacketCodec<RegistryByteBuf, SmashingWeaponDataComponent> PACKET_CODEC = PacketCodec.tuple(
HitSounds.PACKET_CODEC, SmashingWeaponDataComponent::hitSounds,
PacketCodecs.DOUBLE, SmashingWeaponDataComponent::smashAttackFallDistance,
PacketCodecs.DOUBLE, SmashingWeaponDataComponent::heavySmashAttackFallDistance,
PacketCodecs.DOUBLE, SmashingWeaponDataComponent::knockbackPower,
SmashingWeaponDataComponent::new
);

public static SmashingWeaponDataComponent of(HitSounds hitSounds, double smashAttackFallDistance, double heavySmashAttackFallDistance, double knockbackPower) {
return new SmashingWeaponDataComponent(hitSounds, smashAttackFallDistance, heavySmashAttackFallDistance, knockbackPower);
}

public boolean canSmash(LivingEntity attacker) {
return attacker.fallDistance > this.smashAttackFallDistance && !attacker.isGliding();
}

public DamageSource damageSource(LivingEntity attacker) {
if (this.canSmash(attacker)) {
return attacker.getDamageSources().maceSmash(attacker);
}

return null;
}

public record HitSounds(RegistryEntry<SoundEvent> inAir, RegistryEntry<SoundEvent> onGroundSmallFallDistance, RegistryEntry<SoundEvent> onGroundLargeFallDistance) {
public static final Codec<HitSounds> CODEC = RecordCodecBuilder.create(instance -> instance.group(
SoundEvent.ENTRY_CODEC.fieldOf("in_air").forGetter(HitSounds::inAir),
SoundEvent.ENTRY_CODEC.fieldOf("on_ground_small_fall_distance").forGetter(HitSounds::onGroundSmallFallDistance),
SoundEvent.ENTRY_CODEC.fieldOf("on_ground_large_fall_distance").forGetter(HitSounds::onGroundLargeFallDistance)
).apply(instance, HitSounds::new));
public static final PacketCodec<RegistryByteBuf, HitSounds> PACKET_CODEC = PacketCodec.tuple(
SoundEvent.ENTRY_PACKET_CODEC, HitSounds::inAir,
SoundEvent.ENTRY_PACKET_CODEC, HitSounds::onGroundSmallFallDistance,
SoundEvent.ENTRY_PACKET_CODEC, HitSounds::onGroundLargeFallDistance,
HitSounds::new
);

public static HitSounds of(RegistryEntry<SoundEvent> inAir, RegistryEntry<SoundEvent> onGroundSmallFallDistance, RegistryEntry<SoundEvent> onGroundLargeFallDistance) {
return new HitSounds(inAir, onGroundSmallFallDistance, onGroundLargeFallDistance);
}
}
}
13 changes: 12 additions & 1 deletion src/main/java/net/errorcraft/itematic/item/ItemUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.errorcraft.itematic.block.BlockKeys;
import net.errorcraft.itematic.block.ItematicBlockTags;
import net.errorcraft.itematic.component.type.ItemDamageRulesDataComponent;
import net.errorcraft.itematic.component.type.SmashingWeaponDataComponent;
import net.errorcraft.itematic.entity.EntityTypeKeys;
import net.errorcraft.itematic.entity.effect.StatusEffectKeys;
import net.errorcraft.itematic.entity.spawn.EntitySpawner;
Expand All @@ -31,6 +32,7 @@
import net.errorcraft.itematic.loot.predicate.SideCheckPredicate;
import net.errorcraft.itematic.mixin.item.BrushItemAccessor;
import net.errorcraft.itematic.mixin.item.CrossbowItemAccessor;
import net.errorcraft.itematic.mixin.item.MaceItemAccessor;
import net.errorcraft.itematic.potion.PotionKeys;
import net.errorcraft.itematic.registry.ItematicRegistryKeys;
import net.errorcraft.itematic.sound.SoundEventKeys;
Expand Down Expand Up @@ -6143,7 +6145,16 @@ private void bootstrapToolsAndWeapons() {
.with(DamageableItemComponent.of(500))
.with(ToolItemComponent.builder(2).build())
.with(WeaponItemComponent.builder(1, 5.0d, 0.15d)
.type(MeleeWeaponComponents.SMASHING, SmashingMeleeWeapon.INSTANCE)
.type(MeleeWeaponComponents.SMASHING, SmashingMeleeWeapon.of(SmashingWeaponDataComponent.of(
SmashingWeaponDataComponent.HitSounds.of(
this.soundEvents.getOrThrow(SoundEventKeys.MACE_SMASH_AIR),
this.soundEvents.getOrThrow(SoundEventKeys.MACE_SMASH_GROUND),
this.soundEvents.getOrThrow(SoundEventKeys.MACE_SMASH_GROUND_HEAVY)
),
MaceItem.MINING_SPEED_MULTIPLIER,
MaceItemAccessor.heavySmashAttackFallDistance(),
MaceItemAccessor.knockbackPower()
)))
.build())
.with(EnchantableItemComponent.of(15))
.with(RepairableItemComponent.of(RegistryEntryList.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
import net.minecraft.component.type.AttackRangeComponent;
import net.minecraft.component.type.SwingAnimationComponent;
import net.minecraft.component.type.WeaponComponent;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.damage.DamageType;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContextParameters;
Expand Down Expand Up @@ -114,6 +116,31 @@ public ComponentMap getComponents() {
return this.types;
}

public float bonusAttackDamage(Entity target, float baseAttackDamage, DamageSource damageSource) {
SmashingMeleeWeapon smashing = this.types.get(MeleeWeaponComponents.SMASHING);
if (smashing != null) {
return smashing.bonusAttackDamage(target, baseAttackDamage, damageSource);
}

return 0.0f;
}

public void postDamageEntity(ItemStack stack, LivingEntity target, LivingEntity attacker) {
SmashingMeleeWeapon smashing = this.types.get(MeleeWeaponComponents.SMASHING);
if (smashing != null) {
smashing.postDamageEntity(stack, target, attacker);
}
}

public DamageSource damageSource(ItemStack stack, LivingEntity attacker) {
SmashingMeleeWeapon smashing = this.types.get(MeleeWeaponComponents.SMASHING);
if (smashing != null) {
return smashing.damageSource(stack, attacker);
}

return null;
}

public static class Builder {
private final int itemDamagePerAttack;
private final ComponentMap.Builder types = ComponentMap.builder();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
package net.errorcraft.itematic.item.weapon.melee.component;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import net.errorcraft.itematic.component.ItematicDataComponentTypes;
import net.errorcraft.itematic.component.type.SmashingWeaponDataComponent;
import net.errorcraft.itematic.item.weapon.melee.MeleeWeaponWithDataComponents;
import net.minecraft.component.ComponentMap;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.MaceItem;

public class SmashingMeleeWeapon {
public static final SmashingMeleeWeapon INSTANCE = new SmashingMeleeWeapon();
public static final Codec<SmashingMeleeWeapon> CODEC = MapCodec.unitCodec(INSTANCE);
public record SmashingMeleeWeapon(SmashingWeaponDataComponent smashingWeapon) implements MeleeWeaponWithDataComponents {
public static final Codec<SmashingMeleeWeapon> CODEC = SmashingWeaponDataComponent.CODEC.xmap(
SmashingMeleeWeapon::new,
SmashingMeleeWeapon::smashingWeapon
);
private static final MaceItem DUMMY = new MaceItem(new Item.Settings());

private SmashingMeleeWeapon() {}
public static SmashingMeleeWeapon of(SmashingWeaponDataComponent smashingWeapon) {
return new SmashingMeleeWeapon(smashingWeapon);
}

@Override
public void addComponents(ComponentMap.Builder builder) {
builder.add(ItematicDataComponentTypes.SMASHING_WEAPON, this.smashingWeapon);
}

public void hit(ItemStack stack, LivingEntity target, LivingEntity attacker) {
DUMMY.postHit(stack, target, attacker);
}

public float bonusAttackDamage(Entity target, float baseAttackDamage, DamageSource damageSource) {
return DUMMY.getBonusAttackDamage(target, baseAttackDamage, damageSource);
}

public void postDamageEntity(ItemStack stack, LivingEntity target, LivingEntity attacker) {
DUMMY.postDamageEntity(stack, target, attacker);
}

public DamageSource damageSource(ItemStack stack, LivingEntity attacker) {
SmashingWeaponDataComponent smashingWeapon = stack.get(ItematicDataComponentTypes.SMASHING_WEAPON);
if (smashingWeapon != null) {
return smashingWeapon.damageSource(attacker);
}

return null;
}
}
21 changes: 21 additions & 0 deletions src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.errorcraft.itematic.mixin.item;

import com.google.common.annotations.VisibleForTesting;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.mojang.serialization.Codec;
import net.errorcraft.itematic.access.item.ItemAccess;
import net.errorcraft.itematic.component.ItematicDataComponentTypes;
Expand Down Expand Up @@ -35,6 +36,7 @@
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.StackReference;
import net.minecraft.item.Item;
Expand Down Expand Up @@ -277,6 +279,15 @@ public void postHit(ItemStack stack, LivingEntity target, LivingEntity attacker)
tryUpdateItemStack(attacker, Hand.MAIN_HAND, stack, stackExchanger);
}

@Inject(
method = "postDamageEntity",
at = @At("HEAD")
)
private void postDamageEntityUseItemComponent(ItemStack stack, LivingEntity target, LivingEntity attacker, CallbackInfo info) {
this.itematic$getBehavior(ItemComponentTypes.WEAPON)
.ifPresent(weapon -> weapon.postDamageEntity(stack, target, attacker));
}

/**
* @author ErrorCraft
* @reason Uses the ItemComponent implementation for data-driven items.
Expand Down Expand Up @@ -422,6 +433,16 @@ public boolean onClicked(ItemStack stack, ItemStack otherStack, Slot slot, Click
return result;
}

@ModifyReturnValue(
method = "getBonusAttackDamage",
at = @At("TAIL")
)
private float getBonusAttackDamageUseItemComponent(float original, Entity target, float baseAttackDamage, DamageSource damageSource) {
return this.itematic$getBehavior(ItemComponentTypes.WEAPON)
.map(weapon -> weapon.bonusAttackDamage(target, baseAttackDamage, damageSource))
.orElse(0.0f);
}

@Inject(
method = "onCraft",
at = @At("HEAD")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import net.minecraft.entity.Entity;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.StackReference;
import net.minecraft.item.Item;
Expand Down Expand Up @@ -673,6 +674,20 @@ private void checkForUseableBehavior(LivingEntity user, ItemStack stack, Callbac
}
}

@Redirect(
method = "method_75224",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/item/Item;getDamageSource(Lnet/minecraft/entity/LivingEntity;)Lnet/minecraft/entity/damage/DamageSource;"
)
)
@SuppressWarnings("ConstantValue")
private DamageSource getDamageSourceUseItemComponent(Item instance, LivingEntity user) {
return this.itematic$getBehavior(ItemComponentTypes.WEAPON)
.map(weapon -> weapon.damageSource((ItemStack)(Object) this, user))
.orElse(null);
}

/**
* @author ErrorCraft
* @reason Uses a registry entry on the item stack for data-driven items.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package net.errorcraft.itematic.mixin.item;

import net.minecraft.item.MaceItem;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(MaceItem.class)
public interface MaceItemAccessor {
@Accessor("HEAVY_SMASH_SOUND_FALL_DISTANCE_THRESHOLD")
static float heavySmashAttackFallDistance() {
throw new AssertionError();
}

@Accessor("KNOCKBACK_POWER")
static float knockbackPower() {
throw new AssertionError();
}
}
Loading
Loading