From 41cb3cecf43e96c67a69e6a15acfccef43af9e86 Mon Sep 17 00:00:00 2001 From: ExDrill <72329798+ExDrill@users.noreply.github.com> Date: Thu, 20 Jun 2024 12:09:27 -0500 Subject: [PATCH] 1.21 Port --- .github/workflows/build.yml | 4 +- CHANGELOG.md | 30 ++++++ gradle.properties | 6 +- .../java/com/teamabode/guarding/Guarding.java | 16 ++- .../teamabode/guarding/GuardingConfig.java | 19 ++-- .../guarding/client/GuardingClient.java | 6 +- .../client/model/NetheriteShieldModel.java | 8 +- .../render/NetheriteShieldRenderer.java | 4 +- .../common/enchantment/BarbedEnchantment.java | 9 -- .../enchantment/BlockedConditionalEffect.java | 35 +++++++ .../enchantment/EnchantmentConsumer.java | 9 ++ .../enchantment/PummelingEnchantment.java | 10 -- .../common/enchantment/ShieldEnchantment.java | 11 --- .../common/item/NetheriteShieldItem.java | 15 +-- .../recipe/SmithingTransformShieldRecipe.java | 37 +++---- .../config/ItemToEnchantabilityProperty.java | 53 ++++++++++ .../guarding/core/init/GuardingCallbacks.java | 97 ------------------- .../core/init/GuardingEnchantments.java | 22 ----- .../KilledByParriedArrowTriggerMixin.java | 2 +- .../core/mixin/NetheriteShieldMixin.java | 12 ++- .../core/mixin/NetheriteShieldSoundMixin.java | 4 +- .../guarding/core/mixin/ShieldDelayMixin.java | 3 + .../guarding/core/mixin/ShieldItemMixin.java | 6 +- .../core/mixin/SmithingTemplateItemMixin.java | 5 +- .../GuardingCritieriaTriggers.java | 3 +- .../registry/GuardingEnchantmentEffects.java | 32 ++++++ .../core/registry/GuardingEnchantments.java | 18 ++++ .../{init => registry}/GuardingItems.java | 5 +- .../{init => registry}/GuardingParticles.java | 4 +- .../GuardingRecipeSerializers.java | 2 +- .../{init => registry}/GuardingSounds.java | 4 +- .../core/tag/GuardingDamageTypeTags.java | 11 +++ .../guarding/core/tag/GuardingItemTags.java | 11 +++ .../guarding/core/util/EnchantmentUtils.java | 83 ++++++++++++++++ .../guarding/core/util/ShieldUtils.java | 72 ++++++++++++++ .../tags/item/tools/shield.json} | 0 .../nether/obtain_netherite_shield.json | 0 .../story/decorate_shield_with_banner.json | 0 .../story/kill_mob_with_own_arrow.json | 0 .../data/guarding/enchantment/barbed.json | 68 +++++++++++++ .../data/guarding/enchantment/pummeling.json | 31 ++++++ .../netherite_shield_smithing.json | 0 .../guarding/tags/damage_type/no_parry.json | 6 ++ .../tags/item/enchantable/shield.json | 8 ++ .../tags/item/enchantable/durability.json} | 1 - .../tags/{items => item}/trimmable_armor.json | 0 src/main/resources/fabric.mod.json | 2 +- 47 files changed, 549 insertions(+), 235 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 src/main/java/com/teamabode/guarding/common/enchantment/BarbedEnchantment.java create mode 100644 src/main/java/com/teamabode/guarding/common/enchantment/BlockedConditionalEffect.java create mode 100644 src/main/java/com/teamabode/guarding/common/enchantment/EnchantmentConsumer.java delete mode 100644 src/main/java/com/teamabode/guarding/common/enchantment/PummelingEnchantment.java delete mode 100644 src/main/java/com/teamabode/guarding/common/enchantment/ShieldEnchantment.java create mode 100644 src/main/java/com/teamabode/guarding/core/config/ItemToEnchantabilityProperty.java delete mode 100644 src/main/java/com/teamabode/guarding/core/init/GuardingCallbacks.java delete mode 100644 src/main/java/com/teamabode/guarding/core/init/GuardingEnchantments.java rename src/main/java/com/teamabode/guarding/core/{init => registry}/GuardingCritieriaTriggers.java (87%) create mode 100644 src/main/java/com/teamabode/guarding/core/registry/GuardingEnchantmentEffects.java create mode 100644 src/main/java/com/teamabode/guarding/core/registry/GuardingEnchantments.java rename src/main/java/com/teamabode/guarding/core/{init => registry}/GuardingItems.java (83%) rename src/main/java/com/teamabode/guarding/core/{init => registry}/GuardingParticles.java (82%) rename src/main/java/com/teamabode/guarding/core/{init => registry}/GuardingRecipeSerializers.java (94%) rename src/main/java/com/teamabode/guarding/core/{init => registry}/GuardingSounds.java (89%) create mode 100644 src/main/java/com/teamabode/guarding/core/tag/GuardingDamageTypeTags.java create mode 100644 src/main/java/com/teamabode/guarding/core/tag/GuardingItemTags.java create mode 100644 src/main/java/com/teamabode/guarding/core/util/EnchantmentUtils.java create mode 100644 src/main/java/com/teamabode/guarding/core/util/ShieldUtils.java rename src/main/resources/data/{minecraft/tags/items/enchantable/durability.json => c/tags/item/tools/shield.json} (100%) rename src/main/resources/data/guarding/{advancements => advancement}/nether/obtain_netherite_shield.json (100%) rename src/main/resources/data/guarding/{advancements => advancement}/story/decorate_shield_with_banner.json (100%) rename src/main/resources/data/guarding/{advancements => advancement}/story/kill_mob_with_own_arrow.json (100%) create mode 100644 src/main/resources/data/guarding/enchantment/barbed.json create mode 100644 src/main/resources/data/guarding/enchantment/pummeling.json rename src/main/resources/data/guarding/{recipes => recipe}/netherite_shield_smithing.json (100%) create mode 100644 src/main/resources/data/guarding/tags/damage_type/no_parry.json create mode 100644 src/main/resources/data/guarding/tags/item/enchantable/shield.json rename src/main/resources/data/{guarding/tags/items/enchantable/shield.json => minecraft/tags/item/enchantable/durability.json} (74%) rename src/main/resources/data/minecraft/tags/{items => item}/trimmable_armor.json (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e2fa68a..15ae91e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: matrix: # Use these Java versions java: [ - 17, # Current Java LTS & minimum supported by Minecraft + 21, # Current Java LTS & minimum supported by Minecraft ] # and run on both Linux and Windows os: [ubuntu-22.04, windows-2022] @@ -33,7 +33,7 @@ jobs: - name: build run: ./gradlew build - name: capture build artifacts - if: ${{ runner.os == 'Linux' && matrix.java == '17' }} # Only upload artifacts built from latest java on one OS + if: ${{ runner.os == 'Linux' && matrix.java == '21' }} # Only upload artifacts built from latest java on one OS uses: actions/upload-artifact@v3 with: name: Artifacts diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d5c4a7d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +### Gameplay Changes +* Netherite Shield enchantability has been reduced. `20 -> 15` +* Barbed durability damage has been reduced. `2 -> 1` +* Barbed success chance has been increased. `20% -> 33%` + +### Config Changes +* The enchantability of the Shield and Netherite Shield have been made configurable. +* Configurations for Pummeling and Barbed and projectile deflection strength have been removed. + +### Technical Changes +Guarding now uses 1.21's data driven enchantments, for this reason, several configurations were removed in favor of this new system. + +Added 3 new enchantment effect components: + +`guarding:shield_blocked`: Effects applying after an attack is blocked. +* Condition Context: Damage Parameters +* Effect: Entity Effect +* Additional fields: + - `cancel_on_parry`: When true, stops the effects from being applied when a parry is landed + - `affected`: A specifier for whom the effect is applied to. Possible values are `attacker`, `damaging_entity`, and `victim` + +`guarding:shield_parried`: Effects applying after an attack is parried. +* Condition Context: Damage Parameters +* Effect: Entity Effect +* Additional fields: + - `affected`: A specifier for whom the effect is applied to. Possible values are `attacker`, `damaging_entity`, and `victim` + +`guarding:shield_knockback`: Effects for the amount of knockback to deal when an attack is blocked. +* Condition Context: Damage Parameters +* Effect: Value Effect diff --git a/gradle.properties b/gradle.properties index 34c4dae..bd53cb0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G org.gradle.parallel=true # Fabric Properties - minecraft_version=1.20.6 + minecraft_version=1.21 loader_version=0.15.11 # Mod Properties @@ -11,5 +11,5 @@ org.gradle.parallel=true archives_base_name = guarding # Dependencies - fabric_version=0.97.8+1.20.6 - sketch_version=1.20.6-1.1.0 + fabric_version=0.100.3+1.21 + sketch_version=1.21-1.2.0 diff --git a/src/main/java/com/teamabode/guarding/Guarding.java b/src/main/java/com/teamabode/guarding/Guarding.java index 3df2f47..37424d7 100644 --- a/src/main/java/com/teamabode/guarding/Guarding.java +++ b/src/main/java/com/teamabode/guarding/Guarding.java @@ -1,12 +1,11 @@ package com.teamabode.guarding; -import com.teamabode.guarding.core.init.*; +import com.teamabode.guarding.core.registry.*; +import com.teamabode.guarding.core.util.ShieldUtils; import com.teamabode.sketch.core.api.config.ConfigManager; +import com.teamabode.sketch.core.api.event.ShieldEvents; import net.fabricmc.api.ModInitializer; -import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,20 +13,19 @@ public class Guarding implements ModInitializer { public static final String MOD_ID = "guarding"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); - public static final TagKey SHIELD_ENCHANTABLE = TagKey.create(Registries.ITEM, id("enchantable/shield")); - public void onInitialize() { GuardingItems.init(); - GuardingEnchantments.init(); + GuardingEnchantmentEffects.init(); GuardingSounds.init(); GuardingParticles.init(); - GuardingCallbacks.init(); GuardingCritieriaTriggers.init(); GuardingRecipeSerializers.init(); + + ShieldEvents.BLOCKED.register(ShieldUtils::onBlocked); ConfigManager.INSTANCE.register(GuardingConfig.INSTANCE); } public static ResourceLocation id(String name) { - return new ResourceLocation(MOD_ID, name); + return ResourceLocation.fromNamespaceAndPath(MOD_ID, name); } } diff --git a/src/main/java/com/teamabode/guarding/GuardingConfig.java b/src/main/java/com/teamabode/guarding/GuardingConfig.java index 0e6eb12..ba1db2e 100644 --- a/src/main/java/com/teamabode/guarding/GuardingConfig.java +++ b/src/main/java/com/teamabode/guarding/GuardingConfig.java @@ -2,28 +2,25 @@ import com.teamabode.sketch.core.api.config.Config; import com.teamabode.sketch.core.api.config.FloatProperty; +import com.teamabode.sketch.core.api.config.IntProperty; +// TODO: Item to int map property which allows custom shields to be given enchantibility. public class GuardingConfig extends Config { public static final GuardingConfig INSTANCE = new GuardingConfig(); public final FloatProperty exhaustionCost; public final FloatProperty knockbackStrength; - public final FloatProperty projectileReflectStrength; - public final FloatProperty damageAmount; - public final FloatProperty damageChance; - public final FloatProperty additionalKnockbackStrengthPerLevel; + public final IntProperty shieldEnchantibility; + public final IntProperty netheriteShieldEnchantibility; public GuardingConfig() { super("guarding"); this.exhaustionCost = new FloatProperty("exhaustion_cost", 2.0f); this.knockbackStrength = new FloatProperty("knockback_strength", 0.5f); - this.projectileReflectStrength = new FloatProperty("projectile_reflect_strength", 1.25f); - this.damageAmount = new FloatProperty("damage_amount", 2.0f); - this.damageChance = new FloatProperty("damage_chance", 0.2f); - this.additionalKnockbackStrengthPerLevel = new FloatProperty("additional_knockback_strength_per_level", 0.15f); + this.shieldEnchantibility = new IntProperty("minecraft:shield", 9); + this.netheriteShieldEnchantibility = new IntProperty("guarding:netherite_shield", 15); - this.defineCategory("parry", this.exhaustionCost, this.knockbackStrength, this.projectileReflectStrength); - this.defineCategory("barbed", this.damageAmount, this.damageChance); - this.defineCategory("pummeling", this.additionalKnockbackStrengthPerLevel); + this.defineCategory("parry", this.exhaustionCost, this.knockbackStrength); + this.defineCategory("enchantability", this.shieldEnchantibility, this.netheriteShieldEnchantibility); } } diff --git a/src/main/java/com/teamabode/guarding/client/GuardingClient.java b/src/main/java/com/teamabode/guarding/client/GuardingClient.java index 3bc4ede..f3d5e93 100644 --- a/src/main/java/com/teamabode/guarding/client/GuardingClient.java +++ b/src/main/java/com/teamabode/guarding/client/GuardingClient.java @@ -4,8 +4,8 @@ import com.teamabode.guarding.client.model.NetheriteShieldModel; import com.teamabode.guarding.client.particle.ParryParticle; import com.teamabode.guarding.client.render.NetheriteShieldRenderer; -import com.teamabode.guarding.core.init.GuardingItems; -import com.teamabode.guarding.core.init.GuardingParticles; +import com.teamabode.guarding.core.registry.GuardingItems; +import com.teamabode.guarding.core.registry.GuardingParticles; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; import net.fabricmc.fabric.api.client.rendering.v1.BuiltinItemRendererRegistry; @@ -29,7 +29,7 @@ private static void netheriteShield() { NetheriteShieldRenderer renderer = new NetheriteShieldRenderer(); BuiltinItemRendererRegistry.INSTANCE.register(GuardingItems.NETHERITE_SHIELD, renderer); ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(renderer); - ItemProperties.register(GuardingItems.NETHERITE_SHIELD, new ResourceLocation(Guarding.MOD_ID,"blocking"), GuardingClient::blockingPredicate); + ItemProperties.register(GuardingItems.NETHERITE_SHIELD, Guarding.id("blocking"), GuardingClient::blockingPredicate); } private static float blockingPredicate(ItemStack stack, ClientLevel level, LivingEntity user, int i) { diff --git a/src/main/java/com/teamabode/guarding/client/model/NetheriteShieldModel.java b/src/main/java/com/teamabode/guarding/client/model/NetheriteShieldModel.java index 15a313a..166c713 100644 --- a/src/main/java/com/teamabode/guarding/client/model/NetheriteShieldModel.java +++ b/src/main/java/com/teamabode/guarding/client/model/NetheriteShieldModel.java @@ -17,8 +17,8 @@ import net.minecraft.world.item.armortrim.ArmorTrim; public class NetheriteShieldModel extends ShieldModel { - public static final ModelLayerLocation LAYER = new ModelLayerLocation(new ResourceLocation(Guarding.MOD_ID, "netherite_shield"), "main"); - public static final ResourceLocation TEXTURE = new ResourceLocation(Guarding.MOD_ID, "textures/entity/netherite_shield.png"); + public static final ModelLayerLocation LAYER = new ModelLayerLocation(Guarding.id("netherite_shield"), "main"); + public static final ResourceLocation TEXTURE = Guarding.id("textures/entity/netherite_shield.png"); private final TextureAtlas atlas; @@ -31,11 +31,11 @@ public void renderTrim(PoseStack poseStack, MultiBufferSource bufferSource, int TextureAtlasSprite sprite = atlas.getSprite(trimTexture(trim)); VertexConsumer vertex = sprite.wrap(bufferSource.getBuffer(RenderType.entityCutout(Sheets.ARMOR_TRIMS_SHEET))); - this.renderToBuffer(poseStack, vertex, light, OverlayTexture.NO_OVERLAY, 1.0f, 1.0f, 1.0f, 1.0f); + this.renderToBuffer(poseStack, vertex, light, OverlayTexture.NO_OVERLAY); } public void renderGlint(PoseStack poseStack, MultiBufferSource bufferSource, int light) { - this.renderToBuffer(poseStack, ItemRenderer.getFoilBuffer(bufferSource, RenderType.armorGlint(), false, true), light, OverlayTexture.NO_OVERLAY, 1.0f, 1.0f, 1.0f, 1.0f); + this.renderToBuffer(poseStack, ItemRenderer.getFoilBuffer(bufferSource, RenderType.armorEntityGlint(), false, true), light, OverlayTexture.NO_OVERLAY); } private static ResourceLocation trimTexture(ArmorTrim trim) { diff --git a/src/main/java/com/teamabode/guarding/client/render/NetheriteShieldRenderer.java b/src/main/java/com/teamabode/guarding/client/render/NetheriteShieldRenderer.java index 6333017..fc6dbe2 100644 --- a/src/main/java/com/teamabode/guarding/client/render/NetheriteShieldRenderer.java +++ b/src/main/java/com/teamabode/guarding/client/render/NetheriteShieldRenderer.java @@ -23,7 +23,7 @@ public class NetheriteShieldRenderer implements BuiltinItemRendererRegistry.Dyna private NetheriteShieldModel model; public ResourceLocation getFabricId() { - return new ResourceLocation(Guarding.MOD_ID, "netherite_shield_renderer"); + return Guarding.id("netherite_shield_renderer"); } public void render(ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay) { @@ -31,7 +31,7 @@ public void render(ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack.scale(1.0f, -1.0f, -1.0f); VertexConsumer buffer = bufferSource.getBuffer(model.renderType(NetheriteShieldModel.TEXTURE)); - model.renderToBuffer(poseStack, buffer, light, overlay, 1.0f, 1.0f, 1.0f, 1.0f); + model.renderToBuffer(poseStack, buffer, light, overlay); ClientLevel level = Minecraft.getInstance().level; if (level != null && stack.has(DataComponents.TRIM)) { diff --git a/src/main/java/com/teamabode/guarding/common/enchantment/BarbedEnchantment.java b/src/main/java/com/teamabode/guarding/common/enchantment/BarbedEnchantment.java deleted file mode 100644 index 2fc55eb..0000000 --- a/src/main/java/com/teamabode/guarding/common/enchantment/BarbedEnchantment.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.teamabode.guarding.common.enchantment; - -import net.minecraft.world.item.enchantment.Enchantment; - -public class BarbedEnchantment extends ShieldEnchantment { - public BarbedEnchantment() { - super(2, 1, Enchantment.constantCost(20), Enchantment.constantCost(50), 2); - } -} diff --git a/src/main/java/com/teamabode/guarding/common/enchantment/BlockedConditionalEffect.java b/src/main/java/com/teamabode/guarding/common/enchantment/BlockedConditionalEffect.java new file mode 100644 index 0000000..5116124 --- /dev/null +++ b/src/main/java/com/teamabode/guarding/common/enchantment/BlockedConditionalEffect.java @@ -0,0 +1,35 @@ +package com.teamabode.guarding.common.enchantment; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.world.item.enchantment.ConditionalEffect; +import net.minecraft.world.item.enchantment.EnchantmentTarget; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet; +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; + +import java.util.Optional; + +public record BlockedConditionalEffect(EnchantmentTarget affected, T effect, boolean cancelOnParry, Optional requirements) { + + public static Codec> parriedCodec(Codec codec, LootContextParamSet contextSet) { + return RecordCodecBuilder.create(instance -> instance.group( + EnchantmentTarget.CODEC.fieldOf("affected").forGetter(BlockedConditionalEffect::affected), + codec.fieldOf("effect").forGetter(BlockedConditionalEffect::effect), + ConditionalEffect.conditionCodec(contextSet).optionalFieldOf("requirements").forGetter(BlockedConditionalEffect::requirements) + ).apply(instance, (affected, effect, requirements) -> new BlockedConditionalEffect<>(affected, effect, false, requirements))); + } + + public static Codec> codec(Codec codec, LootContextParamSet contextSet) { + return RecordCodecBuilder.create(instance -> instance.group( + EnchantmentTarget.CODEC.fieldOf("affected").forGetter(BlockedConditionalEffect::affected), + codec.fieldOf("effect").forGetter(BlockedConditionalEffect::effect), + Codec.BOOL.fieldOf("cancel_on_parry").forGetter(BlockedConditionalEffect::cancelOnParry), + ConditionalEffect.conditionCodec(contextSet).optionalFieldOf("requirements").forGetter(BlockedConditionalEffect::requirements) + ).apply(instance, BlockedConditionalEffect::new)); + } + + public boolean matches(LootContext lootContext) { + return this.requirements.map(lootItemCondition -> lootItemCondition.test(lootContext)).orElse(true); + } +} diff --git a/src/main/java/com/teamabode/guarding/common/enchantment/EnchantmentConsumer.java b/src/main/java/com/teamabode/guarding/common/enchantment/EnchantmentConsumer.java new file mode 100644 index 0000000..074cbc5 --- /dev/null +++ b/src/main/java/com/teamabode/guarding/common/enchantment/EnchantmentConsumer.java @@ -0,0 +1,9 @@ +package com.teamabode.guarding.common.enchantment; + +import net.minecraft.core.Holder; +import net.minecraft.world.item.enchantment.Enchantment; + +@FunctionalInterface +public interface EnchantmentConsumer { + void accept(Holder holder, int level); +} diff --git a/src/main/java/com/teamabode/guarding/common/enchantment/PummelingEnchantment.java b/src/main/java/com/teamabode/guarding/common/enchantment/PummelingEnchantment.java deleted file mode 100644 index 3c97b1d..0000000 --- a/src/main/java/com/teamabode/guarding/common/enchantment/PummelingEnchantment.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.teamabode.guarding.common.enchantment; - -import net.minecraft.world.item.enchantment.Enchantment; - -public class PummelingEnchantment extends ShieldEnchantment { - - public PummelingEnchantment() { - super(5, 3, Enchantment.dynamicCost(10, 10), Enchantment.dynamicCost(60, 10), 4); - } -} diff --git a/src/main/java/com/teamabode/guarding/common/enchantment/ShieldEnchantment.java b/src/main/java/com/teamabode/guarding/common/enchantment/ShieldEnchantment.java deleted file mode 100644 index 7681b77..0000000 --- a/src/main/java/com/teamabode/guarding/common/enchantment/ShieldEnchantment.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.teamabode.guarding.common.enchantment; - -import com.teamabode.guarding.Guarding; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.enchantment.Enchantment; - -public class ShieldEnchantment extends Enchantment { - public ShieldEnchantment(int weight, int maxLevel, Cost minCost, Cost maxCost, int anvilCost) { - super(Enchantment.definition(Guarding.SHIELD_ENCHANTABLE, weight, maxLevel, minCost, maxCost, anvilCost, EquipmentSlot.MAINHAND)); - } -} diff --git a/src/main/java/com/teamabode/guarding/common/item/NetheriteShieldItem.java b/src/main/java/com/teamabode/guarding/common/item/NetheriteShieldItem.java index c6b598e..e8899d4 100644 --- a/src/main/java/com/teamabode/guarding/common/item/NetheriteShieldItem.java +++ b/src/main/java/com/teamabode/guarding/common/item/NetheriteShieldItem.java @@ -1,14 +1,13 @@ package com.teamabode.guarding.common.item; import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.Multimap; -import com.teamabode.guarding.core.init.GuardingSounds; +import com.teamabode.guarding.Guarding; +import com.teamabode.guarding.GuardingConfig; +import com.teamabode.guarding.core.registry.GuardingSounds; import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlotGroup; -import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.item.ItemStack; @@ -20,6 +19,8 @@ import java.util.function.Supplier; public class NetheriteShieldItem extends ShieldItem { + private static final ResourceLocation KNOCKBACK_RESISTANCE = Guarding.id("knockback_resistance"); + private static final UUID MODIIFER_UUID = UUID.fromString("8b128327-f878-4e94-ada2-707cd81b13af"); private final Supplier defaultModifiers; @@ -28,7 +29,7 @@ public NetheriteShieldItem(Properties properties) { this.defaultModifiers = Suppliers.memoize(() -> { ItemAttributeModifiers.Builder builder = ItemAttributeModifiers.builder(); - builder.add(Attributes.KNOCKBACK_RESISTANCE, new AttributeModifier(MODIIFER_UUID, "Shield modifier", 0.1d, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.OFFHAND); + builder.add(Attributes.KNOCKBACK_RESISTANCE, new AttributeModifier(KNOCKBACK_RESISTANCE, 0.1d, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.OFFHAND); return builder.build(); }); } @@ -39,7 +40,7 @@ public ItemAttributeModifiers getDefaultAttributeModifiers() { } public int getEnchantmentValue() { - return 15; + return GuardingConfig.INSTANCE.netheriteShieldEnchantibility.get(); } public Holder getEquipSound() { diff --git a/src/main/java/com/teamabode/guarding/common/recipe/SmithingTransformShieldRecipe.java b/src/main/java/com/teamabode/guarding/common/recipe/SmithingTransformShieldRecipe.java index 02a34c5..a92d8c2 100644 --- a/src/main/java/com/teamabode/guarding/common/recipe/SmithingTransformShieldRecipe.java +++ b/src/main/java/com/teamabode/guarding/common/recipe/SmithingTransformShieldRecipe.java @@ -1,23 +1,17 @@ package com.teamabode.guarding.common.recipe; -import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import com.teamabode.guarding.Guarding; -import com.teamabode.guarding.core.init.GuardingRecipeSerializers; +import com.teamabode.guarding.core.registry.GuardingRecipeSerializers; import net.minecraft.core.HolderLookup; -import net.minecraft.core.RegistryAccess; import net.minecraft.core.component.DataComponents; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.SmithingRecipe; +import net.minecraft.world.item.crafting.SmithingRecipeInput; import net.minecraft.world.level.Level; import java.util.stream.Stream; @@ -32,30 +26,23 @@ public record SmithingTransformShieldRecipe(Ingredient template, Ingredient base public static final StreamCodec STREAM_CODEC = StreamCodec.of(Serializer::toNetwork, Serializer::fromNetwork); - public SmithingTransformShieldRecipe(Ingredient template, Ingredient base, Ingredient addition, ItemStack result) { - this.template = template; - this.base = base; - this.addition = addition; - this.result = result; - } - @Override - public boolean matches(Container container, Level level) { - return this.template.test(container.getItem(0)) && this.base.test(container.getItem(1)) && this.addition.test(container.getItem(2)); + public boolean matches(SmithingRecipeInput input, Level level) { + return this.template.test(input.template()) && this.base.test(input.base()) && this.addition.test(input.addition()); } @Override - public ItemStack assemble(Container container, HolderLookup.Provider provider) { - ItemStack itemStack = container.getItem(1).transmuteCopy(this.result.getItem(), this.result.getCount()); + public ItemStack assemble(SmithingRecipeInput input, HolderLookup.Provider provider) { + ItemStack stack = input.base().transmuteCopy(this.result.getItem(), this.result.getCount()); - if (itemStack.has(DataComponents.BASE_COLOR)) { - itemStack.remove(DataComponents.BASE_COLOR); + if (stack.has(DataComponents.BASE_COLOR)) { + stack.remove(DataComponents.BASE_COLOR); } - if (itemStack.has(DataComponents.BANNER_PATTERNS)) { - itemStack.remove(DataComponents.BANNER_PATTERNS); + if (stack.has(DataComponents.BANNER_PATTERNS)) { + stack.remove(DataComponents.BANNER_PATTERNS); } - itemStack.applyComponents(this.result.getComponentsPatch()); - return itemStack; + stack.applyComponents(this.result.getComponentsPatch()); + return stack; } @Override diff --git a/src/main/java/com/teamabode/guarding/core/config/ItemToEnchantabilityProperty.java b/src/main/java/com/teamabode/guarding/core/config/ItemToEnchantabilityProperty.java new file mode 100644 index 0000000..ec46130 --- /dev/null +++ b/src/main/java/com/teamabode/guarding/core/config/ItemToEnchantabilityProperty.java @@ -0,0 +1,53 @@ +package com.teamabode.guarding.core.config; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.teamabode.guarding.Guarding; +import com.teamabode.sketch.core.api.config.ConfigProperty; +import net.minecraft.resources.ResourceLocation; + +import java.util.Map; + +// WIP +public class ItemToEnchantabilityProperty extends ConfigProperty> { + + public ItemToEnchantabilityProperty(String name, Map defaultValue) { + super(name, defaultValue); + } + + @Override + public Map get() { + return (Map) this.value; + } + + @Override + public JsonElement toJson() { + JsonObject root = new JsonObject(); + this.get().forEach((location, integer) -> { + root.addProperty(location.toString(), integer); + }); + return root; + } + + @Override + public Map fromJson(JsonElement element) { + ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); + JsonObject root = element.getAsJsonObject(); + + for (var entry : root.entrySet()) { + ResourceLocation location = ResourceLocation.tryParse(entry.getKey()); + + if (location == null) { + Guarding.LOGGER.warn("{} is an invalid resource location", entry.getKey()); + continue; + } + if (!entry.getValue().isJsonPrimitive() || !entry.getValue().getAsJsonPrimitive().isNumber()) { + Guarding.LOGGER.warn("{} is not an integer", entry.getValue().getAsInt()); + } + int enchantability = entry.getValue().getAsInt(); + builder.put(location, enchantability); + } + return builder.build(); + } +} diff --git a/src/main/java/com/teamabode/guarding/core/init/GuardingCallbacks.java b/src/main/java/com/teamabode/guarding/core/init/GuardingCallbacks.java deleted file mode 100644 index c93cb48..0000000 --- a/src/main/java/com/teamabode/guarding/core/init/GuardingCallbacks.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.teamabode.guarding.core.init; - -import com.teamabode.guarding.Guarding; -import com.teamabode.guarding.GuardingConfig; -import com.teamabode.guarding.core.access.ProjectileAccessor; -import com.teamabode.sketch.core.api.event.ShieldEvents; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.RandomSource; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; - -public class GuardingCallbacks { - - public static void init() { - ShieldEvents.BLOCKED.register(GuardingCallbacks::onBlocked); - } - - // Logic for blocking - private static void onBlocked(Player user, DamageSource source, float amount) { - Entity sourceEntity = source.getDirectEntity(); - boolean isParry = (user.getUseItem().getUseDuration() - user.getUseItemRemainingTicks()) <= 3; - if (sourceEntity instanceof LivingEntity attacker) blockLivingEntity(user, attacker, isParry); - if (sourceEntity instanceof Projectile projectile) blockProjectile(user, source.getEntity(), projectile, isParry); - - if (isParry) { - parryEffects(user, sourceEntity); - } - } - - // Logic for blocking a living entity - private static void blockLivingEntity(Player user, LivingEntity attacker, boolean isParry) { - if (isParry) { - float exhaustion = GuardingConfig.INSTANCE.exhaustionCost.get(); - float strength = getKnockbackStrength(user.getUseItem()); - - user.causeFoodExhaustion(exhaustion); - attacker.knockback(strength, user.getX() - attacker.getX(), user.getZ() - attacker.getZ()); - attacker.hurtMarked = true; - } - handleBarbed(user, attacker, isParry); - } - - // Logic for blocking a projectile - private static void blockProjectile(Player user, Entity damageCauser, Projectile projectile, boolean isParry) { - if (!isParry || damageCauser == null) return; - float projectileReflectStrength = GuardingConfig.INSTANCE.projectileReflectStrength.get(); - if (projectile instanceof ProjectileAccessor accessor) accessor.setParrier(user); - Vec3 motion = new Vec3(user.getX() - damageCauser.getX(), 0.0f, user.getZ() - damageCauser.getZ()).scale(projectileReflectStrength); - projectile.setDeltaMovement(motion.x(), -1.5f, motion.z()); - projectile.hurtMarked = true; - } - - // Handles all code for the barbed enchantment - private static void handleBarbed(Player user, LivingEntity attacker, boolean isParry) { - RandomSource random = user.getRandom(); - float damage = GuardingConfig.INSTANCE.damageAmount.get(); - float chance = GuardingConfig.INSTANCE.damageChance.get(); - int barbedLevel = EnchantmentHelper.getItemEnchantmentLevel(GuardingEnchantments.BARBED, user.getUseItem()); - if (barbedLevel <= 0) return; - damage += isParry ? 1.0f : 0.0f; // Parrying will cause barbed to increase it's power. - - if ((random.nextFloat() <= chance && chance > 0.0f) || isParry || chance >= 1.0f) { - attacker.hurt(attacker.damageSources().thorns(user), damage); - user.hurtCurrentlyUsedShield(2.0f); - } - } - - // Determines the knockback strength on parry - private static float getKnockbackStrength(ItemStack stack) { - float baseStrength = GuardingConfig.INSTANCE.knockbackStrength.get(); - float additionalStrength = GuardingConfig.INSTANCE.additionalKnockbackStrengthPerLevel.get(); - int pummelingLevel = EnchantmentHelper.getItemEnchantmentLevel(GuardingEnchantments.PUMMELING, stack); - float pummelStrength = pummelingLevel > 0 ? pummelingLevel * additionalStrength : 0.0f; - - return baseStrength + pummelStrength; - } - - // Parry visual effects (Sound and particles) - private static void parryEffects(Player user, Entity sourceEntity) { - Level level = user.level(); - SoundEvent breakSound = GuardingSounds.ITEM_SHIELD_PARRY; - level.playSound(null, user.blockPosition(), breakSound, SoundSource.PLAYERS); - - if (level instanceof ServerLevel server && sourceEntity != null) { - server.sendParticles(GuardingParticles.PARRY, sourceEntity.getX(), sourceEntity.getEyeY(), sourceEntity.getZ(), 1, 0.0d, 0.0d, 0.0d, 0.0d); - } - } -} diff --git a/src/main/java/com/teamabode/guarding/core/init/GuardingEnchantments.java b/src/main/java/com/teamabode/guarding/core/init/GuardingEnchantments.java deleted file mode 100644 index 534e1ec..0000000 --- a/src/main/java/com/teamabode/guarding/core/init/GuardingEnchantments.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.teamabode.guarding.core.init; - -import com.teamabode.guarding.Guarding; -import com.teamabode.guarding.common.enchantment.BarbedEnchantment; -import com.teamabode.guarding.common.enchantment.PummelingEnchantment; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.enchantment.Enchantment; - -public class GuardingEnchantments { - public static final Enchantment BARBED = register("barbed", new BarbedEnchantment()); - public static final Enchantment PUMMELING = register("pummeling", new PummelingEnchantment()); - - private static E register(String name, E enchantment) { - return Registry.register(BuiltInRegistries.ENCHANTMENT, new ResourceLocation(Guarding.MOD_ID, name), enchantment); - } - - public static void init() { - - } -} diff --git a/src/main/java/com/teamabode/guarding/core/mixin/KilledByParriedArrowTriggerMixin.java b/src/main/java/com/teamabode/guarding/core/mixin/KilledByParriedArrowTriggerMixin.java index 9bd348e..3e4d46b 100644 --- a/src/main/java/com/teamabode/guarding/core/mixin/KilledByParriedArrowTriggerMixin.java +++ b/src/main/java/com/teamabode/guarding/core/mixin/KilledByParriedArrowTriggerMixin.java @@ -1,7 +1,7 @@ package com.teamabode.guarding.core.mixin; import com.teamabode.guarding.core.access.ProjectileAccessor; -import com.teamabode.guarding.core.init.GuardingCritieriaTriggers; +import com.teamabode.guarding.core.registry.GuardingCritieriaTriggers; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; diff --git a/src/main/java/com/teamabode/guarding/core/mixin/NetheriteShieldMixin.java b/src/main/java/com/teamabode/guarding/core/mixin/NetheriteShieldMixin.java index 36f61ed..619f1ec 100644 --- a/src/main/java/com/teamabode/guarding/core/mixin/NetheriteShieldMixin.java +++ b/src/main/java/com/teamabode/guarding/core/mixin/NetheriteShieldMixin.java @@ -1,7 +1,8 @@ package com.teamabode.guarding.core.mixin; -import com.teamabode.guarding.core.init.GuardingItems; -import com.teamabode.guarding.core.init.GuardingSounds; +import com.teamabode.guarding.core.registry.GuardingItems; +import com.teamabode.guarding.core.registry.GuardingSounds; +import com.teamabode.guarding.core.util.ShieldUtils; import net.minecraft.stats.Stat; import net.minecraft.stats.Stats; import net.minecraft.util.Mth; @@ -10,6 +11,8 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.entity.projectile.ProjectileDeflection; import net.minecraft.world.item.ItemCooldowns; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -30,6 +33,11 @@ protected NetheriteShieldMixin(EntityType entityType, Le @Shadow public abstract void awardStat(Stat stat); + @Override + public ProjectileDeflection deflection(Projectile projectile) { + return ShieldUtils.PARRY; + } + @Inject(method = "hurtCurrentlyUsedShield", at = @At("HEAD"), cancellable = true) private void guarding$hurtCurrentlyUsedShield(float damageAmount, CallbackInfo ci) { if (useItem.is(GuardingItems.NETHERITE_SHIELD)) { diff --git a/src/main/java/com/teamabode/guarding/core/mixin/NetheriteShieldSoundMixin.java b/src/main/java/com/teamabode/guarding/core/mixin/NetheriteShieldSoundMixin.java index c960815..d8d8cbb 100644 --- a/src/main/java/com/teamabode/guarding/core/mixin/NetheriteShieldSoundMixin.java +++ b/src/main/java/com/teamabode/guarding/core/mixin/NetheriteShieldSoundMixin.java @@ -1,7 +1,7 @@ package com.teamabode.guarding.core.mixin; -import com.teamabode.guarding.core.init.GuardingItems; -import com.teamabode.guarding.core.init.GuardingSounds; +import com.teamabode.guarding.core.registry.GuardingItems; +import com.teamabode.guarding.core.registry.GuardingSounds; import net.minecraft.sounds.SoundSource; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; diff --git a/src/main/java/com/teamabode/guarding/core/mixin/ShieldDelayMixin.java b/src/main/java/com/teamabode/guarding/core/mixin/ShieldDelayMixin.java index 8c07451..9baeaa9 100644 --- a/src/main/java/com/teamabode/guarding/core/mixin/ShieldDelayMixin.java +++ b/src/main/java/com/teamabode/guarding/core/mixin/ShieldDelayMixin.java @@ -5,6 +5,9 @@ import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyConstant; +/** + * This mixin removes the 5 tick delay that exists on Shields + */ @Mixin(LivingEntity.class) public class ShieldDelayMixin { diff --git a/src/main/java/com/teamabode/guarding/core/mixin/ShieldItemMixin.java b/src/main/java/com/teamabode/guarding/core/mixin/ShieldItemMixin.java index b096001..03e6b72 100644 --- a/src/main/java/com/teamabode/guarding/core/mixin/ShieldItemMixin.java +++ b/src/main/java/com/teamabode/guarding/core/mixin/ShieldItemMixin.java @@ -1,9 +1,13 @@ package com.teamabode.guarding.core.mixin; +import com.teamabode.guarding.GuardingConfig; import net.minecraft.world.item.Item; import net.minecraft.world.item.ShieldItem; import org.spongepowered.asm.mixin.Mixin; +/** + * This mixin handles Shield enchantability + */ @Mixin(ShieldItem.class) public class ShieldItemMixin extends Item { public ShieldItemMixin(Properties properties) { @@ -11,6 +15,6 @@ public ShieldItemMixin(Properties properties) { } public int getEnchantmentValue() { - return 9; + return GuardingConfig.INSTANCE.shieldEnchantibility.get(); } } diff --git a/src/main/java/com/teamabode/guarding/core/mixin/SmithingTemplateItemMixin.java b/src/main/java/com/teamabode/guarding/core/mixin/SmithingTemplateItemMixin.java index 06bcdb1..7ba0246 100644 --- a/src/main/java/com/teamabode/guarding/core/mixin/SmithingTemplateItemMixin.java +++ b/src/main/java/com/teamabode/guarding/core/mixin/SmithingTemplateItemMixin.java @@ -11,10 +11,13 @@ import java.util.ArrayList; import java.util.List; +/** + * This mixin is used to add UI icons for Shields in the Smithing Table menu + */ @Mixin(SmithingTemplateItem.class) public class SmithingTemplateItemMixin { @Unique - private static final ResourceLocation EMPTY_SLOT_SHIELD = new ResourceLocation("item/empty_armor_slot_shield"); + private static final ResourceLocation EMPTY_SLOT_SHIELD = ResourceLocation.withDefaultNamespace("item/empty_armor_slot_shield"); @Inject(method = "createTrimmableArmorIconList", at = @At("RETURN"), cancellable = true) private static void guarding$createTrimmableArmorIconList(CallbackInfoReturnable> cir) { diff --git a/src/main/java/com/teamabode/guarding/core/init/GuardingCritieriaTriggers.java b/src/main/java/com/teamabode/guarding/core/registry/GuardingCritieriaTriggers.java similarity index 87% rename from src/main/java/com/teamabode/guarding/core/init/GuardingCritieriaTriggers.java rename to src/main/java/com/teamabode/guarding/core/registry/GuardingCritieriaTriggers.java index 9117610..e7c7f8f 100644 --- a/src/main/java/com/teamabode/guarding/core/init/GuardingCritieriaTriggers.java +++ b/src/main/java/com/teamabode/guarding/core/registry/GuardingCritieriaTriggers.java @@ -1,8 +1,7 @@ -package com.teamabode.guarding.core.init; +package com.teamabode.guarding.core.registry; import com.teamabode.guarding.Guarding; import com.teamabode.guarding.common.critieria.KilledByParriedArrowTrigger; -import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.advancements.CriterionTrigger; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; diff --git a/src/main/java/com/teamabode/guarding/core/registry/GuardingEnchantmentEffects.java b/src/main/java/com/teamabode/guarding/core/registry/GuardingEnchantmentEffects.java new file mode 100644 index 0000000..b342466 --- /dev/null +++ b/src/main/java/com/teamabode/guarding/core/registry/GuardingEnchantmentEffects.java @@ -0,0 +1,32 @@ +package com.teamabode.guarding.core.registry; + +import com.teamabode.guarding.Guarding; +import com.teamabode.guarding.common.enchantment.BlockedConditionalEffect; +import net.minecraft.core.Registry; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect; +import net.minecraft.world.item.enchantment.effects.EnchantmentValueEffect; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + +import java.util.List; +import java.util.function.UnaryOperator; + +public class GuardingEnchantmentEffects { + public static final DataComponentType SHIELD_KNOCKBACK = register("shield_knockback", builder -> builder.persistent(EnchantmentValueEffect.CODEC)); + + public static final DataComponentType>> SHIELD_BLOCKED = register("shield_blocked", builder -> builder.persistent( + BlockedConditionalEffect.codec(EnchantmentEntityEffect.CODEC, LootContextParamSets.ENCHANTED_DAMAGE).listOf() + )); + public static final DataComponentType>> SHIELD_PARRIED = register("shield_parried", builder -> builder.persistent( + BlockedConditionalEffect.parriedCodec(EnchantmentEntityEffect.CODEC, LootContextParamSets.ENCHANTED_DAMAGE).listOf() + )); + + private static DataComponentType register(String name, UnaryOperator> dataComponent) { + return Registry.register(BuiltInRegistries.ENCHANTMENT_EFFECT_COMPONENT_TYPE, Guarding.id(name), dataComponent.apply(DataComponentType.builder()).build()); + } + + public static void init() { + + } +} diff --git a/src/main/java/com/teamabode/guarding/core/registry/GuardingEnchantments.java b/src/main/java/com/teamabode/guarding/core/registry/GuardingEnchantments.java new file mode 100644 index 0000000..6c83ab6 --- /dev/null +++ b/src/main/java/com/teamabode/guarding/core/registry/GuardingEnchantments.java @@ -0,0 +1,18 @@ +package com.teamabode.guarding.core.registry; + +import com.teamabode.guarding.Guarding; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.enchantment.Enchantment; + +public class GuardingEnchantments { + public static final ResourceKey BARBED = createKey("barbed"); + public static final ResourceKey PUMMELING = createKey("pummeling"); + + private static ResourceKey createKey(String name) { + return ResourceKey.create(Registries.ENCHANTMENT, Guarding.id(name)); + } +} diff --git a/src/main/java/com/teamabode/guarding/core/init/GuardingItems.java b/src/main/java/com/teamabode/guarding/core/registry/GuardingItems.java similarity index 83% rename from src/main/java/com/teamabode/guarding/core/init/GuardingItems.java rename to src/main/java/com/teamabode/guarding/core/registry/GuardingItems.java index 3d746e0..231aa03 100644 --- a/src/main/java/com/teamabode/guarding/core/init/GuardingItems.java +++ b/src/main/java/com/teamabode/guarding/core/registry/GuardingItems.java @@ -1,6 +1,5 @@ -package com.teamabode.guarding.core.init; +package com.teamabode.guarding.core.registry; -import com.google.gson.JsonObject; import com.teamabode.guarding.Guarding; import com.teamabode.guarding.common.item.NetheriteShieldItem; import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; @@ -16,7 +15,7 @@ public class GuardingItems { public static final Item NETHERITE_SHIELD = register("netherite_shield", new NetheriteShieldItem(new Item.Properties().stacksTo(1).durability(614).fireResistant())); private static I register(String name, I item) { - return Registry.register(BuiltInRegistries.ITEM, new ResourceLocation(Guarding.MOD_ID, name), item); + return Registry.register(BuiltInRegistries.ITEM, Guarding.id(name), item); } public static void init() { diff --git a/src/main/java/com/teamabode/guarding/core/init/GuardingParticles.java b/src/main/java/com/teamabode/guarding/core/registry/GuardingParticles.java similarity index 82% rename from src/main/java/com/teamabode/guarding/core/init/GuardingParticles.java rename to src/main/java/com/teamabode/guarding/core/registry/GuardingParticles.java index 8386eaf..f64d275 100644 --- a/src/main/java/com/teamabode/guarding/core/init/GuardingParticles.java +++ b/src/main/java/com/teamabode/guarding/core/registry/GuardingParticles.java @@ -1,4 +1,4 @@ -package com.teamabode.guarding.core.init; +package com.teamabode.guarding.core.registry; import com.teamabode.guarding.Guarding; import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; @@ -12,7 +12,7 @@ public class GuardingParticles { public static final SimpleParticleType PARRY = register("parry"); private static SimpleParticleType register(String name) { - return Registry.register(BuiltInRegistries.PARTICLE_TYPE, new ResourceLocation(Guarding.MOD_ID, name), FabricParticleTypes.simple(true)); + return Registry.register(BuiltInRegistries.PARTICLE_TYPE, Guarding.id(name), FabricParticleTypes.simple(true)); } public static void init() { diff --git a/src/main/java/com/teamabode/guarding/core/init/GuardingRecipeSerializers.java b/src/main/java/com/teamabode/guarding/core/registry/GuardingRecipeSerializers.java similarity index 94% rename from src/main/java/com/teamabode/guarding/core/init/GuardingRecipeSerializers.java rename to src/main/java/com/teamabode/guarding/core/registry/GuardingRecipeSerializers.java index 1b485f6..7a2a7ff 100644 --- a/src/main/java/com/teamabode/guarding/core/init/GuardingRecipeSerializers.java +++ b/src/main/java/com/teamabode/guarding/core/registry/GuardingRecipeSerializers.java @@ -1,4 +1,4 @@ -package com.teamabode.guarding.core.init; +package com.teamabode.guarding.core.registry; import com.teamabode.guarding.Guarding; import com.teamabode.guarding.common.recipe.SmithingTransformShieldRecipe; diff --git a/src/main/java/com/teamabode/guarding/core/init/GuardingSounds.java b/src/main/java/com/teamabode/guarding/core/registry/GuardingSounds.java similarity index 89% rename from src/main/java/com/teamabode/guarding/core/init/GuardingSounds.java rename to src/main/java/com/teamabode/guarding/core/registry/GuardingSounds.java index 9c5eb62..63383dd 100644 --- a/src/main/java/com/teamabode/guarding/core/init/GuardingSounds.java +++ b/src/main/java/com/teamabode/guarding/core/registry/GuardingSounds.java @@ -1,11 +1,9 @@ -package com.teamabode.guarding.core.init; +package com.teamabode.guarding.core.registry; import com.teamabode.guarding.Guarding; -import com.teamabode.sketch.Sketch; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; public class GuardingSounds { diff --git a/src/main/java/com/teamabode/guarding/core/tag/GuardingDamageTypeTags.java b/src/main/java/com/teamabode/guarding/core/tag/GuardingDamageTypeTags.java new file mode 100644 index 0000000..1eab07c --- /dev/null +++ b/src/main/java/com/teamabode/guarding/core/tag/GuardingDamageTypeTags.java @@ -0,0 +1,11 @@ +package com.teamabode.guarding.core.tag; + +import com.teamabode.guarding.Guarding; +import net.minecraft.core.registries.Registries; +import net.minecraft.tags.TagKey; +import net.minecraft.world.damagesource.DamageType; + +public class GuardingDamageTypeTags { + + public static final TagKey NO_PARRY = TagKey.create(Registries.DAMAGE_TYPE, Guarding.id("no_parry")); +} diff --git a/src/main/java/com/teamabode/guarding/core/tag/GuardingItemTags.java b/src/main/java/com/teamabode/guarding/core/tag/GuardingItemTags.java new file mode 100644 index 0000000..b9b0274 --- /dev/null +++ b/src/main/java/com/teamabode/guarding/core/tag/GuardingItemTags.java @@ -0,0 +1,11 @@ +package com.teamabode.guarding.core.tag; + +import com.teamabode.guarding.Guarding; +import net.minecraft.core.registries.Registries; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; + +public class GuardingItemTags { + + public static final TagKey SHIELD_ENCHANTABLE = TagKey.create(Registries.ITEM, Guarding.id("enchantable/shield")); +} diff --git a/src/main/java/com/teamabode/guarding/core/util/EnchantmentUtils.java b/src/main/java/com/teamabode/guarding/core/util/EnchantmentUtils.java new file mode 100644 index 0000000..92511d5 --- /dev/null +++ b/src/main/java/com/teamabode/guarding/core/util/EnchantmentUtils.java @@ -0,0 +1,83 @@ +package com.teamabode.guarding.core.util; + +import com.teamabode.guarding.common.enchantment.BlockedConditionalEffect; +import com.teamabode.guarding.common.enchantment.EnchantmentConsumer; +import com.teamabode.guarding.core.registry.GuardingEnchantmentEffects; +import net.minecraft.core.component.DataComponents; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.*; +import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect; +import org.apache.commons.lang3.mutable.MutableFloat; + +public class EnchantmentUtils { + + public static float modifyParryKnockback(Player player, float baseStrength) { + MutableFloat strength = new MutableFloat(baseStrength); + runIterationOnItem(player.getUseItem(), (holder, level) -> { + Enchantment enchantment = holder.value(); + enchantment.modifyUnfilteredValue(GuardingEnchantmentEffects.SHIELD_KNOCKBACK, player.getRandom(), level, strength); + }); + return strength.floatValue(); + } + + public static void runBlockedEffects(ServerLevel server, Player player, DamageSource source, boolean performedParry) { + ItemStack stack = player.getUseItem(); + runIterationOnItem(stack, (holder, level) -> { + Enchantment enchantment = holder.value(); + EnchantedItemInUse enchantedItem = new EnchantedItemInUse(stack, getSlotFromHand(player.getUsedItemHand()), player); + + for (var blockedCondition : enchantment.getEffects(GuardingEnchantmentEffects.SHIELD_BLOCKED)) { + if (performedParry && blockedCondition.cancelOnParry()) { + continue; + } + tryEffect(blockedCondition, server, level, enchantedItem, player, source); + } + }); + } + + public static void runParriedEffects(ServerLevel server, Player player, DamageSource source) { + ItemStack stack = player.getUseItem(); + runIterationOnItem(stack, (holder, level) -> { + Enchantment enchantment = holder.value(); + EnchantedItemInUse enchantedItem = new EnchantedItemInUse(stack, getSlotFromHand(player.getUsedItemHand()), player); + + for (var targetedCondition : enchantment.getEffects(GuardingEnchantmentEffects.SHIELD_PARRIED)) { + tryEffect(targetedCondition, server, level, enchantedItem, player, source); + } + }); + } + + public static EquipmentSlot getSlotFromHand(InteractionHand hand) { + if (hand == InteractionHand.MAIN_HAND) { + return EquipmentSlot.MAINHAND; + } + return EquipmentSlot.OFFHAND; + } + + public static void tryEffect(BlockedConditionalEffect blockedCondition, ServerLevel server, int level, EnchantedItemInUse enchantedItem, Player player, DamageSource source) { + if (blockedCondition.matches(Enchantment.damageContext(server, level, player, source))) { + Entity target = switch (blockedCondition.affected()) { + case VICTIM -> player; + case ATTACKER -> source.getEntity(); + case DAMAGING_ENTITY -> source.getDirectEntity(); + }; + if (target != null) { + blockedCondition.effect().apply(server, level, enchantedItem, target, target.position()); + } + } + } + + public static void runIterationOnItem(ItemStack stack, EnchantmentConsumer consumer) { + ItemEnchantments enchantments = stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY); + + for (var entry : enchantments.entrySet()) { + consumer.accept(entry.getKey(), entry.getIntValue()); + } + } +} diff --git a/src/main/java/com/teamabode/guarding/core/util/ShieldUtils.java b/src/main/java/com/teamabode/guarding/core/util/ShieldUtils.java new file mode 100644 index 0000000..e90bfac --- /dev/null +++ b/src/main/java/com/teamabode/guarding/core/util/ShieldUtils.java @@ -0,0 +1,72 @@ +package com.teamabode.guarding.core.util; + +import com.teamabode.guarding.GuardingConfig; +import com.teamabode.guarding.core.access.ProjectileAccessor; +import com.teamabode.guarding.core.registry.GuardingParticles; +import com.teamabode.guarding.core.registry.GuardingSounds; +import com.teamabode.guarding.core.tag.GuardingDamageTypeTags; +import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.Projectile; + +public class ShieldUtils { + + public static void onBlocked(Player user, DamageSource source, float amount) { + if (!(user.level() instanceof ServerLevel server)) return; + boolean performedParry = canPerformParry(user, source); + + if (performedParry) { + parry(server, user, source); + } + EnchantmentUtils.runBlockedEffects(server, user, source, performedParry); + } + + public static void parry(ServerLevel server, Player player, DamageSource source) { + if (source.getDirectEntity() instanceof Projectile projectile) { + deflectProjectile(player, projectile); + spawnParticle(server, projectile.getX(), projectile.getY(), projectile.getZ()); + } + else if (source.getDirectEntity() instanceof LivingEntity attacker) { + knockbackAttacker(player, attacker); + spawnParticle(server, (player.getX() + attacker.getX()) / 2, attacker.getEyeY(), (player.getZ() + attacker.getZ()) / 2); + } + player.causeFoodExhaustion(GuardingConfig.INSTANCE.exhaustionCost.get()); + server.playSound(null, player.blockPosition(), GuardingSounds.ITEM_SHIELD_PARRY, SoundSource.PLAYERS); + EnchantmentUtils.runParriedEffects(server, player, source); + } + + public static void knockbackAttacker(Player player, LivingEntity attacker) { + float knockbackStrength = getKnockbackStrength(player); + attacker.knockback(knockbackStrength, player.getX() - attacker.getX(), player.getZ() - attacker.getZ()); + } + + public static void deflectProjectile(Player player, Projectile projectile) { + ((ProjectileAccessor) projectile).setParrier(player); + + projectile.setDeltaMovement(projectile.getDeltaMovement().scale(-0.5f)); + float reverseRot = 170.0F + projectile.getRandom().nextFloat() * 20.0F; + projectile.setYRot(projectile.getYRot() + reverseRot); + projectile.hasImpulse = true; + } + + public static float getKnockbackStrength(Player player) { + float baseStrength = GuardingConfig.INSTANCE.knockbackStrength.get(); + return EnchantmentUtils.modifyParryKnockback(player, baseStrength); + } + + public static void spawnParticle(ServerLevel server, double x, double y, double z) { + server.sendParticles(GuardingParticles.PARRY, x, y, z, 1, 0.0d, 0.0d, 0.0d, 0.0d); + } + + public static boolean canPerformParry(Player player, DamageSource source) { + return player.getTicksUsingItem() <= 3 && !source.is(GuardingDamageTypeTags.NO_PARRY); + } + + public static boolean canDeflectProjectile(Player player) { + return player.getUseItem().is(ConventionalItemTags.SHIELD_TOOLS) && player.getTicksUsingItem() <= 3; + } +} diff --git a/src/main/resources/data/minecraft/tags/items/enchantable/durability.json b/src/main/resources/data/c/tags/item/tools/shield.json similarity index 100% rename from src/main/resources/data/minecraft/tags/items/enchantable/durability.json rename to src/main/resources/data/c/tags/item/tools/shield.json diff --git a/src/main/resources/data/guarding/advancements/nether/obtain_netherite_shield.json b/src/main/resources/data/guarding/advancement/nether/obtain_netherite_shield.json similarity index 100% rename from src/main/resources/data/guarding/advancements/nether/obtain_netherite_shield.json rename to src/main/resources/data/guarding/advancement/nether/obtain_netherite_shield.json diff --git a/src/main/resources/data/guarding/advancements/story/decorate_shield_with_banner.json b/src/main/resources/data/guarding/advancement/story/decorate_shield_with_banner.json similarity index 100% rename from src/main/resources/data/guarding/advancements/story/decorate_shield_with_banner.json rename to src/main/resources/data/guarding/advancement/story/decorate_shield_with_banner.json diff --git a/src/main/resources/data/guarding/advancements/story/kill_mob_with_own_arrow.json b/src/main/resources/data/guarding/advancement/story/kill_mob_with_own_arrow.json similarity index 100% rename from src/main/resources/data/guarding/advancements/story/kill_mob_with_own_arrow.json rename to src/main/resources/data/guarding/advancement/story/kill_mob_with_own_arrow.json diff --git a/src/main/resources/data/guarding/enchantment/barbed.json b/src/main/resources/data/guarding/enchantment/barbed.json new file mode 100644 index 0000000..ba2df50 --- /dev/null +++ b/src/main/resources/data/guarding/enchantment/barbed.json @@ -0,0 +1,68 @@ +{ + "anvil_cost": 8, + "description": { + "translate": "enchantment.guarding.barbed" + }, + "effects": { + "guarding:shield_parried": [ + { + "effect": { + "type": "minecraft:all_of", + "effects": [ + { + "type": "minecraft:damage_entity", + "damage_type": "minecraft:thorns", + "min_damage": 4.0, + "max_damage": 4.0 + }, + { + "type": "minecraft:damage_item", + "amount": 1.0 + } + ] + }, + "affected": "attacker" + } + ], + "guarding:shield_blocked": [ + { + "effect": { + "type": "minecraft:all_of", + "effects": [ + { + "type": "minecraft:damage_entity", + "damage_type": "minecraft:thorns", + "min_damage": 3.0, + "max_damage": 3.0 + }, + { + "type": "minecraft:damage_item", + "amount": 1.0 + } + ] + }, + "requirements": { + "condition": "minecraft:random_chance", + "chance": 0.33 + }, + "affected": "attacker", + "cancel_on_parry": true + } + ] + }, + "max_cost": { + "base": 75, + "per_level_above_first": 25 + }, + "max_level": 1, + "min_cost": { + "base": 25, + "per_level_above_first": 25 + }, + "slots": [ + "mainhand", + "offhand" + ], + "supported_items": "#guarding:enchantable/shield", + "weight": 2 +} \ No newline at end of file diff --git a/src/main/resources/data/guarding/enchantment/pummeling.json b/src/main/resources/data/guarding/enchantment/pummeling.json new file mode 100644 index 0000000..3df5082 --- /dev/null +++ b/src/main/resources/data/guarding/enchantment/pummeling.json @@ -0,0 +1,31 @@ +{ + "anvil_cost": 4, + "description": { + "translate": "enchantment.guarding.pummeling" + }, + "effects": { + "guarding:shield_knockback": { + "type": "minecraft:add", + "value": { + "type": "minecraft:linear", + "base": 0.15, + "per_level_above_first": 0.15 + } + } + }, + "max_cost": { + "base": 55, + "per_level_above_first": 8 + }, + "max_level": 3, + "min_cost": { + "base": 5, + "per_level_above_first": 8 + }, + "slots": [ + "mainhand", + "offhand" + ], + "supported_items": "#guarding:enchantable/shield", + "weight": 5 +} \ No newline at end of file diff --git a/src/main/resources/data/guarding/recipes/netherite_shield_smithing.json b/src/main/resources/data/guarding/recipe/netherite_shield_smithing.json similarity index 100% rename from src/main/resources/data/guarding/recipes/netherite_shield_smithing.json rename to src/main/resources/data/guarding/recipe/netherite_shield_smithing.json diff --git a/src/main/resources/data/guarding/tags/damage_type/no_parry.json b/src/main/resources/data/guarding/tags/damage_type/no_parry.json new file mode 100644 index 0000000..c3becf4 --- /dev/null +++ b/src/main/resources/data/guarding/tags/damage_type/no_parry.json @@ -0,0 +1,6 @@ +{ + "values": [ + "#minecraft:is_explosion", + "#minecraft:bypasses_shield" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/guarding/tags/item/enchantable/shield.json b/src/main/resources/data/guarding/tags/item/enchantable/shield.json new file mode 100644 index 0000000..8f7d917 --- /dev/null +++ b/src/main/resources/data/guarding/tags/item/enchantable/shield.json @@ -0,0 +1,8 @@ +{ + "values": [ + { + "id": "#c:tools/shield", + "required": false + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/guarding/tags/items/enchantable/shield.json b/src/main/resources/data/minecraft/tags/item/enchantable/durability.json similarity index 74% rename from src/main/resources/data/guarding/tags/items/enchantable/shield.json rename to src/main/resources/data/minecraft/tags/item/enchantable/durability.json index 1d59734..d0b479b 100644 --- a/src/main/resources/data/guarding/tags/items/enchantable/shield.json +++ b/src/main/resources/data/minecraft/tags/item/enchantable/durability.json @@ -1,7 +1,6 @@ { "replace": false, "values": [ - "minecraft:shield", "guarding:netherite_shield" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/items/trimmable_armor.json b/src/main/resources/data/minecraft/tags/item/trimmable_armor.json similarity index 100% rename from src/main/resources/data/minecraft/tags/items/trimmable_armor.json rename to src/main/resources/data/minecraft/tags/item/trimmable_armor.json diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index dda8792..3cf5f77 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -30,7 +30,7 @@ "depends": { "fabricloader": ">=0.15.10", "fabric-api": "*", - "minecraft": "~1.20.5", + "minecraft": "1.21", "java": ">=21" }, "suggests": {}