diff --git a/common/src/main/java/yesman/epicfight/EpicFight.java b/common/src/main/java/yesman/epicfight/EpicFight.java index 2c1a6bad2..c521630c7 100644 --- a/common/src/main/java/yesman/epicfight/EpicFight.java +++ b/common/src/main/java/yesman/epicfight/EpicFight.java @@ -7,7 +7,24 @@ import yesman.epicfight.platform.ModPlatform; import yesman.epicfight.platform.ModPlatformProvider; +/// 21.16.x +/// Introduced ExCap, with fallbacks to legacy methods +/// ExCap changes: +/// Introduces the ExCapData which houses all providers and movesets, essentially a little data packet. +/// Removed weapon default registration and now Epic Fight hooks into their own event to handle registering weapons +/// Builders are now static and are copied to form a new weapon, Innate skills are improved to use a BiFunction to avoid hardcoding innates. +/// RangedWeaponCapability now extends WeaponCapability and have full access to ExCap's things. +/// Added a new hook that registers ExCapData into a weapon which will then be applied. +/// Enhanced the tier system to allow bases and scaling multipliers. +/// +/// Programmer's Note: +/// This was the greatest undertaking I could've done under the hood wth Epic Fight, if you thought Holdable Skills were cool, +/// ExCap was one of my first projects and was the first one of how I made Battle Arts. Completing this for ExCap would mean that ExCap would no longer be available on 1.21.1 +/// +/// Cheers to you, and everyone here. +/// /// Common functionalities shared between the platform entrypoints. +/// @author Forixaim, Ellet public final class EpicFight { private EpicFight() { } diff --git a/common/src/main/resources/assets/epicfight/models/item/uchigatana_sheath.json b/common/src/main/resources/assets/epicfight/models/item/uchigatana_sheath.json index 69b187fb0..577bab2ff 100644 --- a/common/src/main/resources/assets/epicfight/models/item/uchigatana_sheath.json +++ b/common/src/main/resources/assets/epicfight/models/item/uchigatana_sheath.json @@ -11,9 +11,9 @@ "scale": [1.8, 1.8, 1.3] }, "thirdperson_lefthand": { - "rotation": [0, 90, -55], - "translation": [0, 13.25, -1.75], - "scale": [1.8, 1.8, 0.85] + "rotation": [0, 90, 60], + "translation": [-0.45, -9.7, -2.7], + "scale": [1.8, 1.8, 1.3] }, "firstperson_righthand": { "rotation": [0, -90, 25], diff --git a/neoforge/src/main/java/yesman/epicfight/api/event/EpicFightEventHooks.java b/neoforge/src/main/java/yesman/epicfight/api/event/EpicFightEventHooks.java index 727550b23..fadb59be9 100644 --- a/neoforge/src/main/java/yesman/epicfight/api/event/EpicFightEventHooks.java +++ b/neoforge/src/main/java/yesman/epicfight/api/event/EpicFightEventHooks.java @@ -3,10 +3,8 @@ import yesman.epicfight.api.event.types.animation.*; import yesman.epicfight.api.event.types.entity.*; import yesman.epicfight.api.event.types.player.*; -import yesman.epicfight.api.event.types.registry.EntityPatchRegistryEvent; -import yesman.epicfight.api.event.types.registry.RegisterMobSkillBookLootTableEvent; -import yesman.epicfight.api.event.types.registry.SkillBuilderModificationEvent; -import yesman.epicfight.api.event.types.registry.WeaponCapabilityPresetRegistryEvent; +import yesman.epicfight.api.event.types.registry.*; +import yesman.epicfight.api.ex_cap.modules.core.events.*; import yesman.epicfight.api.utils.side.LogicalSide; import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; @@ -70,6 +68,11 @@ public static final class Registry { public static final EventHook MODIFY_SKILL_BUILDER = EventHook.createEventHook(); public static final EventHook SKILLBOOK_LOOT_TABLE = EventHook.createEventHook(); public static final EventHook WEAPON_CAPABILITY_PRESET = EventHook.createEventHook(); + public static final EventHook EX_CAP_DATA_POPULATION = EventHook.createEventHook(); + public static final EventHook EX_CAP_BUILDER_CREATION = EventHook.createEventHook(); + public static final EventHook EX_CAP_DATA_CREATION = EventHook.createEventHook(); + public static final EventHook EX_CAP_MOVESET_REGISTRY = EventHook.createEventHook(); + public static final EventHook EX_CAP_CONDITIONAL_REGISTRATION = EventHook.createEventHook(); private Registry() {} } diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/Builders.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/Builders.java new file mode 100644 index 000000000..122fdc0a3 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/Builders.java @@ -0,0 +1,106 @@ +package yesman.epicfight.api.ex_cap.modules.assets; + +import yesman.epicfight.api.ex_cap.modules.core.data.BuilderEntry; +import net.minecraft.sounds.SoundEvents; +import yesman.epicfight.EpicFight; +import yesman.epicfight.gameasset.ColliderPreset; +import yesman.epicfight.registry.entries.EpicFightSounds; +import yesman.epicfight.world.capabilities.item.*; + +public class Builders +{ + + public static final BuilderEntry AXE = new BuilderEntry(EpicFight.identifier("axe"), WeaponCapability.builder() + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .collider(ColliderPreset.TOOLS) + .setTierValues(0, 10d, 0.7, 0.3)); + + public static final BuilderEntry SWORD = new BuilderEntry(EpicFight.identifier("sword"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.SWORD) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .collider(ColliderPreset.SWORD) + .setTierValues(0, 0, 0.0, 0.0)); + + public static final BuilderEntry HOE = new BuilderEntry(EpicFight.identifier("hoe"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.HOE) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .collider(ColliderPreset.TOOLS) + .setTierValues(0, 0d, -0.4, 0.1)); + + public static final BuilderEntry PICKAXE = new BuilderEntry(EpicFight.identifier("pickaxe"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.PICKAXE) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .collider(ColliderPreset.TOOLS) + .setTierValues(0, 6d, 0.4, 0.1)); + + public static final BuilderEntry SHOVEL = new BuilderEntry(EpicFight.identifier("shovel"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.SHOVEL) + .collider(ColliderPreset.TOOLS) + .setTierValues(0, 0d, 0.8, 0.4)); + + public static final BuilderEntry SPEAR = new BuilderEntry(EpicFight.identifier("spear"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.SPEAR) + .swingSound(EpicFightSounds.WHOOSH_ROD.get()) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .collider(ColliderPreset.SPEAR) + .canBePlacedOffhand(false) + .reach(1.0F) + .setTierValues(0, 0d, 0.0, 0.0)); + + public static final BuilderEntry GREATSWORD = new BuilderEntry(EpicFight.identifier("greatsword"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.GREATSWORD) + .collider(ColliderPreset.GREATSWORD) + .swingSound(EpicFightSounds.WHOOSH_BIG.get()) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .canBePlacedOffhand(false) + .reach(1.0F) + .setTierValues(0, 0d, 0.0, 0.0)); + + public static final BuilderEntry UCHIGATANA = new BuilderEntry(EpicFight.identifier("uchigatana"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.UCHIGATANA) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .collider(ColliderPreset.UCHIGATANA) + .canBePlacedOffhand(true) + .setTierValues(0, 0d, 0.0, 0.0)); + + public static final BuilderEntry TACHI = new BuilderEntry(EpicFight.identifier("tachi"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.TACHI) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .collider(ColliderPreset.TACHI) + .canBePlacedOffhand(true) + .setTierValues(0, 0d, 0.0, 0.0)); + + public static final BuilderEntry DAGGER = new BuilderEntry(EpicFight.identifier("dagger"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.DAGGER) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .swingSound(EpicFightSounds.WHOOSH_SMALL.get()) + .collider(ColliderPreset.DAGGER) + .setTierValues(0, 0d, 0.0, 0.0)); + + public static final BuilderEntry LONGSWORD = new BuilderEntry(EpicFight.identifier("longsword"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.LONGSWORD) + .collider(ColliderPreset.LONGSWORD) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .canBePlacedOffhand(true) + .setTierValues(0, 0d, 0.0, 0.0)); + + public static final BuilderEntry FIST = new BuilderEntry(EpicFight.identifier("fist"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.FIST) + .offHandAlone(true) + .setTierValues(0, 0d, 0.0, 0.0)); + + public static final BuilderEntry BOW = new BuilderEntry(EpicFight.identifier("bow"), WeaponCapability.builder() + .zoomInType(CapabilityItem.ZoomInType.USE_TICK)); + + public static final BuilderEntry CROSSBOW = new BuilderEntry(EpicFight.identifier("crossbow"), WeaponCapability.builder() + .zoomInType(CapabilityItem.ZoomInType.AIMING)); + + public static final BuilderEntry TRIDENT = new BuilderEntry(EpicFight.identifier("trident"), WeaponCapability.builder() + .zoomInType(CapabilityItem.ZoomInType.USE_TICK) + .hitSound(EpicFightSounds.BLADE_HIT.get()) + .collider(ColliderPreset.SPEAR) + .category(CapabilityItem.WeaponCategories.TRIDENT)); + + public static final BuilderEntry SHIELD = new BuilderEntry(EpicFight.identifier("shield"), WeaponCapability.builder() + .category(CapabilityItem.WeaponCategories.SHIELD)); +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/ExCapDataSets.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/ExCapDataSets.java new file mode 100644 index 000000000..2c10622c8 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/ExCapDataSets.java @@ -0,0 +1,99 @@ +package yesman.epicfight.api.ex_cap.modules.assets; + +import yesman.epicfight.api.ex_cap.modules.core.data.ExCapData; +import yesman.epicfight.api.ex_cap.modules.core.data.ExCapDataEntry; +import yesman.epicfight.EpicFight; +import yesman.epicfight.world.capabilities.item.CapabilityItem; + +public class ExCapDataSets +{ + public static final ExCapDataEntry SWORD = new ExCapDataEntry(EpicFight.identifier("sword"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id(), MainConditionals.DUAL_SWORDS.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.sword1HMS.id()) + .addMoveset(CapabilityItem.Styles.TWO_HAND, Movesets.sword2HMS.id()) + ); + + public static final ExCapDataEntry AXE = new ExCapDataEntry(EpicFight.identifier("axe"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.axeOneHandMS.id()) + ); + + public static final ExCapDataEntry PICKAXE = new ExCapDataEntry(EpicFight.identifier("pickaxe"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.axeOneHandMS.id()) + ); + + public static final ExCapDataEntry SHOVEL = new ExCapDataEntry(EpicFight.identifier("shovel"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.axeOneHandMS.id()) + ); + + public static final ExCapDataEntry DAGGER = new ExCapDataEntry(EpicFight.identifier("dagger"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id(), MainConditionals.DUAL_DAGGERS.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.dagger1HMS.id()) + .addMoveset(CapabilityItem.Styles.TWO_HAND, Movesets.dagger2HMS.id()) + .addMoveset(CapabilityItem.Styles.MOUNT, Movesets.mountedSwordMS.id()) + ); + + public static final ExCapDataEntry SPEAR = new ExCapDataEntry(EpicFight.identifier("spear"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_2H_WIELD_STYLE.id(), MainConditionals.SHIELD_OFFHAND.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.spear1HMS.id()) + .addMoveset(CapabilityItem.Styles.TWO_HAND, Movesets.spear2HMS.id()) + .addMoveset(CapabilityItem.Styles.MOUNT, Movesets.mountedSpearMS.id()) + ); + + public static final ExCapDataEntry GREATSWORD = new ExCapDataEntry(EpicFight.identifier("greatsword"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_2H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.TWO_HAND, Movesets.greatsword2HMS.id()) + ); + + public static final ExCapDataEntry LONGSWORD = new ExCapDataEntry(EpicFight.identifier("longsword"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_2H_WIELD_STYLE.id(), MainConditionals.SHIELD_OFFHAND.id(), MainConditionals.LIECHTENAUER_CONDITION.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.longsword1HMS.id()) + .addMoveset(CapabilityItem.Styles.TWO_HAND, Movesets.longsword2HMS.id()) + .addMoveset(CapabilityItem.Styles.OCHS, Movesets.liechtenauerMS.id()) + ); + + public static final ExCapDataEntry TACHI = new ExCapDataEntry(EpicFight.identifier("tachi"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_2H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.TWO_HAND, Movesets.tachi2HMS.id()) + .addMoveset(CapabilityItem.Styles.MOUNT, Movesets.mountedSwordMS.id()) + ); + + public static final ExCapDataEntry UCHIGATANA = new ExCapDataEntry(EpicFight.identifier("uchigatana"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_2H_WIELD_STYLE.id(), MainConditionals.UCHIGATANA_SHEATHED.id()) + .addMoveset(CapabilityItem.Styles.TWO_HAND, Movesets.uchigatanaBase.id()) + .addMoveset(CapabilityItem.Styles.SHEATH, Movesets.uchigatanaSheathed.id()) + .addMoveset(CapabilityItem.Styles.MOUNT, Movesets.mountedSwordMS.id()) + ); + + public static final ExCapDataEntry HOE = new ExCapDataEntry(EpicFight.identifier("hoe"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.sword1HMS.id()) + ); + + public static final ExCapDataEntry BOW = new ExCapDataEntry(EpicFight.identifier("bow"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.bow.id()) + ); + + public static final ExCapDataEntry CROSSBOW = new ExCapDataEntry(EpicFight.identifier("crossbow"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_2H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.TWO_HAND, Movesets.crossBow.id()) + ); + + public static final ExCapDataEntry FIST = new ExCapDataEntry(EpicFight.identifier("fist"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.glove.id()) + ); + + public static final ExCapDataEntry SHIELD = new ExCapDataEntry(EpicFight.identifier("shield"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.shield.id()) + ); + + public static final ExCapDataEntry TRIDENT = new ExCapDataEntry(EpicFight.identifier("trident"), ExCapData.builder() + .addConditional(MainConditionals.DEFAULT_1H_WIELD_STYLE.id()) + .addMoveset(CapabilityItem.Styles.ONE_HAND, Movesets.tridentMS.id()) + ); +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/ExampleModifiers.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/ExampleModifiers.java new file mode 100644 index 000000000..a2bc9d7e2 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/ExampleModifiers.java @@ -0,0 +1,29 @@ +package yesman.epicfight.api.ex_cap.modules.assets; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import yesman.epicfight.api.utils.math.MathUtils; +import yesman.epicfight.api.utils.math.OpenMatrix4f; +import yesman.epicfight.client.renderer.patched.item.RenderItemBase; +import yesman.epicfight.registry.entries.EpicFightItems; +import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; + +public class ExampleModifiers +{ + public static boolean uchigatanaRender(RenderItemBase baseRenderer, ItemStack stack, LivingEntityPatch livingEntityPatch, InteractionHand hand, OpenMatrix4f[] poses, MultiBufferSource source, PoseStack poseStack, int packedLight, float partialTicks, ItemRenderer renderer) + { + OpenMatrix4f modelMatrix = baseRenderer.getCorrectionMatrix(livingEntityPatch, InteractionHand.OFF_HAND, poses); + poseStack.pushPose(); + MathUtils.mulStack(poseStack, modelMatrix); + renderer.renderStatic(new ItemStack(EpicFightItems.UCHIGATANA_SHEATH), ItemDisplayContext.THIRD_PERSON_RIGHT_HAND, packedLight, OverlayTexture.NO_OVERLAY, poseStack, source, null, 0); + poseStack.popPose(); + //Let the render process complete, true if the render needs to be completely overridden. + return false; + } + +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/MainConditionals.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/MainConditionals.java new file mode 100644 index 000000000..102088fa9 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/MainConditionals.java @@ -0,0 +1,97 @@ +package yesman.epicfight.api.ex_cap.modules.assets; + +import yesman.epicfight.api.ex_cap.modules.core.data.ConditionalEntry; +import yesman.epicfight.api.ex_cap.modules.core.provider.ProviderConditional; +import yesman.epicfight.api.ex_cap.modules.core.provider.ProviderConditionalType; +import net.minecraft.world.InteractionHand; +import yesman.epicfight.EpicFight; +import yesman.epicfight.registry.entries.EpicFightSkillDataKeys; +import yesman.epicfight.registry.entries.EpicFightSkills; +import yesman.epicfight.skill.SkillSlots; +import yesman.epicfight.world.capabilities.item.CapabilityItem; + +public class MainConditionals +{ + public static final ConditionalEntry DEFAULT_1H_WIELD_STYLE = + new ConditionalEntry( + EpicFight.identifier("default_1h_wield_style"), + ProviderConditional.builder() + .setType(ProviderConditionalType.DEFAULT) + .setWieldStyle(CapabilityItem.Styles.ONE_HAND) + .isVisibleOffHand(true) + ); + + public static final ConditionalEntry DEFAULT_2H_WIELD_STYLE = + new ConditionalEntry( + EpicFight.identifier("default_2h_wield_style"), + ProviderConditional.builder() + .setType(ProviderConditionalType.DEFAULT) + .isVisibleOffHand(false) + .setWieldStyle(CapabilityItem.Styles.TWO_HAND) + ); + + public static final ConditionalEntry DEFAULT_RANGED = + new ConditionalEntry( + EpicFight.identifier("default_ranged"), + ProviderConditional.builder() + .setType(ProviderConditionalType.DEFAULT) + .isVisibleOffHand(false) + .setWieldStyle(CapabilityItem.Styles.RANGED) + ); + + public static final ConditionalEntry SHIELD_OFFHAND = + new ConditionalEntry( + EpicFight.identifier("shield_offhand"), + ProviderConditional.builder() + .setType(ProviderConditionalType.WEAPON_CATEGORY) + .setHand(InteractionHand.OFF_HAND) + .setCategory(CapabilityItem.WeaponCategories.SHIELD) + .setWieldStyle(CapabilityItem.Styles.ONE_HAND) + .isVisibleOffHand(true) + ); + + public static final ConditionalEntry LIECHTENAUER_CONDITION = + new ConditionalEntry( + EpicFight.identifier("liechtenauer_condition"), + ProviderConditional.builder() + .setType(ProviderConditionalType.SKILL_ACTIVATION) + .setSlot(SkillSlots.WEAPON_INNATE) + .setSkillToCheck(EpicFightSkills.LIECHTENAUER.value()) + .isVisibleOffHand(false) + .setWieldStyle(CapabilityItem.Styles.OCHS) + ); + + public static final ConditionalEntry UCHIGATANA_SHEATHED = + new ConditionalEntry( + EpicFight.identifier("uchigatana_sheathed"), + ProviderConditional.builder() + .setType(ProviderConditionalType.DATA_KEY) + .isVisibleOffHand(false) + .setSlot(SkillSlots.WEAPON_PASSIVE) + .setSkillToCheck(EpicFightSkills.BATTOJUTSU_PASSIVE.value()) + .setWieldStyle(CapabilityItem.Styles.SHEATH) + .setKey(EpicFightSkillDataKeys.SHEATH) + ); + + public static final ConditionalEntry DUAL_DAGGERS = + new ConditionalEntry( + EpicFight.identifier("dual_daggers"), + ProviderConditional.builder() + .setType(ProviderConditionalType.WEAPON_CATEGORY) + .setCategory(CapabilityItem.WeaponCategories.DAGGER) + .isVisibleOffHand(true) + .setHand(InteractionHand.OFF_HAND) + .setWieldStyle(CapabilityItem.Styles.TWO_HAND) + ); + + public static final ConditionalEntry DUAL_SWORDS = + new ConditionalEntry( + EpicFight.identifier("dual_swords"), + ProviderConditional.builder() + .setType(ProviderConditionalType.WEAPON_CATEGORY) + .setCategory(CapabilityItem.WeaponCategories.SWORD) + .isVisibleOffHand(true) + .setHand(InteractionHand.OFF_HAND) + .setWieldStyle(CapabilityItem.Styles.TWO_HAND) + ); +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/Movesets.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/Movesets.java new file mode 100644 index 000000000..9262eeb48 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/assets/Movesets.java @@ -0,0 +1,344 @@ +package yesman.epicfight.api.ex_cap.modules.assets; + +import yesman.epicfight.api.ex_cap.modules.core.data.MoveSetEntry; +import net.minecraft.world.item.CrossbowItem; +import net.minecraft.world.item.ProjectileWeaponItem; +import net.minecraft.world.item.UseAnim; +import net.minecraft.world.item.enchantment.Enchantments; +import yesman.epicfight.EpicFight; +import yesman.epicfight.api.animation.LivingMotions; +import yesman.epicfight.gameasset.Animations; +import yesman.epicfight.registry.entries.EpicFightSkills; +import yesman.epicfight.api.ex_cap.modules.core.data.MoveSet; + +@SuppressWarnings("unchecked") +public class Movesets +{ + public static MoveSetEntry commonShield = new MoveSetEntry( + EpicFight.identifier("common_shield"), + MoveSet.builder() + .addLivingMotionModifier(LivingMotions.BLOCK_SHIELD, Animations.BIPED_BLOCK) + ); + + public static MoveSetEntry mountedSwordMS = new MoveSetEntry( + EpicFight.identifier("mounted_sword"), + MoveSet.builder() + .addComboAttacks(Animations.SWORD_MOUNT_ATTACK) + ); + + public static MoveSetEntry greatsword2HMS = new MoveSetEntry( + EpicFight.identifier("greatsword_2h"), + MoveSet.builder() + .addLivingMotionsRecursive(Animations.BIPED_HOLD_GREATSWORD, + LivingMotions.IDLE, LivingMotions.JUMP, LivingMotions.KNEEL, LivingMotions.SNEAK, + LivingMotions.SWIM, LivingMotions.FLY, LivingMotions.CREATIVE_FLY, LivingMotions.CREATIVE_IDLE) + .addLivingMotionsRecursive(Animations.BIPED_WALK_GREATSWORD, + LivingMotions.WALK, + LivingMotions.CHASE) + .addLivingMotionModifier(LivingMotions.RUN, Animations.BIPED_RUN_GREATSWORD) + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.GREATSWORD_GUARD) + .addComboAttacks( + Animations.GREATSWORD_AUTO1, + Animations.GREATSWORD_AUTO2, + Animations.GREATSWORD_DASH, + Animations.GREATSWORD_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.STEEL_WHIRLWIND.get()) + ); + + public static MoveSetEntry axeOneHandMS = new MoveSetEntry( + EpicFight.identifier("axe_1h"), + MoveSet.builder() + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.SWORD_GUARD) + .addComboAttacks( + Animations.AXE_AUTO1, + Animations.AXE_AUTO2, + Animations.AXE_DASH, + Animations.AXE_AIRSLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.THE_GUILLOTINE.get()) + ); + + public static MoveSetEntry mountedSpearMS = new MoveSetEntry( + EpicFight.identifier("mounted_spear"), + MoveSet.builder() + .addComboAttacks( + Animations.SPEAR_MOUNT_ATTACK + ) + ); + + public static MoveSetEntry longsword2HMS = new MoveSetEntry( + EpicFight.identifier("longsword_2h"), + MoveSet.builder() + .addLivingMotionsRecursive(Animations.BIPED_HOLD_LONGSWORD, + LivingMotions.IDLE, LivingMotions.SNEAK, LivingMotions.KNEEL, + LivingMotions.JUMP, LivingMotions.SWIM) + .addLivingMotionsRecursive(Animations.BIPED_WALK_LONGSWORD, + LivingMotions.WALK, LivingMotions.CHASE) + .addLivingMotionModifier(LivingMotions.RUN, Animations.BIPED_RUN_LONGSWORD) + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.LONGSWORD_GUARD) + .addComboAttacks( + Animations.LONGSWORD_AUTO1, + Animations.LONGSWORD_AUTO2, + Animations.LONGSWORD_AUTO3, + Animations.LONGSWORD_DASH, + Animations.LONGSWORD_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.LIECHTENAUER.get()) + .shouldRenderSheath(livingEntityPatch -> true) + ); + + public static MoveSetEntry longsword1HMS = new MoveSetEntry( + EpicFight.identifier("longsword_1h"), + MoveSet.builder() + .parent(longsword2HMS.id()) + .addLivingMotionModifier(LivingMotions.BLOCK_SHIELD, Animations.BIPED_BLOCK) + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.BIPED_BLOCK) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.SHARP_STAB.get()) + ); + + public static MoveSetEntry liechtenauerMS = new MoveSetEntry( + EpicFight.identifier("liechtenauer"), + MoveSet.builder() + .addLivingMotionsRecursive(Animations.BIPED_HOLD_LIECHTENAUER, + LivingMotions.IDLE, LivingMotions.SNEAK, LivingMotions.KNEEL, + LivingMotions.JUMP, LivingMotions.SWIM) + .addLivingMotionsRecursive(Animations.BIPED_WALK_LIECHTENAUER, + LivingMotions.WALK, LivingMotions.CHASE) + .addLivingMotionModifier(LivingMotions.RUN, Animations.BIPED_HOLD_LIECHTENAUER) + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.LONGSWORD_GUARD) + .addComboAttacks( + Animations.LONGSWORD_LIECHTENAUER_AUTO1, + Animations.LONGSWORD_LIECHTENAUER_AUTO2, + Animations.LONGSWORD_LIECHTENAUER_AUTO3, + Animations.LONGSWORD_DASH, + Animations.LONGSWORD_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.LIECHTENAUER.get()) + ); + + public static MoveSetEntry dagger1HMS = new MoveSetEntry( + EpicFight.identifier("dagger_1h"), + MoveSet.builder() + .addComboAttacks( + Animations.DAGGER_AUTO1, + Animations.DAGGER_AUTO2, + Animations.DAGGER_AUTO3, + Animations.DAGGER_DASH, + Animations.DAGGER_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.EVISCERATE.get()) + ); + + public static MoveSetEntry dagger2HMS = new MoveSetEntry( + EpicFight.identifier("dagger_2h"), + MoveSet.builder() + .addComboAttacks( + Animations.DAGGER_DUAL_AUTO1, + Animations.DAGGER_DUAL_AUTO2, + Animations.DAGGER_DUAL_AUTO3, + Animations.DAGGER_DUAL_AUTO4, + Animations.DAGGER_DUAL_DASH, + Animations.DAGGER_DUAL_AIR_SLASH + ) + .addLivingMotionsRecursive(Animations.BIPED_HOLD_DUAL_WEAPON, + LivingMotions.IDLE, LivingMotions.KNEEL, LivingMotions.WALK, LivingMotions.CHASE, + LivingMotions.SNEAK, LivingMotions.SWIM, LivingMotions.FLOAT, LivingMotions.FALL) + .addLivingMotionModifier(LivingMotions.RUN, Animations.BIPED_RUN_DUAL) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.BLADE_RUSH.get()) + ); + + public static MoveSetEntry spear2HMS = new MoveSetEntry( + EpicFight.identifier("spear_2h"), + MoveSet.builder() + .addLivingMotionsRecursive(Animations.BIPED_HOLD_SPEAR, + LivingMotions.IDLE, LivingMotions.SWIM) + .addLivingMotionsRecursive(Animations.BIPED_WALK_SPEAR, + LivingMotions.WALK, LivingMotions.CHASE) + .addLivingMotionModifier(LivingMotions.RUN, Animations.BIPED_RUN_SPEAR) + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.SPEAR_GUARD) + .addComboAttacks( + Animations.SPEAR_TWOHAND_AUTO1, Animations.SPEAR_TWOHAND_AUTO2, + Animations.SPEAR_DASH, + Animations.SPEAR_TWOHAND_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.GRASPING_SPIRE.get()) + ); + + public static MoveSetEntry spear1HMS = new MoveSetEntry( + EpicFight.identifier("spear_1h"), + MoveSet.builder() + .parent(EpicFight.identifier("spear_2h")) + .addComboAttacks( + Animations.SPEAR_ONEHAND_AUTO, + Animations.SPEAR_DASH, + Animations.SPEAR_ONEHAND_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.HEARTPIERCER.get()) + ); + + public static MoveSetEntry sword1HMS = new MoveSetEntry( + EpicFight.identifier("sword_1h"), + MoveSet.builder() + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.SWORD_GUARD) + .addComboAttacks( + Animations.SWORD_AUTO1, + Animations.SWORD_AUTO2, Animations.SWORD_AUTO3, + Animations.SWORD_DASH, Animations.SWORD_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.SWEEPING_EDGE.get()) + ); + + public static MoveSetEntry sword2HMS = new MoveSetEntry( + EpicFight.identifier("sword_dual"), + MoveSet.builder() + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.SWORD_DUAL_GUARD) + .parent(dagger2HMS.id()) + .addComboAttacks( + Animations.SWORD_DUAL_AUTO1, + Animations.SWORD_DUAL_AUTO2, Animations.SWORD_DUAL_AUTO3, + Animations.SWORD_DUAL_DASH, Animations.SWORD_DUAL_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.DANCING_EDGE.get()) + ); + + public static MoveSetEntry shield = new MoveSetEntry( + EpicFight.identifier("shield"), + MoveSet.builder() + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.BIPED_BLOCK) + .addLivingMotionModifier(LivingMotions.BLOCK_SHIELD, Animations.BIPED_BLOCK) + ); + + public static MoveSetEntry tachi2HMS = new MoveSetEntry( + EpicFight.identifier("tachi_2h"), + MoveSet.builder() + .addLivingMotionsRecursive(Animations.BIPED_HOLD_TACHI, + LivingMotions.IDLE, + LivingMotions.KNEEL, LivingMotions.WALK, LivingMotions.CHASE, LivingMotions.RUN, + LivingMotions.SNEAK, LivingMotions.SWIM, LivingMotions.FLOAT, LivingMotions.FALL) + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.LONGSWORD_GUARD) + .addComboAttacks( + Animations.TACHI_AUTO1, + Animations.TACHI_AUTO2, + Animations.TACHI_AUTO3, + Animations.TACHI_DASH, + Animations.LONGSWORD_AIR_SLASH + ) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.RUSHING_TEMPO.get()) + ); + + public static MoveSetEntry uchigatanaBase = new MoveSetEntry( + EpicFight.identifier("uchigatana_base"), + MoveSet.builder() + .addComboAttacks( + Animations.UCHIGATANA_AUTO1, Animations.UCHIGATANA_AUTO2, + Animations.UCHIGATANA_AUTO3, Animations.UCHIGATANA_DASH, + Animations.UCHIGATANA_AIR_SLASH) + .addLivingMotionsRecursive(Animations.BIPED_HOLD_UCHIGATANA, + LivingMotions.IDLE, LivingMotions.KNEEL, + LivingMotions.SWIM, LivingMotions.FALL, + LivingMotions.FALL) + .addLivingMotionsRecursive(Animations.BIPED_WALK_UCHIGATANA, + LivingMotions.CHASE, LivingMotions.WALK, LivingMotions.SNEAK) + .addLivingMotionModifier(LivingMotions.RUN, Animations.BIPED_RUN_UCHIGATANA) + .addLivingMotionModifier(LivingMotions.BLOCK, Animations.UCHIGATANA_GUARD) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.BATTOJUTSU.get()) + .setPassiveSkill(EpicFightSkills.BATTOJUTSU_PASSIVE.get()) + .shouldRenderSheath(livingEntityPatch -> true) + ); + + public static MoveSetEntry uchigatanaSheathed = new MoveSetEntry( + EpicFight.identifier("uchigatana_sheathed"), + MoveSet.builder() + .parent(EpicFight.identifier("uchigatana_base")) + .addComboAttacks( + Animations.UCHIGATANA_SHEATHING_AUTO, + Animations.UCHIGATANA_SHEATHING_DASH, + Animations.UCHIGATANA_SHEATH_AIR_SLASH) + .addLivingMotionsRecursive(Animations.BIPED_HOLD_UCHIGATANA_SHEATHING, + LivingMotions.IDLE, LivingMotions.KNEEL, + LivingMotions.SWIM, LivingMotions.FALL, + LivingMotions.FALL, LivingMotions.SNEAK, LivingMotions.CHASE) + .addLivingMotionModifier(LivingMotions.WALK, Animations.BIPED_WALK_UCHIGATANA_SHEATHING) + .addLivingMotionModifier(LivingMotions.RUN, Animations.BIPED_RUN_UCHIGATANA_SHEATHING) + .shouldRenderSheath(livingEntityPatch -> true) + ); + + public static MoveSetEntry glove = new MoveSetEntry( + EpicFight.identifier("glove"), + MoveSet.builder() + .addLivingMotionModifier(LivingMotions.IDLE, Animations.BIPED_IDLE) + .addLivingMotionModifier(LivingMotions.WALK, Animations.BIPED_WALK) + .addComboAttacks( + Animations.FIST_AUTO1, + Animations.FIST_AUTO2, + Animations.FIST_AUTO3, + Animations.FIST_DASH, + Animations.FIST_AIR_SLASH) + .addInnateSkill((itemStack, playerPatch) -> EpicFightSkills.RELENTLESS_COMBO.get()) + ); + + public static MoveSetEntry bow = new MoveSetEntry( + EpicFight.identifier("bow"), + MoveSet.builder() + .addLivingMotionModifier(LivingMotions.AIM, Animations.BIPED_BOW_AIM) + .addLivingMotionModifier(LivingMotions.IDLE, Animations.BIPED_IDLE) + .addLivingMotionModifier(LivingMotions.WALK, Animations.BIPED_WALK) + .addLivingMotionModifier(LivingMotions.SHOT, Animations.BIPED_BOW_SHOT) + .setMotionPredicate((entityPatch, interactionHand) -> + entityPatch.getOriginal().isUsingItem() && + entityPatch.getOriginal().getUseItem().getUseAnimation() == UseAnim.BOW + ? LivingMotions.AIM : null) + .addComboAttacks( + Animations.FIST_AUTO1, + Animations.FIST_AUTO2, + Animations.FIST_AUTO3, + Animations.FIST_DASH, + Animations.FIST_AIR_SLASH) + ); + + public static MoveSetEntry crossBow = new MoveSetEntry( + EpicFight.identifier("crossbow"), + MoveSet.builder() + .addLivingMotionsRecursive(Animations.BIPED_HOLD_CROSSBOW, + LivingMotions.IDLE, LivingMotions.KNEEL, LivingMotions.WALK, LivingMotions.RUN, + LivingMotions.SWIM, LivingMotions.FALL, LivingMotions.FLOAT, LivingMotions.SNEAK) + .setMotionPredicate((entityPatch, interactionHand) -> + entityPatch.getEntityState().canUseItem() && + entityPatch.getOriginal().getMainHandItem().getItem() instanceof ProjectileWeaponItem && + CrossbowItem.isCharged(entityPatch.getOriginal().getMainHandItem()) + ? LivingMotions.AIM : null) + .addLivingMotionModifier(LivingMotions.AIM, Animations.BIPED_CROSSBOW_AIM) + .addLivingMotionModifier(LivingMotions.RELOAD, Animations.BIPED_CROSSBOW_RELOAD) + .addLivingMotionModifier(LivingMotions.SHOT, Animations.BIPED_CROSSBOW_SHOT) + ); + + public static MoveSetEntry tridentMS = new MoveSetEntry( + EpicFight.identifier("trident"), + MoveSet.builder() + .addComboAttacks( + Animations.TRIDENT_AUTO1, + Animations.TRIDENT_AUTO2, + Animations.TRIDENT_AUTO3, + Animations.SPEAR_DASH, + Animations.SPEAR_ONEHAND_AIR_SLASH + ) + .setMotionPredicate((entityPatch, interactionHand) -> + entityPatch.getOriginal().isUsingItem() && entityPatch.getOriginal().getUseItem().getUseAnimation() == UseAnim.SPEAR ? LivingMotions.AIM : null) + .addLivingMotionModifier(LivingMotions.AIM, Animations.BIPED_JAVELIN_AIM) + .addLivingMotionModifier(LivingMotions.SHOT, Animations.BIPED_JAVELIN_THROW) + .addMountAttacks(Animations.SPEAR_MOUNT_ATTACK) + .addInnateSkill((itemStack, playerPatch) -> + { + if (itemStack.getEnchantmentLevel(playerPatch.getLevel().holderOrThrow(Enchantments.RIPTIDE)) > 0) { + return EpicFightSkills.TSUNAMI.get(); + } else if (itemStack.getEnchantmentLevel(playerPatch.getLevel().holderOrThrow(Enchantments.CHANNELING)) > 0) { + return EpicFightSkills.WRATHFUL_LIGHTING.get(); + } else if (itemStack.getEnchantmentLevel(playerPatch.getLevel().holderOrThrow(Enchantments.LOYALTY)) > 0) { + return EpicFightSkills.EVERLASTING_ALLEGIANCE.get(); + } else { + return EpicFightSkills.GRASPING_SPIRE.get(); + } + }) + ); +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/BuilderEntry.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/BuilderEntry.java new file mode 100644 index 000000000..97cb0b829 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/BuilderEntry.java @@ -0,0 +1,6 @@ +package yesman.epicfight.api.ex_cap.modules.core.data; + +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.world.capabilities.item.WeaponCapability; + +public record BuilderEntry(ResourceLocation id, WeaponCapability.Builder template) { } diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ConditionalEntry.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ConditionalEntry.java new file mode 100644 index 000000000..05cc9d879 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ConditionalEntry.java @@ -0,0 +1,7 @@ +package yesman.epicfight.api.ex_cap.modules.core.data; + +import yesman.epicfight.api.ex_cap.modules.core.provider.ProviderConditional; +import net.minecraft.resources.ResourceLocation; + +/// See {@link MoveSetEntry} same concept +public record ConditionalEntry(ResourceLocation id, ProviderConditional.ProviderConditionalBuilder builder) { } diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ExCapData.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ExCapData.java new file mode 100644 index 000000000..2f8bdea85 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ExCapData.java @@ -0,0 +1,79 @@ +package yesman.epicfight.api.ex_cap.modules.core.data; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gson.JsonElement; +import yesman.epicfight.api.ex_cap.modules.core.managers.ConditionalManager; +import yesman.epicfight.api.ex_cap.modules.core.managers.MovesetManager; +import yesman.epicfight.api.ex_cap.modules.core.provider.ProviderConditional; +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.world.capabilities.item.Style; +import yesman.epicfight.world.capabilities.item.WeaponCapability; + +import java.util.List; +import java.util.Map; + +public record ExCapData(List conditionals, Map sets) { + + public void apply(WeaponCapability.Builder cap) + { + cap.addConditionals(conditionals); + sets.forEach( (style, builder) -> cap.addMoveSet(style, MovesetManager.getBuilder(builder))); + } + + public static Builder builder() + { + return new Builder(); + } + + public static class Builder { + + private final List conditionals = Lists.newArrayList(); + private final Map moveSets = Maps.newHashMap(); + + public static Builder deserialize(JsonElement jsonElement) + { + Builder builder = new Builder(); + JsonElement conditionals = jsonElement.getAsJsonObject().get("conditionals"); + if (conditionals != null && conditionals.isJsonArray()) + { + conditionals.getAsJsonArray().forEach(el -> builder.addConditional(ResourceLocation.parse(el.getAsJsonObject().get("id").getAsString()))); + } + JsonElement moveSets = jsonElement.getAsJsonObject().get("move_sets"); + if (moveSets != null && moveSets.isJsonObject()) + { + moveSets.getAsJsonObject().entrySet().forEach(entry -> + { + Style style = Style.ENUM_MANAGER.get(entry.getKey()); + ResourceLocation moveSet = ResourceLocation.tryParse(entry.getValue().getAsString()); + if (style != null && moveSet != null) + { + builder.addMoveset(style, moveSet); + } + }); + } + return builder; + } + + public Builder addConditional(ResourceLocation... conds) { + for (ResourceLocation cond : conds) { + conditionals.add(ConditionalManager.get(cond).build()); + } + return this; + } + + public Builder addMoveset(Style style, ResourceLocation builder) + { + moveSets.put(style, builder); + return this; + } + public ExCapData build() { + return new ExCapData( + List.copyOf(conditionals), + Map.copyOf(moveSets) + ); + } + } + + +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ExCapDataEntry.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ExCapDataEntry.java new file mode 100644 index 000000000..9cf354502 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/ExCapDataEntry.java @@ -0,0 +1,5 @@ +package yesman.epicfight.api.ex_cap.modules.core.data; + +import net.minecraft.resources.ResourceLocation; + +public record ExCapDataEntry(ResourceLocation id, ExCapData.Builder data) { } diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/MoveSet.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/MoveSet.java new file mode 100644 index 000000000..47f5f86e2 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/MoveSet.java @@ -0,0 +1,417 @@ +package yesman.epicfight.api.ex_cap.modules.core.data; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import yesman.epicfight.api.ex_cap.modules.core.managers.MovesetManager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import yesman.epicfight.api.animation.AnimationManager; +import yesman.epicfight.api.animation.LivingMotion; +import yesman.epicfight.api.animation.types.AttackAnimation; +import yesman.epicfight.api.animation.types.StaticAnimation; +import yesman.epicfight.registry.EpicFightRegistries; +import yesman.epicfight.skill.Skill; +import yesman.epicfight.skill.guard.GuardSkill; +import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; +import yesman.epicfight.world.capabilities.entitypatch.player.PlayerPatch; + +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Predicate; + +public class MoveSet +{ + private final List> comboAttackAnimations; + private final List> mountAttackAnimations; + private final Map> livingMotionModifiers; + private final BiFunction, Skill> weaponInnateSkill; + private final Map>> guardPoses; + private final Map>>> skillSpecificGuardAnimations; + private final Skill weaponPassiveSkill; + private final AnimationManager.AnimationAccessor revelationAnimation; + private final Predicate> sheathRender; + private final BiFunction, InteractionHand, LivingMotion> customMotion; + private final Map>> defaultGuardAnimations; + private final RenderModifier modifier; + + public MoveSet(MoveSetBuilder builder) + { + this.mountAttackAnimations = builder.mountAttackAnimations; + this.sheathRender = builder.sheathRender; + this.comboAttackAnimations = builder.comboAttackAnimations; + this.livingMotionModifiers = builder.livingMotionModifiers; + this.skillSpecificGuardAnimations = builder.skillSpecificGuardAnimations; + this.guardPoses = builder.guardPoses; + this.modifier = builder.modifier; + this.defaultGuardAnimations = builder.defaultGuardAnimations; + this.weaponInnateSkill = builder.weaponInnateSkill; + this.weaponPassiveSkill = builder.weaponPassiveSkill; + this.revelationAnimation = builder.revelationAnimation; + this.customMotion = builder.motion; + } + + public RenderModifier getRenderModifier() { + return modifier; + } + + public BiFunction, InteractionHand, LivingMotion> getCustomMotion() + { + return customMotion; + } + + public Map>> getDefaultGuardAnimations() { + return defaultGuardAnimations; + } + + public AnimationManager.AnimationAccessor getRevelation() + { + return revelationAnimation; + } + + public Predicate> shouldRenderSheath() + { + return sheathRender; + } + + public static MoveSetBuilder builder() + { + return new MoveSetBuilder(); + } + + public Skill getWeaponPassiveSkill() { + return weaponPassiveSkill; + } + + public List> getMountAttackAnimations() + { + return mountAttackAnimations; + } + + public BiFunction, Skill> getWeaponInnateSkill() { + return weaponInnateSkill; + } + + public Map>>> getSkillSpecificGuardAnimations() { + return skillSpecificGuardAnimations; + } + + public List> getComboAttackAnimations() { + return comboAttackAnimations; + } + + public Map>> getGuardPoses() { + return guardPoses; + } + + public Map> getLivingMotionModifiers() { + return livingMotionModifiers; + } + + + + /** + * Allows for + */ + public static class MoveSetBuilder + { + protected ResourceLocation registryIdentifier; + protected final List> comboAttackAnimations; + protected final List> mountAttackAnimations; + protected final Map> livingMotionModifiers; + protected BiFunction, Skill> weaponInnateSkill; + protected final Map>>> skillSpecificGuardAnimations; + private final Map>> guardPoses; + protected final Map>> defaultGuardAnimations; + protected Skill weaponPassiveSkill; + protected Predicate> sheathRender; + protected AnimationManager.AnimationAccessor revelationAnimation; + protected BiFunction, InteractionHand, LivingMotion> motion; + protected ResourceLocation parent; + protected RenderModifier modifier; + + public MoveSetBuilder() + { + mountAttackAnimations = Lists.newArrayList(); + sheathRender = livingEntityPatch -> false; + comboAttackAnimations = Lists.newArrayList(); + livingMotionModifiers = Maps.newHashMap(); + skillSpecificGuardAnimations = Maps.newHashMap(); + defaultGuardAnimations = Maps.newHashMap(); + guardPoses = Maps.newHashMap(); + modifier = null; + motion = (a, b) -> null; + weaponInnateSkill = null; + weaponPassiveSkill = null; + revelationAnimation = null; + } + + public MoveSetBuilder parent(ResourceLocation parent) + { + this.parent = parent; + return this; + } + + public MoveSetBuilder renderModifier(RenderModifier modifier) + { + this.modifier = modifier; + return this; + } + + public MoveSetBuilder identifier(ResourceLocation identifier) + { + this.registryIdentifier = identifier; + return this; + } + + public MoveSetBuilder setMotionPredicate(BiFunction, InteractionHand, LivingMotion> lambda) + { + this.motion = lambda; + return this; + } + + + public MoveSetBuilder revelationAttack(AnimationManager.AnimationAccessor attack) + { + revelationAnimation = attack; + return this; + } + + public MoveSetBuilder shouldRenderSheath(Predicate> sheathRender) + { + this.sheathRender = sheathRender; + return this; + } + + @SafeVarargs + public final MoveSetBuilder guardSpecificHold(Skill skill, AnimationManager.AnimationAccessor... animations) + { + if (skill instanceof GuardSkill) + { + guardPoses.computeIfAbsent(skill, (k) -> Lists.newArrayList(animations)); + } + return this; + } + + public MoveSetBuilder setPassiveSkill(Skill newPassiveSkill) + { + this.weaponPassiveSkill = newPassiveSkill; + return this; + } + + @SafeVarargs + public final MoveSetBuilder addMountAttacks(AnimationManager.AnimationAccessor... attackAnimations) + { + mountAttackAnimations.addAll(Arrays.asList(attackAnimations)); + return this; + } + + @SafeVarargs + public final MoveSetBuilder addComboAttacks(AnimationManager.AnimationAccessor... attackAnimations) + { + comboAttackAnimations.addAll(Arrays.asList(attackAnimations)); + return this; + } + + public MoveSetBuilder addLivingMotionModifier(LivingMotion livingMotion, AnimationManager.AnimationAccessor animation) + { + livingMotionModifiers.put(livingMotion, animation); + return this; + } + + public MoveSetBuilder addInnateSkill(BiFunction, Skill> weaponInnateSkill) + { + this.weaponInnateSkill = weaponInnateSkill; + return this; + } + + public MoveSetBuilder addLivingMotionsRecursive(AnimationManager.AnimationAccessor animation, LivingMotion... motions) + { + for (LivingMotion livingMotion : motions) + { + livingMotionModifiers.put(livingMotion, animation); + } + return this; + } + + @SafeVarargs + public final MoveSetBuilder addGuardAnimations(GuardSkill.BlockType blockType, AnimationManager.AnimationAccessor... animation) + { + defaultGuardAnimations.computeIfAbsent(blockType, (key) -> Lists.newArrayList()).addAll(Arrays.asList(animation)); + return this; + } + + public final MoveSetBuilder addSkillSpecificGuardAnimations(Skill guardSkill, Map>> animations) + { + if (guardSkill instanceof GuardSkill) + { + skillSpecificGuardAnimations.computeIfAbsent(guardSkill, (key) -> Maps.newHashMap()).putAll(animations); + } + return this; + } + + private static @NotNull List> getAnimationAccessors(JsonElement jsonElement) + { + List attacks = jsonElement.getAsJsonArray().asList(); + List> autocomboAnims = Lists.newArrayList(); + + attacks.forEach(attacksElement -> { + autocomboAnims.add(AnimationManager.byKey(attacksElement.getAsString())); + }); + return autocomboAnims; + } + + private static Map> getLivingMotionModifiers(Map map) + { + Map> result = Maps.newHashMap(); + map.forEach((key, jsonElement) -> result.put(LivingMotion.ENUM_MANAGER.get(key), AnimationManager.byKey(jsonElement.getAsString()))); + return result; + } + + @SuppressWarnings("unchecked") + public static MoveSetBuilder deserialize(JsonElement jsonObject) throws JsonParseException + { + MoveSetBuilder result = new MoveSetBuilder(); + try { + if (jsonObject.isJsonObject()) + { + JsonObject json = jsonObject.getAsJsonObject(); + if (json.has("combo_attack")) + { + result.addComboAttacks(getAnimationAccessors(json.get("combo_attack").getAsJsonArray()).toArray(AnimationManager.AnimationAccessor[]::new)); + } + if (json.has("guard_holds")) + { + JsonElement get = json.get("guard_holds"); + if (get.isJsonObject()) + { + get.getAsJsonObject().entrySet().forEach(entry -> { + Skill guard = EpicFightRegistries.SKILL.get(ResourceLocation.parse(entry.getKey())); + List> animations = Lists.newArrayList(); + if (entry.getValue().isJsonArray()) + { + JsonArray array = entry.getValue().getAsJsonArray(); + array.forEach(element -> { + if (element.isJsonPrimitive()) + { + animations.add(AnimationManager.byKey(element.getAsJsonPrimitive().getAsString())); + } + }); + } + if (guard != null) + { + result.guardPoses.put(guard, animations); + } + }); + } + } + if (json.has("mount_attack")) + { + result.addMountAttacks(getAnimationAccessors(json.get("mount_attack").getAsJsonArray()).toArray(AnimationManager.AnimationAccessor[]::new)); + } + if (json.has("innate_skill")) + { + result.addInnateSkill((itemStack, playerPatch) -> EpicFightRegistries.SKILL.get(ResourceLocation.parse(json.get("innate_skill").getAsString()))); + } + if (json.has("living_animations")) + { + getLivingMotionModifiers(json.get("living_animations").getAsJsonObject().asMap()).forEach(result::addLivingMotionModifier); + } + if (json.has("weapon_passive")) + { + result.setPassiveSkill(EpicFightRegistries.SKILL.get(ResourceLocation.parse(json.get("weapon_passive").getAsString()))); + } + if (json.has("guard_motions")) + { + json.get("guard_motions").getAsJsonObject().asMap().forEach((s, jsonElement) -> + { + GuardSkill.BlockType blockType = GuardSkill.BlockType.valueOf(s.toUpperCase(Locale.ROOT)); + result.addGuardAnimations(blockType, getAnimationAccessors(jsonElement.getAsJsonArray()).toArray(AnimationManager.AnimationAccessor[]::new)); + }); + } + if (json.has("revelation_attack")) + { + result.revelationAttack(AnimationManager.byKey(json.get("revelation_attack").getAsString())); + } + if (json.has("sheath_render")) + { + result.shouldRenderSheath(livingEntityPatch -> json.get("sheath_render").getAsBoolean()); + } + } + } catch (RuntimeException e) { + throw new JsonParseException("Failed to parse moveset json: " + e.getMessage()); + } + return result; + } + + + private MoveSetBuilder merge() { + MoveSetBuilder result = new MoveSetBuilder(); + + Deque hierarchy = new ArrayDeque<>(); + MoveSetBuilder current = this; + + while (current != null) { + hierarchy.push(current); + current = MovesetManager.getBuilder(current.parent); + } + + while (!hierarchy.isEmpty()) { + MoveSetBuilder builder = hierarchy.pop(); + + if (!builder.comboAttackAnimations.isEmpty()) { + result.comboAttackAnimations.clear(); + result.comboAttackAnimations.addAll(builder.comboAttackAnimations); + } + + if (!builder.mountAttackAnimations.isEmpty()) { + result.mountAttackAnimations.clear(); + result.mountAttackAnimations.addAll(builder.mountAttackAnimations); + } + + if (!builder.livingMotionModifiers.isEmpty()) { + result.livingMotionModifiers.putAll(builder.livingMotionModifiers); + } + + if (!builder.skillSpecificGuardAnimations.isEmpty()) { + result.skillSpecificGuardAnimations.putAll(builder.skillSpecificGuardAnimations); + } + + if (!builder.defaultGuardAnimations.isEmpty()) { + result.defaultGuardAnimations.putAll(builder.defaultGuardAnimations); + } + + if (!builder.guardPoses.isEmpty()) { + result.guardPoses.putAll(builder.guardPoses); + } + + if (builder.weaponInnateSkill != null) + result.weaponInnateSkill = builder.weaponInnateSkill; + + if (builder.weaponPassiveSkill != null) + result.weaponPassiveSkill = builder.weaponPassiveSkill; + + if (builder.sheathRender != null) + result.sheathRender = builder.sheathRender; + + if (builder.revelationAnimation != null) + result.revelationAnimation = builder.revelationAnimation; + + if (builder.motion != null) + result.motion = builder.motion; + } + + return result; + } + + public MoveSet build() + { + return new MoveSet(merge()); + } + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/MoveSetEntry.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/MoveSetEntry.java new file mode 100644 index 000000000..55420a585 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/MoveSetEntry.java @@ -0,0 +1,7 @@ +package yesman.epicfight.api.ex_cap.modules.core.data; + +import net.minecraft.resources.ResourceLocation; + +/// A record representing an entry in the {@link MoveSet} registry, containing the ID and the builder for the {@link MoveSet}. For modders to use when registering their {@link MoveSet}. +/// Datapack authors do not need to use this, as they will be using JSON files to define their {@link MoveSet} which are built directly from JSON data; +public record MoveSetEntry(ResourceLocation id, MoveSet.MoveSetBuilder builder) {} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/RenderModifier.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/RenderModifier.java new file mode 100644 index 000000000..a03076843 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/data/RenderModifier.java @@ -0,0 +1,17 @@ +package yesman.epicfight.api.ex_cap.modules.core.data; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.renderer.ItemInHandRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import yesman.epicfight.api.utils.math.OpenMatrix4f; +import yesman.epicfight.client.renderer.patched.item.RenderItemBase; +import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; + +@FunctionalInterface +public interface RenderModifier { + /// Returns true if the original item renderer needs to be canceled, otherwise continues with the render chain. + boolean modify(RenderItemBase itemBaseRenderer, ItemStack stack, LivingEntityPatch livingEntityPatch, InteractionHand hand, OpenMatrix4f[] poses, MultiBufferSource source, PoseStack poseStack, int packedLight, float partialTicks, ItemRenderer renderer, ItemInHandRenderer handRenderer); +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ConditionalRegistryEvent.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ConditionalRegistryEvent.java new file mode 100644 index 000000000..9ba9ff125 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ConditionalRegistryEvent.java @@ -0,0 +1,35 @@ +package yesman.epicfight.api.ex_cap.modules.core.events; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import yesman.epicfight.api.ex_cap.modules.core.data.ConditionalEntry; +import yesman.epicfight.api.ex_cap.modules.core.provider.ProviderConditional; +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.api.event.Event; + +import java.util.Map; + +public class ConditionalRegistryEvent extends Event +{ + private final Map conditionals; + + public ConditionalRegistryEvent() + { + conditionals = Maps.newHashMap(); + } + + public Map getConditionals() { + return ImmutableMap.copyOf(conditionals); + } + + public void addConditional(ResourceLocation id, ProviderConditional.ProviderConditionalBuilder builder) { + conditionals.put(id, builder); + } + + public void addConditional(ConditionalEntry... entry) { + for (ConditionalEntry ent : entry) + { + conditionals.put(ent.id(), ent.builder()); + } + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapBuilderCreationEvent.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapBuilderCreationEvent.java new file mode 100644 index 000000000..fce9e9e7a --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapBuilderCreationEvent.java @@ -0,0 +1,35 @@ +package yesman.epicfight.api.ex_cap.modules.core.events; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import yesman.epicfight.api.ex_cap.modules.core.data.BuilderEntry; +import yesman.epicfight.api.ex_cap.modules.core.managers.ExCapManager; +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.api.event.Event; +import yesman.epicfight.world.capabilities.item.WeaponCapability; + +import java.util.Map; + +public class ExCapBuilderCreationEvent extends Event +{ + private final Map builders = Maps.newHashMap(); + + public Map getBuilders() { + return ImmutableMap.copyOf(builders); + } + + public void addBuilder(ResourceLocation rl, WeaponCapability.Builder builder) { + ExCapManager.addAcceptor(rl); + builders.put(rl, builder); + } + + public void addBuilder(BuilderEntry... entries) + { + for (BuilderEntry entry : entries) + { + addBuilder(entry.id(), entry.template()); + } + } + + +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapDataRegistrationEvent.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapDataRegistrationEvent.java new file mode 100644 index 000000000..3054744e9 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapDataRegistrationEvent.java @@ -0,0 +1,32 @@ +package yesman.epicfight.api.ex_cap.modules.core.events; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import yesman.epicfight.api.ex_cap.modules.core.data.ExCapData; +import yesman.epicfight.api.ex_cap.modules.core.data.ExCapDataEntry; +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.api.event.Event; + +import java.util.Map; + +public class ExCapDataRegistrationEvent extends Event +{ + private final Map dataMap = Maps.newHashMap(); + + public Map getDataMap() { + return ImmutableMap.copyOf(dataMap); + } + + public void addData(ResourceLocation key, ExCapData.Builder data) + { + dataMap.put(key, data); + } + + public void addData(ExCapDataEntry... entries) + { + for (ExCapDataEntry entry : entries) + { + dataMap.put(entry.id(), entry.data()); + } + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapMovesetRegistryEvent.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapMovesetRegistryEvent.java new file mode 100644 index 000000000..4d7ab6f87 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapMovesetRegistryEvent.java @@ -0,0 +1,36 @@ +package yesman.epicfight.api.ex_cap.modules.core.events; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import yesman.epicfight.api.ex_cap.modules.core.data.MoveSet; +import yesman.epicfight.api.ex_cap.modules.core.data.MoveSetEntry; +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.api.event.Event; + +import java.util.Map; + +public class ExCapMovesetRegistryEvent extends Event +{ + private final Map movesets; + + public ExCapMovesetRegistryEvent() + { + movesets = Maps.newHashMap(); + } + + public Map getMovesets() { + return ImmutableMap.copyOf(movesets); + } + + public void addMoveset(ResourceLocation id, MoveSet.MoveSetBuilder moveSet) { + movesets.put(id, moveSet); + } + + public void addMoveSet(MoveSetEntry... entries) + { + for (MoveSetEntry entry : entries) + { + addMoveset(entry.id(), entry.builder()); + } + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapabilityBuilderPopulationEvent.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapabilityBuilderPopulationEvent.java new file mode 100644 index 000000000..f4c04fcff --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/events/ExCapabilityBuilderPopulationEvent.java @@ -0,0 +1,38 @@ +package yesman.epicfight.api.ex_cap.modules.core.events; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import yesman.epicfight.api.ex_cap.modules.core.data.ExCapData; +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.api.event.Event; +import yesman.epicfight.api.ex_cap.modules.core.managers.DatasetManager; + +import java.util.Arrays; +import java.util.Map; +import java.util.List; + +public class ExCapabilityBuilderPopulationEvent extends Event { + private final Map> builders; + + public ExCapabilityBuilderPopulationEvent() { + this.builders = Maps.newHashMap(); + } + + public Map> getBuilders() { + return ImmutableMap.copyOf(builders); + } + + public void registerData(ResourceLocation target, ResourceLocation... dataSet) { + List list = Lists.newArrayList(); + for (ResourceLocation id : dataSet) { + list.add(DatasetManager.get(id)); + } + builders.computeIfAbsent(target, k -> Lists.newArrayList()).addAll(list); + } + + public void registerData(ResourceLocation target, List dataSet) + { + builders.computeIfAbsent(target, k -> Lists.newArrayList()).addAll(dataSet); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapBuilderReloadListener.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapBuilderReloadListener.java new file mode 100644 index 000000000..3cad50d27 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapBuilderReloadListener.java @@ -0,0 +1,36 @@ +package yesman.epicfight.api.ex_cap.modules.core.listeners; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import yesman.epicfight.api.ex_cap.modules.core.events.ExCapBuilderCreationEvent; +import yesman.epicfight.api.ex_cap.modules.core.managers.BuilderManager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; +import yesman.epicfight.api.event.EpicFightEventHooks; + +import java.util.Map; + +public class ExCapBuilderReloadListener extends SimpleJsonResourceReloadListener +{ + public static final String DIRECTORY = "capabilities/weapons/excap_builders"; + + private static final Gson GSON = (new GsonBuilder()).create(); + + public ExCapBuilderReloadListener() + { + super(GSON, DIRECTORY); + } + + + @Override + protected void apply(Map elementMap, ResourceManager resourceManager, ProfilerFiller profilerFiller) + { + ExCapBuilderCreationEvent exCapBuilderCreationEvent = new ExCapBuilderCreationEvent(); + EpicFightEventHooks.Registry.EX_CAP_BUILDER_CREATION.post(exCapBuilderCreationEvent); + BuilderManager.acceptEvent(exCapBuilderCreationEvent); + elementMap.forEach(BuilderManager::add); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapConditionalReloadListener.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapConditionalReloadListener.java new file mode 100644 index 000000000..d59f4e2bf --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapConditionalReloadListener.java @@ -0,0 +1,36 @@ +package yesman.epicfight.api.ex_cap.modules.core.listeners; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import yesman.epicfight.api.ex_cap.modules.core.events.ConditionalRegistryEvent; +import yesman.epicfight.api.ex_cap.modules.core.managers.ConditionalManager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; +import org.jetbrains.annotations.NotNull; +import yesman.epicfight.api.event.EpicFightEventHooks; + +import java.util.Map; + +public class ExCapConditionalReloadListener extends SimpleJsonResourceReloadListener +{ + public static final String DIRECTORY = "capabilities/weapons/conditionals"; + + private static final Gson GSON = (new GsonBuilder()).create(); + + public ExCapConditionalReloadListener() + { + super(GSON, DIRECTORY); + } + + @Override + protected void apply(@NotNull Map elementMap, @NotNull ResourceManager resourceManager, @NotNull ProfilerFiller profilerFiller) + { + ConditionalRegistryEvent conditionalRegistryEvent = new ConditionalRegistryEvent(); + EpicFightEventHooks.Registry.EX_CAP_CONDITIONAL_REGISTRATION.post(conditionalRegistryEvent); + ConditionalManager.acceptEvent(conditionalRegistryEvent); + elementMap.forEach(ConditionalManager::add); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapDataCreationReloadListener.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapDataCreationReloadListener.java new file mode 100644 index 000000000..1e474c6f1 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapDataCreationReloadListener.java @@ -0,0 +1,37 @@ +package yesman.epicfight.api.ex_cap.modules.core.listeners; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import yesman.epicfight.api.ex_cap.modules.core.events.ExCapDataRegistrationEvent; +import yesman.epicfight.api.ex_cap.modules.core.managers.DatasetManager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; +import org.jetbrains.annotations.NotNull; +import yesman.epicfight.api.event.EpicFightEventHooks; + +import java.util.Map; + +public class ExCapDataCreationReloadListener extends SimpleJsonResourceReloadListener +{ + + public static final String DIRECTORY = "capabilities/weapons/ex_cap_data/definitions"; + + private static final Gson GSON = (new GsonBuilder()).create(); + + public ExCapDataCreationReloadListener() + { + super(GSON, DIRECTORY); + } + @Override + protected void apply(@NotNull Map elementMap, @NotNull ResourceManager resourceManager, @NotNull ProfilerFiller profilerFiller) + { + ExCapDataRegistrationEvent exCapDataRegistrationEvent = new ExCapDataRegistrationEvent(); + EpicFightEventHooks.Registry.EX_CAP_DATA_CREATION.post(exCapDataRegistrationEvent); + DatasetManager.acceptEvent(exCapDataRegistrationEvent); + + + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapDataReloadListener.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapDataReloadListener.java new file mode 100644 index 000000000..bbda7e65d --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapDataReloadListener.java @@ -0,0 +1,68 @@ +package yesman.epicfight.api.ex_cap.modules.core.listeners; + +import com.google.common.collect.Lists; +import com.google.gson.*; +import yesman.epicfight.api.ex_cap.modules.core.events.ExCapabilityBuilderPopulationEvent; +import yesman.epicfight.api.ex_cap.modules.core.managers.ExCapManager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; +import org.jetbrains.annotations.NotNull; +import yesman.epicfight.EpicFight; +import yesman.epicfight.api.event.EpicFightEventHooks; + +import java.util.List; +import java.util.Map; + +public class ExCapDataReloadListener extends SimpleJsonResourceReloadListener +{ + public static final String DIRECTORY = "capabilities/weapons/ex_cap_data/loader"; + + private static final Gson GSON = (new GsonBuilder()).create(); + + public ExCapDataReloadListener() + { + super(GSON, DIRECTORY); + } + + @Override + protected void apply(@NotNull Map elementMap, @NotNull ResourceManager resourceManager, @NotNull ProfilerFiller profilerFiller) + { + ExCapabilityBuilderPopulationEvent exCapabilityBuilderPopulationEvent = new ExCapabilityBuilderPopulationEvent(); + EpicFightEventHooks.Registry.EX_CAP_DATA_POPULATION.post(exCapabilityBuilderPopulationEvent); + ExCapManager.acceptEvent(exCapabilityBuilderPopulationEvent); + + elementMap.forEach(this::deserialize); + } + + protected void deserialize(ResourceLocation rl, JsonElement jsonElement) { + EpicFight.LOGGER.info("Deserializing data for Ex Cap from JSON: {}", rl); + JsonObject obj = jsonElement.getAsJsonObject(); + if (obj.has("target") && obj.get("target").isJsonPrimitive()) + { + ResourceLocation target = ResourceLocation.tryParse(obj.get("target").getAsString().toLowerCase()); + if (target == null) + { + EpicFight.LOGGER.warn("Invalid target ResourceLocation in Ex Cap data JSON: {}", rl); + return; + } + if (obj.has("ex_cap_data") && obj.get("ex_cap_data").isJsonArray()) + { + JsonArray exCapData = obj.getAsJsonArray("ex_cap_data"); + List exCapDataList = Lists.newArrayList(); + exCapData.asList().forEach(capData -> { + if (capData.isJsonPrimitive()) + { + ResourceLocation capDataRL = ResourceLocation.tryParse(capData.getAsString().toLowerCase()); + if (capDataRL != null) + { + exCapDataList.add(capDataRL); + } + } + }); + ExCapManager.addExCapData(target, exCapDataList); + } + } + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapMovesetReloadListener.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapMovesetReloadListener.java new file mode 100644 index 000000000..dc01a1ac1 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/listeners/ExCapMovesetReloadListener.java @@ -0,0 +1,36 @@ +package yesman.epicfight.api.ex_cap.modules.core.listeners; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import yesman.epicfight.api.ex_cap.modules.core.events.ExCapMovesetRegistryEvent; +import yesman.epicfight.api.ex_cap.modules.core.managers.MovesetManager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; +import org.jetbrains.annotations.NotNull; +import yesman.epicfight.api.event.EpicFightEventHooks; + +import java.util.Map; + +public class ExCapMovesetReloadListener extends SimpleJsonResourceReloadListener +{ + public static final String DIRECTORY = "capabilities/weapons/movesets"; + + private static final Gson GSON = (new GsonBuilder()).create(); + + public ExCapMovesetReloadListener() + { + super(GSON, DIRECTORY); + } + + @Override + protected void apply(@NotNull Map elementMap, @NotNull ResourceManager resourceManager, @NotNull ProfilerFiller profilerFiller) + { + ExCapMovesetRegistryEvent exCapMovesetRegistryEvent = new ExCapMovesetRegistryEvent(); + EpicFightEventHooks.Registry.EX_CAP_MOVESET_REGISTRY.post(exCapMovesetRegistryEvent); + MovesetManager.acceptEvent(exCapMovesetRegistryEvent); + elementMap.forEach(MovesetManager::add); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/BuilderManager.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/BuilderManager.java new file mode 100644 index 000000000..22d196199 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/BuilderManager.java @@ -0,0 +1,50 @@ +package yesman.epicfight.api.ex_cap.modules.core.managers; + +import com.google.common.collect.Maps; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import yesman.epicfight.api.ex_cap.modules.core.events.ExCapBuilderCreationEvent; +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.EpicFight; +import yesman.epicfight.api.event.types.registry.WeaponCapabilityPresetRegistryEvent; +import yesman.epicfight.world.capabilities.item.WeaponCapability; +import yesman.epicfight.world.capabilities.item.WeaponCapabilityPresets; + +import java.util.Map; + +public class BuilderManager { + private static final Map weaponCapabilityBuilders = Maps.newHashMap(); + + public static WeaponCapability.Builder get(ResourceLocation id) { + return weaponCapabilityBuilders.get(id); + } + + public static void acceptEvent(ExCapBuilderCreationEvent event) + { + weaponCapabilityBuilders.clear(); + weaponCapabilityBuilders.putAll(event.getBuilders()); + } + + public static void acceptExport(WeaponCapabilityPresetRegistryEvent event) + { + weaponCapabilityBuilders.entrySet().forEach(entry -> event.getTypeEntry().put(entry.getKey(), item -> WeaponCapabilityPresets.exCapRegistration(entry, item))); + } + + public static Map.Entry getEntry(ResourceLocation id) + { + WeaponCapability.Builder builder = weaponCapabilityBuilders.get(id); + return builder == null ? null : Map.entry(id, builder); + } + + public static void add(ResourceLocation id, JsonElement json) + { + try { + weaponCapabilityBuilders.put(id, WeaponCapability.Builder.deserializeBuilder(json)); + } catch (JsonParseException e) + { + // Log the error and skip this entry + EpicFight.LOGGER.warn(e.getMessage()); + } + + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/ConditionalManager.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/ConditionalManager.java new file mode 100644 index 000000000..6d8c4580e --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/ConditionalManager.java @@ -0,0 +1,29 @@ +package yesman.epicfight.api.ex_cap.modules.core.managers; + +import com.google.common.collect.Maps; +import com.google.gson.JsonElement; +import yesman.epicfight.api.ex_cap.modules.core.events.ConditionalRegistryEvent; +import yesman.epicfight.api.ex_cap.modules.core.provider.ProviderConditional; +import net.minecraft.resources.ResourceLocation; + +import java.util.Map; + +public class ConditionalManager +{ + private static final Map CONDITIONALS = Maps.newHashMap(); + + public static ProviderConditional.ProviderConditionalBuilder get(ResourceLocation id) { + return CONDITIONALS.get(id); + } + + public static void add(ResourceLocation id, JsonElement json) { + CONDITIONALS.put(id, ProviderConditional.ProviderConditionalBuilder.deserialize(json)); + } + + public static void acceptEvent(ConditionalRegistryEvent event) + { + CONDITIONALS.clear(); + CONDITIONALS.putAll(event.getConditionals()); + } + +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/DatasetManager.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/DatasetManager.java new file mode 100644 index 000000000..63fbd231b --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/DatasetManager.java @@ -0,0 +1,28 @@ +package yesman.epicfight.api.ex_cap.modules.core.managers; + +import com.google.common.collect.Maps; +import yesman.epicfight.api.ex_cap.modules.core.data.ExCapData; +import yesman.epicfight.api.ex_cap.modules.core.events.ExCapDataRegistrationEvent; +import net.minecraft.resources.ResourceLocation; +import com.google.gson.JsonElement; + +import java.util.Map; + +public class DatasetManager { + private static final Map dataMap = Maps.newHashMap(); + + public static void acceptEvent(ExCapDataRegistrationEvent event) { + dataMap.clear(); + dataMap.putAll(event.getDataMap()); + } + + public static ExCapData.Builder get(ResourceLocation resourceLocation) + { + return dataMap.get(resourceLocation); + } + + public static void add(ResourceLocation resourceLocation, JsonElement jsonElement) + { + dataMap.put(resourceLocation, ExCapData.Builder.deserialize(jsonElement)); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/ExCapManager.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/ExCapManager.java new file mode 100644 index 000000000..d9df97cc0 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/ExCapManager.java @@ -0,0 +1,63 @@ +package yesman.epicfight.api.ex_cap.modules.core.managers; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import yesman.epicfight.api.ex_cap.modules.core.data.ExCapData; +import yesman.epicfight.api.ex_cap.modules.core.events.ExCapabilityBuilderPopulationEvent; +import net.minecraft.resources.ResourceLocation; + +import java.util.Map; +import java.util.List; + + +public class ExCapManager +{ + private static final Map> dataMap = Maps.newHashMap(); + + /** + * Registers the preset builder as an acceptor + * @param cap The statically registered Capability Builder + */ + public static void addAcceptor(ResourceLocation cap) + { + dataMap.putIfAbsent(cap, Lists.newArrayList()); + } + + public static List retrieveExCapData(ResourceLocation cap) + { + return dataMap.get(cap); + } + + public static void addExCapData(ResourceLocation cap, List data) + { + List list = Lists.newArrayList(); + for (ResourceLocation rl : data) + { + list.add(DatasetManager.get(rl)); + } + dataMap.computeIfAbsent(cap, k -> Lists.newArrayList()).addAll(list); + } + + public static Map> getDataMap() + { + return ImmutableMap.copyOf(dataMap); + } + + public static void acceptEvent(ExCapabilityBuilderPopulationEvent event) + { + clearEntries(); + dataMap.putAll(event.getBuilders()); + } + + public static void clearEntries() + { + //Do not clear the actual keys, only clear the lists + dataMap.forEach(ExCapManager::clearList); + } + + private static void clearList(ResourceLocation rl, List list) + { + list.clear(); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/MovesetManager.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/MovesetManager.java new file mode 100644 index 000000000..dbe64dbf1 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/managers/MovesetManager.java @@ -0,0 +1,38 @@ +package yesman.epicfight.api.ex_cap.modules.core.managers; + +import com.google.common.collect.Maps; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import yesman.epicfight.api.ex_cap.modules.core.data.MoveSet; +import yesman.epicfight.api.ex_cap.modules.core.events.ExCapMovesetRegistryEvent; +import net.minecraft.resources.ResourceLocation; +import yesman.epicfight.EpicFight; + +import java.util.Map; + +public class MovesetManager +{ + private static final Map MOVESETS = Maps.newHashMap(); + + public static void acceptEvent(ExCapMovesetRegistryEvent event) + { + MOVESETS.clear(); + MOVESETS.putAll(event.getMovesets()); + } + + public static void add(ResourceLocation id, JsonElement jsonElement) + { + try { + MoveSet.MoveSetBuilder builder = MoveSet.MoveSetBuilder.deserialize(jsonElement); + MOVESETS.put(id, builder); + } catch (JsonParseException e) { + //Skip invalid JSON + EpicFight.LOGGER.warn(e.getMessage()); + } + } + + public static MoveSet.MoveSetBuilder getBuilder(ResourceLocation id) + { + return MOVESETS.get(id); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/CoreWeaponCapabilityProvider.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/CoreWeaponCapabilityProvider.java new file mode 100644 index 000000000..c1715bde4 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/CoreWeaponCapabilityProvider.java @@ -0,0 +1,85 @@ +package yesman.epicfight.api.ex_cap.modules.core.provider; + +import com.google.common.collect.Lists; +import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; +import yesman.epicfight.world.capabilities.item.Style; + +import java.util.Arrays; +import java.util.List; + +/** + * This class is meant to be as an extendbale + */ +public class CoreWeaponCapabilityProvider +{ + private final List conditionals; + public CoreWeaponCapabilityProvider() + { + conditionals = Lists.newArrayList(); + } + + public void addConditional(ProviderConditional... conditional) + { + this.conditionals.addAll(Arrays.asList(conditional)); + } + + public void addConditional(List conditionals) + { + this.conditionals.addAll(conditionals); + } + + public CoreWeaponCapabilityProvider copy() + { + CoreWeaponCapabilityProvider copy = new CoreWeaponCapabilityProvider(); + conditionals.forEach(s -> copy.addConditional(s.copy())); + return copy; + } + + private void sortByPriority() + { + if (conditionals.size() <= 1) return; + for (int i = 0; i < conditionals.size() - 1; i++) + { + ProviderConditional conditional = conditionals.get(i).copy(); + if (conditional.getPriority() < conditionals.get(i + 1).getPriority()) + { + conditionals.set(i, conditionals.get(i+1)); + conditionals.set(i+1, conditional); + } + } + } + + /** + * @throws NullPointerException if none of the provided Conditionals return a Style; + * @return The Function that is used for the StyleProvider + */ + public Style getStyle(LivingEntityPatch entityPatch) + { + sortByPriority(); + for (ProviderConditional conditional : conditionals) + { + if (conditional.test(entityPatch)) + { + return conditional.style; + } + } + return null; + } + + /** + * @throws NullPointerException if none of the provided Conditionals return a Style; + * @return Boolean + */ + public Boolean checkVisibleOffHand(LivingEntityPatch entityPatch) + { + sortByPriority(); + for (ProviderConditional conditional : conditionals) + { + if (conditional.test(entityPatch)) + { + return conditional.combination; + } + } + return null; + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/HelperFunctions.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/HelperFunctions.java new file mode 100644 index 000000000..72728cc41 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/HelperFunctions.java @@ -0,0 +1,27 @@ +package yesman.epicfight.api.ex_cap.modules.core.provider; + +import net.minecraft.world.InteractionHand; +import yesman.epicfight.skill.Skill; +import yesman.epicfight.skill.SkillSlot; +import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; +import yesman.epicfight.world.capabilities.entitypatch.player.PlayerPatch; +import yesman.epicfight.world.capabilities.item.WeaponCategory; + +public class HelperFunctions +{ + //Initial Helper Functions + public static boolean itemCheck(LivingEntityPatch entityPatch, WeaponCategory category, InteractionHand hand) + { + return entityPatch.getHoldingItemCapability(hand).getWeaponCategory() == category; + } + public static boolean skillCheck(LivingEntityPatch entityPatch, Skill skill, SkillSlot slot) + { + if (entityPatch instanceof PlayerPatch patch) + { + if (slot == null) + return (patch.getSkill(skill)) != null; + return patch.getSkill(slot).hasSkill(skill); + } + return false; + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/ProviderConditional.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/ProviderConditional.java new file mode 100644 index 000000000..8ceeb7a23 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/ProviderConditional.java @@ -0,0 +1,501 @@ +package yesman.epicfight.api.ex_cap.modules.core.provider; + +import com.google.common.collect.Lists; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import yesman.epicfight.api.ex_cap.modules.core.managers.ConditionalManager; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.Item; +import org.jetbrains.annotations.NotNull; +import yesman.epicfight.EpicFight; +import yesman.epicfight.registry.EpicFightRegistries; +import yesman.epicfight.skill.Skill; +import yesman.epicfight.skill.SkillDataKey; +import yesman.epicfight.skill.SkillSlot; +import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; +import yesman.epicfight.world.capabilities.entitypatch.player.PlayerPatch; +import yesman.epicfight.world.capabilities.item.Style; +import yesman.epicfight.world.capabilities.item.WeaponCategory; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; +import java.util.function.Predicate; + +public class ProviderConditional +{ + public static final ResourceKey> REGISTRY_KEY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(EpicFight.MODID, "ex_cap_conditional")); + + //Identifiers + protected final ProviderConditionalType type; + //Output + protected final Style style; + protected final Boolean combination; + //Input + protected final Skill skillToCheck; + protected final WeaponCategory category; + protected final Item weapon; + protected final List providerConditionals; + protected final SkillSlot slot; + protected final Holder> key; + protected final InteractionHand hand; + protected final Predicate> customFunction; + + private ProviderConditional(ProviderConditionalType type, Style style, Skill skillToCheck, WeaponCategory category, Item weapon, InteractionHand hand, SkillSlot slot, Holder> key, Boolean combination, Predicate> customFunction, List providerConditionals) { + this.type = type; + this.style = style; + this.skillToCheck = skillToCheck; + this.category = category; + this.weapon = weapon; + this.hand = hand; + this.slot = slot; + this.key = key; + this.combination = combination; + this.customFunction = customFunction; + this.providerConditionals = Lists.newArrayList(providerConditionals); + } + + public static ProviderConditionalBuilder builder() + { + return new ProviderConditionalBuilder(); + } + + public ProviderConditional(ProviderConditionalBuilder builder) + { + this.type = builder.type; + this.style = builder.wieldStyle; + this.combination = builder.visibleOffHand; + this.skillToCheck = builder.skillToCheck; + this.category = builder.category; + this.weapon = builder.weapon; + //Build the sub-conditionals, + this.providerConditionals = Lists.newArrayList(); + builder.providerConditionals.forEach(subCond -> providerConditionals.add(subCond.build())); + this.slot = builder.slot; + this.key = builder.key; + this.hand = builder.hand; + this.customFunction = builder.customFunction; + } + + + /** + * @param entityPatch the patch used to return whatever it is. + * @return if the conditionals ever evaluate to true. + */ + public Boolean test(LivingEntityPatch entityPatch) + { + if (type.equals(ProviderConditionalType.SKILL_ACTIVATION)) + { + if (entityPatch instanceof PlayerPatch pPatch) + { + if (pPatch.getSkill(slot).isActivated()) + { + return true; + } + } + } + if (type.equals(ProviderConditionalType.SKILL_EXISTENCE)) + { + if (HelperFunctions.skillCheck(entityPatch, skillToCheck, slot)) + { + return true; + } + } + if (type.equals(ProviderConditionalType.WEAPON_CATEGORY)) + { + if (HelperFunctions.itemCheck(entityPatch, category, hand)) + { + return true; + } + } + if (type.equals(ProviderConditionalType.DATA_KEY)) + { + if (entityPatch instanceof PlayerPatch playerPatch) + { + return playerPatch.getSkill(slot).getDataManager().hasData(key) && (Boolean) playerPatch.getSkill(slot).getDataManager().getRawDataValue(key); + } + } + if (type.equals(ProviderConditionalType.SPECIFIC_WEAPON)) + { + assert hand != null; + return entityPatch.getOriginal().getItemInHand(hand).is(weapon); + } + if (type.equals(ProviderConditionalType.COMPOSITE)) + { + assert providerConditionals != null; + for (ProviderConditional conditional : providerConditionals) + { + if (!conditional.test(entityPatch)) + { + return false; + } + } + return true; + } + if (type.equals(ProviderConditionalType.CUSTOM)) + { + assert this.customFunction != null; + if (this.customFunction.test(entityPatch)) + { + return true; + } + } + return type.equals(ProviderConditionalType.DEFAULT); + } + + public Style testConditionalStyle(LivingEntityPatch entityPatch) + { + if (type.equals(ProviderConditionalType.SKILL_ACTIVATION)) + { + if (entityPatch instanceof PlayerPatch pPatch) + { + if (pPatch.getSkill(slot).isActivated()) + { + return style; + } + } + } + if (type.equals(ProviderConditionalType.SKILL_EXISTENCE)) + { + if (HelperFunctions.skillCheck(entityPatch, skillToCheck, slot)) + return style; + } + if (type.equals(ProviderConditionalType.WEAPON_CATEGORY)) + { + if (HelperFunctions.itemCheck(entityPatch, category, hand)) + return style; + } + if (type.equals(ProviderConditionalType.DATA_KEY)) + { + if (entityPatch instanceof PlayerPatch playerPatch) + { + if (playerPatch.getSkill(slot).getDataManager().hasData(key) && (Boolean) playerPatch.getSkill(slot).getDataManager().getRawDataValue(key)) + return style; + } + } + if (type.equals(ProviderConditionalType.SPECIFIC_WEAPON)) + { + assert hand != null; + if (entityPatch.getOriginal().getItemInHand(hand).is(this.weapon)) + return style; + } + if (type.equals(ProviderConditionalType.COMPOSITE)) + { + assert providerConditionals != null; + for (ProviderConditional conditional : providerConditionals) + { + if (!conditional.test(entityPatch)) + return null; + } + return style; + } + if (type.equals(ProviderConditionalType.CUSTOM)) + { + assert this.customFunction != null; + if (this.customFunction.test(entityPatch)) + { + return style; + } + } + if (type.equals(ProviderConditionalType.DEFAULT)) + return style; + return null; + } + + public Boolean testConditionalCombo(LivingEntityPatch entityPatch) + { + if (type.equals(ProviderConditionalType.SKILL_ACTIVATION)) + { + if (entityPatch instanceof PlayerPatch pPatch) + { + if (pPatch.getSkill(slot).isActivated()) + { + return combination; + } + } + } + if (type.equals(ProviderConditionalType.SKILL_EXISTENCE)) + { + if (HelperFunctions.skillCheck(entityPatch, skillToCheck, slot)) + return combination; + } + if (type.equals(ProviderConditionalType.WEAPON_CATEGORY)) + { + if (HelperFunctions.itemCheck(entityPatch, category, hand)) + return combination; + } + if (type.equals(ProviderConditionalType.DATA_KEY)) + { + if (entityPatch instanceof PlayerPatch playerPatch) + { + if (playerPatch.getSkill(slot).getDataManager().hasData(key) && (Boolean) playerPatch.getSkill(slot).getDataManager().getRawDataValue(key)) + return combination; + } + } + if (type.equals(ProviderConditionalType.SPECIFIC_WEAPON)) + { + assert hand != null; + if (entityPatch.getOriginal().getItemInHand(hand).is(this.weapon)) + return combination; + } + if (type.equals(ProviderConditionalType.COMPOSITE)) + { + assert providerConditionals != null; + for (ProviderConditional conditional : providerConditionals) + { + if (!conditional.test(entityPatch)) + return null; + } + return combination; + } + if (type.equals(ProviderConditionalType.CUSTOM)) + { + assert this.customFunction != null; + if (this.customFunction.test(entityPatch)) + { + return combination; + } + } + if (type.equals(ProviderConditionalType.DEFAULT)) + return combination; + return null; + } + +// private boolean checkSubConditionalsForExistence() +// { +// if (type == ProviderConditionalType.COMPOSITE) +// { +// assert providerConditionals != null; +// for (ProviderConditional conditional : providerConditionals) +// { +// if (conditional.type == ProviderConditionalType.SKILL_EXISTENCE && conditional.slot == BattleArtsSkillSlots.BATTLE_STYLE) +// return true; +// } +// } +// return false; +// } + + public ProviderConditionalType getType() + { + return type; + } + +// private boolean checkSubConditionalsForDataKey() +// { +// if (type == ProviderConditionalType.COMPOSITE) +// { +// assert providerConditionals != null; +// for (ProviderConditional conditional : providerConditionals) +// { +// if (conditional.type == ProviderConditionalType.DATA_KEY && conditional.slot == BattleArtsSkillSlots.BATTLE_STYLE) +// return true; +// } +// } +// return false; +// } + + public int getPriority() + { + //TODO: Move this into Battle Arts API; + // if (ModList.get().isLoaded("battlearts_api") && type == ProviderConditionalType.SKILL_EXISTENCE && slot == BattleArtsSkillSlots.BATTLE_STYLE) + // return Integer.MAX_VALUE - 3; + // if (type == ProviderConditionalType.DATA_KEY && ModList.get().isLoaded("battlearts_api") && slot == BattleArtsSkillSlots.BATTLE_STYLE) + // return Integer.MAX_VALUE - 2; + // if (type == ProviderConditionalType.COMPOSITE && ModList.get().isLoaded("battlearts_api") && checkSubConditionalsForExistence()) + // return Integer.MAX_VALUE - 1; + // if (type == ProviderConditionalType.COMPOSITE && ModList.get().isLoaded("battlearts_api") && checkSubConditionalsForDataKey()) + // return Integer.MAX_VALUE; + return this.type.getPriority(); + } + + public ProviderConditional copy() + { + return new ProviderConditional(type, style, skillToCheck, category, weapon, hand, slot, key, combination, customFunction, providerConditionals); + } + public static class ProviderConditionalBuilder + { + private ProviderConditionalType type; + private Style wieldStyle; + private Boolean visibleOffHand; + private Skill skillToCheck; + private WeaponCategory category; + private Item weapon; + private final List providerConditionals; + private SkillSlot slot; + private Holder> key; + private InteractionHand hand; + private Predicate> customFunction; + protected ResourceLocation parent; + + + public ProviderConditionalBuilder() + { + type = ProviderConditionalType.DEFAULT; + skillToCheck = null; + category = null; + weapon = null; + providerConditionals = Lists.newArrayList(); + slot = null; + key = null; + hand = null; + customFunction = null; + wieldStyle = null; + visibleOffHand = false; + } + + public ProviderConditionalBuilder setParent(ResourceLocation parent) + { + this.parent = parent; + return this; + } + + public static ProviderConditionalBuilder deserialize(JsonElement jsonElement) throws JsonParseException + { + ProviderConditionalBuilder builder = new ProviderConditionalBuilder(); + try { + JsonObject gsonObject = jsonElement.getAsJsonObject(); + ProviderConditionalType type = ProviderConditionalType.valueOf(gsonObject.get("provider_type").getAsString().toUpperCase()); + Style wieldStyle = Style.ENUM_MANAGER.get(gsonObject.get("style").getAsString().toUpperCase()); + boolean visibleOffHand = gsonObject.get("visible_offhand").getAsBoolean(); + builder.setType(type); + switch (type) { + case WEAPON_CATEGORY -> builder + .setType(type).setWieldStyle(wieldStyle).isVisibleOffHand(visibleOffHand) + .setCategory(WeaponCategory.ENUM_MANAGER.get(gsonObject.get("weapon_category").getAsString().toUpperCase())) + .setHand(InteractionHand.valueOf(gsonObject.get("hand").getAsString().toUpperCase())); + case SPECIFIC_WEAPON -> builder + .setType(type).setWieldStyle(wieldStyle).isVisibleOffHand(visibleOffHand) + .setWeapon(BuiltInRegistries.ITEM.get(ResourceLocation.parse(gsonObject.get("specific_weapon").getAsString()))) + .setHand(InteractionHand.valueOf(gsonObject.get("hand").getAsString().toUpperCase())); + case SKILL_EXISTENCE, SKILL_ACTIVATION -> builder + .setType(type).setWieldStyle(wieldStyle).isVisibleOffHand(visibleOffHand) + .setSkillToCheck(EpicFightRegistries.SKILL.get(ResourceLocation.parse(gsonObject.get("skill").getAsString()))) + .setSlot(SkillSlot.ENUM_MANAGER.get(gsonObject.get("slot").getAsString().toUpperCase())); + case DATA_KEY -> builder + .setType(type).setWieldStyle(wieldStyle).isVisibleOffHand(visibleOffHand) + .setSkillToCheck(EpicFightRegistries.SKILL.get(ResourceLocation.parse(gsonObject.get("skill").getAsString()))) + .setKey(EpicFightRegistries.SKILL_DATA_KEY.getHolder(ResourceLocation.parse(gsonObject.get("boolean_key").getAsString())).get()) + .setSlot(SkillSlot.ENUM_MANAGER.get(gsonObject.get("slot").getAsString().toUpperCase())); + } + } + catch (RuntimeException e) + { + throw new JsonParseException("Failed to parse ProviderConditional: " + e.getMessage()); + } + return builder; + } + + private ProviderConditionalBuilder merge() + { + ProviderConditionalBuilder result = new ProviderConditionalBuilder(); + Deque hierarchy = new ArrayDeque<>(); + ProviderConditionalBuilder current = this; + + // Collect parent chain + while (current != null) { + hierarchy.push(current); + current = ConditionalManager.get(parent); + } + + while (!hierarchy.isEmpty()) { + ProviderConditionalBuilder builder = hierarchy.pop(); + if (builder.type != ProviderConditionalType.DEFAULT) + result.setType(builder.type); + if (builder.wieldStyle != null) + result.setWieldStyle(builder.wieldStyle); + if (builder.visibleOffHand) + result.isVisibleOffHand(true); + if (builder.skillToCheck != null) + result.setSkillToCheck(builder.skillToCheck); + if (builder.category != null) + result.setCategory(builder.category); + if (builder.weapon != null) + result.setWeapon(builder.weapon); + if (builder.slot != null) + result.setSlot(builder.slot); + if (builder.key != null) + result.setKey(builder.key); + if (builder.hand != null) + result.setHand(builder.hand); + if (builder.customFunction != null) + result.setCustomFunction(builder.customFunction); + result.providerConditionals.addAll(builder.providerConditionals); + } + return result; + } + + public ProviderConditional build() + { + return new ProviderConditional(merge()); + } + + public ProviderConditionalBuilder isVisibleOffHand(boolean visibleOffHand) { + this.visibleOffHand = visibleOffHand; + return this; + } + + public ProviderConditionalBuilder setWieldStyle(Style wieldStyle) { + this.wieldStyle = wieldStyle; + return this; + } + + public ProviderConditionalBuilder setType(@NotNull ProviderConditionalType type) + { + this.type = type; + return this; + } + + public ProviderConditionalBuilder setSkillToCheck(Skill skillToCheck) { + this.skillToCheck = skillToCheck; + return this; + } + + public ProviderConditionalBuilder setCategory(WeaponCategory category) { + this.category = category; + return this; + } + + public ProviderConditionalBuilder setWeapon(Item weapon) { + this.weapon = weapon; + return this; + } + + public ProviderConditionalBuilder setProviderConditionals(ProviderConditionalBuilder... providerConditionals) { + for (ProviderConditionalBuilder conditional : providerConditionals) + { + if (conditional.type == ProviderConditionalType.COMPOSITE) + { + throw new IllegalArgumentException("Cannot have composite conditionals as sub-conditionals."); + } + this.providerConditionals.add(conditional); + } + return this; + } + + public ProviderConditionalBuilder setSlot(SkillSlot slot) { + this.slot = slot; + return this; + } + + public ProviderConditionalBuilder setKey(Holder> key) { + this.key = key; + return this; + } + + public ProviderConditionalBuilder setHand(InteractionHand hand) { + this.hand = hand; + return this; + } + + public ProviderConditionalBuilder setCustomFunction(Predicate> customFunction) { + this.customFunction = customFunction; + return this; + } + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/ProviderConditionalType.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/ProviderConditionalType.java new file mode 100644 index 000000000..613e66149 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/core/provider/ProviderConditionalType.java @@ -0,0 +1,25 @@ +package yesman.epicfight.api.ex_cap.modules.core.provider; + +public enum ProviderConditionalType +{ + WEAPON_CATEGORY(1), + SPECIFIC_WEAPON(2), + SKILL_EXISTENCE(3), + SKILL_ACTIVATION(4), + DATA_KEY(5), + COMPOSITE(6), + CUSTOM(7), + DEFAULT(0); + + private final int priority; + + ProviderConditionalType(int priority) + { + this.priority = priority; + } + + public int getPriority() + { + return priority; + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/hooks/ExCapRegistryHooks.java b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/hooks/ExCapRegistryHooks.java new file mode 100644 index 000000000..5fe438898 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/api/ex_cap/modules/hooks/ExCapRegistryHooks.java @@ -0,0 +1,123 @@ +package yesman.epicfight.api.ex_cap.modules.hooks; + +import yesman.epicfight.api.ex_cap.modules.assets.Builders; +import yesman.epicfight.api.ex_cap.modules.assets.ExCapDataSets; +import yesman.epicfight.api.ex_cap.modules.assets.MainConditionals; +import yesman.epicfight.api.ex_cap.modules.assets.Movesets; +import yesman.epicfight.api.ex_cap.modules.core.events.*; +import yesman.epicfight.api.ex_cap.modules.core.events.*; +import yesman.epicfight.api.ex_cap.modules.core.managers.BuilderManager; +import yesman.epicfight.api.event.types.registry.WeaponCapabilityPresetRegistryEvent; + +public class ExCapRegistryHooks +{ + public static void registerExCapMethods(ExCapabilityBuilderPopulationEvent event) + { + event.registerData(Builders.SWORD.id(), ExCapDataSets.SWORD.id()); + event.registerData(Builders.AXE.id(), ExCapDataSets.AXE.id()); + event.registerData(Builders.PICKAXE.id(), ExCapDataSets.PICKAXE.id()); + event.registerData(Builders.SHOVEL.id(), ExCapDataSets.SHOVEL.id()); + event.registerData(Builders.HOE.id(), ExCapDataSets.HOE.id()); + event.registerData(Builders.SPEAR.id(), ExCapDataSets.SPEAR.id()); + event.registerData(Builders.GREATSWORD.id(), ExCapDataSets.GREATSWORD.id()); + event.registerData(Builders.LONGSWORD.id(), ExCapDataSets.LONGSWORD.id()); + event.registerData(Builders.TACHI.id(), ExCapDataSets.TACHI.id()); + event.registerData(Builders.UCHIGATANA.id(), ExCapDataSets.UCHIGATANA.id()); + event.registerData(Builders.DAGGER.id(), ExCapDataSets.DAGGER.id()); + event.registerData(Builders.FIST.id(), ExCapDataSets.FIST.id()); + event.registerData(Builders.BOW.id(), ExCapDataSets.BOW.id()); + event.registerData(Builders.CROSSBOW.id(), ExCapDataSets.CROSSBOW.id()); + event.registerData(Builders.TRIDENT.id(), ExCapDataSets.TRIDENT.id()); + event.registerData(Builders.SHIELD.id(), ExCapDataSets.SHIELD.id()); + } + + public static void registerData(ExCapDataRegistrationEvent event) + { + event.addData( + ExCapDataSets.SWORD, + ExCapDataSets.AXE, + ExCapDataSets.PICKAXE, + ExCapDataSets.SHOVEL, + ExCapDataSets.DAGGER, + ExCapDataSets.SPEAR, + ExCapDataSets.GREATSWORD, + ExCapDataSets.LONGSWORD, + ExCapDataSets.TACHI, + ExCapDataSets.UCHIGATANA, + ExCapDataSets.HOE, + ExCapDataSets.BOW, + ExCapDataSets.CROSSBOW, + ExCapDataSets.FIST, + ExCapDataSets.SHIELD, + ExCapDataSets.TRIDENT + ); + } + + public static void registerExCapBuilders(ExCapBuilderCreationEvent event) + { + event.addBuilder( + Builders.GREATSWORD, + Builders.AXE, + Builders.SWORD, + Builders.SPEAR, + Builders.SHOVEL, + Builders.PICKAXE, + Builders.HOE, + Builders.UCHIGATANA, + Builders.TACHI, + Builders.DAGGER, + Builders.LONGSWORD, + Builders.FIST, + Builders.BOW, + Builders.CROSSBOW, + Builders.TRIDENT, + Builders.SHIELD + ); + } + + public static void registerConditionals(ConditionalRegistryEvent event) + { + event.addConditional( + MainConditionals.DEFAULT_1H_WIELD_STYLE, + MainConditionals.DEFAULT_2H_WIELD_STYLE, + MainConditionals.DEFAULT_RANGED, + MainConditionals. SHIELD_OFFHAND, + MainConditionals.LIECHTENAUER_CONDITION, + MainConditionals.UCHIGATANA_SHEATHED, + MainConditionals.DUAL_DAGGERS, + MainConditionals. DUAL_SWORDS); + } + + public static void registerExCapMovesets(ExCapMovesetRegistryEvent event) + { + event.addMoveSet( + Movesets.commonShield, + Movesets.mountedSwordMS, + Movesets.greatsword2HMS, + Movesets.axeOneHandMS, + Movesets.mountedSpearMS, + Movesets.longsword2HMS, + Movesets.longsword1HMS, + Movesets.liechtenauerMS, + Movesets.dagger1HMS, + Movesets.dagger2HMS, + Movesets.spear2HMS, + Movesets.spear1HMS, + Movesets.sword1HMS, + Movesets.sword2HMS, + Movesets.shield, + Movesets.tachi2HMS, + Movesets.uchigatanaBase, + Movesets.uchigatanaSheathed, + Movesets.glove, + Movesets.bow, + Movesets.crossBow, + Movesets.tridentMS + ); + } + + + public static void registerWeaponCapabilities(WeaponCapabilityPresetRegistryEvent event) { + BuilderManager.acceptExport(event); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/client/events/ClientEvents.java b/neoforge/src/main/java/yesman/epicfight/client/events/ClientEvents.java deleted file mode 100644 index e69de29bb..000000000 diff --git a/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderItemBase.java b/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderItemBase.java index 49cc0e527..d69c720a9 100644 --- a/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderItemBase.java +++ b/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderItemBase.java @@ -18,11 +18,15 @@ import net.minecraft.world.item.ItemStack; import yesman.epicfight.api.animation.Joint; import yesman.epicfight.api.client.animation.property.TrailInfo; +import yesman.epicfight.api.ex_cap.modules.core.data.MoveSet; +import yesman.epicfight.api.ex_cap.modules.core.data.RenderModifier; import yesman.epicfight.api.utils.math.MathUtils; import yesman.epicfight.api.utils.math.OpenMatrix4f; import yesman.epicfight.api.utils.math.Vec3f; import yesman.epicfight.model.armature.types.ToolHolderArmature; import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; +import yesman.epicfight.world.capabilities.item.CapabilityItem; +import yesman.epicfight.world.capabilities.item.WeaponCapability; public class RenderItemBase { protected static final Map GLOBAL_MAINHAND_ITEM_TRANSFORMS = ImmutableMap.builder() @@ -152,9 +156,23 @@ public RenderItemBase(JsonElement jsonElement) { } } } - + public void renderItemInHand(ItemStack stack, LivingEntityPatch entitypatch, InteractionHand hand, OpenMatrix4f[] poses, MultiBufferSource buffer, PoseStack poseStack, int packedLight, float partialTicks) { - OpenMatrix4f modelMatrix = this.getCorrectionMatrix(entitypatch, hand, poses); + CapabilityItem cap = entitypatch.getHoldingItemCapability(InteractionHand.MAIN_HAND); + if (cap instanceof WeaponCapability wCap) { + MoveSet set = wCap.getCurrentSet(entitypatch); + if (set != null) { + RenderModifier modifier = set.getRenderModifier(); + if (modifier != null && modifier.modify( + this, stack, entitypatch, hand, poses, buffer, + poseStack, packedLight, partialTicks, + itemRenderer, itemInHandRenderer)) { + return; + } + } + } + + OpenMatrix4f modelMatrix = this.getCorrectionMatrix(entitypatch, hand, poses); poseStack.pushPose(); MathUtils.mulStack(poseStack, modelMatrix); ItemDisplayContext transformType = (hand == InteractionHand.MAIN_HAND) ? ItemDisplayContext.THIRD_PERSON_RIGHT_HAND : ItemDisplayContext.THIRD_PERSON_LEFT_HAND; @@ -180,12 +198,8 @@ public OpenMatrix4f getCorrectionMatrix(LivingEntityPatch entitypatch, Intera } switch (hand) { - case MAIN_HAND -> { - this.transformHolder.load(this.mainhandCorrectionTransforms.getOrDefault(parentJoint.getName(), GLOBAL_MAINHAND_ITEM_TRANSFORMS.get(parentJoint.getName()))); - } - case OFF_HAND -> { - this.transformHolder.load(this.offhandCorrectionTransforms.getOrDefault(parentJoint.getName(), GLOBAL_OFFHAND_ITEM_TRANSFORMS.get(parentJoint.getName()))); - } + case MAIN_HAND -> this.transformHolder.load(this.mainhandCorrectionTransforms.getOrDefault(parentJoint.getName(), GLOBAL_MAINHAND_ITEM_TRANSFORMS.get(parentJoint.getName()))); + case OFF_HAND -> this.transformHolder.load(this.offhandCorrectionTransforms.getOrDefault(parentJoint.getName(), GLOBAL_OFFHAND_ITEM_TRANSFORMS.get(parentJoint.getName()))); } this.transformHolder.mulFront(poses[parentJoint.getId()]); diff --git a/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderKatana.java b/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderKatana.java index 610cc7918..851eca6ae 100644 --- a/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderKatana.java +++ b/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderKatana.java @@ -12,13 +12,19 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; +import yesman.epicfight.api.ex_cap.modules.core.data.MoveSet; import yesman.epicfight.api.utils.math.MathUtils; import yesman.epicfight.api.utils.math.OpenMatrix4f; import yesman.epicfight.registry.entries.EpicFightItems; import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; +import yesman.epicfight.world.capabilities.item.WeaponCapability; public class RenderKatana extends RenderItemBase { private final ItemStack sheathStack; + + public ItemStack getSheathStack() { + return sheathStack.copy(); + } public RenderKatana(JsonElement jsonElement) { super(jsonElement); @@ -32,14 +38,13 @@ public RenderKatana(JsonElement jsonElement) { @Override public void renderItemInHand(ItemStack stack, LivingEntityPatch entitypatch, InteractionHand hand, OpenMatrix4f[] poses, MultiBufferSource buffer, PoseStack poseStack, int packedLight, float partialTicks) { - OpenMatrix4f modelMatrix = this.getCorrectionMatrix(entitypatch, InteractionHand.MAIN_HAND, poses); + OpenMatrix4f modelMatrix = this.getCorrectionMatrix(entitypatch, InteractionHand.MAIN_HAND, poses); poseStack.pushPose(); MathUtils.mulStack(poseStack, modelMatrix); itemRenderer.renderStatic(stack, ItemDisplayContext.THIRD_PERSON_RIGHT_HAND, packedLight, OverlayTexture.NO_OVERLAY, poseStack, buffer, null, 0); poseStack.popPose(); - + modelMatrix = this.getCorrectionMatrix(entitypatch, InteractionHand.OFF_HAND, poses); - poseStack.pushPose(); MathUtils.mulStack(poseStack, modelMatrix); itemRenderer.renderStatic(this.sheathStack, ItemDisplayContext.THIRD_PERSON_RIGHT_HAND, packedLight, OverlayTexture.NO_OVERLAY, poseStack, buffer, null, 0); diff --git a/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderShield.java b/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderShield.java index 8175eb0e9..2fc061ed8 100644 --- a/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderShield.java +++ b/neoforge/src/main/java/yesman/epicfight/client/renderer/patched/item/RenderShield.java @@ -20,7 +20,9 @@ public RenderShield(JsonElement jsonElement) { @Override public void renderItemInHand(ItemStack itemstack, LivingEntityPatch entitypatch, InteractionHand hand, OpenMatrix4f[] poses, MultiBufferSource buffer, PoseStack poseStack, int packedLight, float partialTicks) { - OpenMatrix4f modelMatrix = this.getCorrectionMatrix(entitypatch, hand, poses); + + + OpenMatrix4f modelMatrix = this.getCorrectionMatrix(entitypatch, hand, poses); poseStack.pushPose(); MathUtils.mulStack(poseStack, modelMatrix); ItemDisplayContext transformType = (hand == InteractionHand.MAIN_HAND) ? ItemDisplayContext.THIRD_PERSON_RIGHT_HAND : ItemDisplayContext.THIRD_PERSON_LEFT_HAND; diff --git a/neoforge/src/main/java/yesman/epicfight/gameasset/Animations.java b/neoforge/src/main/java/yesman/epicfight/gameasset/Animations.java index 7b660f836..825b16153 100644 --- a/neoforge/src/main/java/yesman/epicfight/gameasset/Animations.java +++ b/neoforge/src/main/java/yesman/epicfight/gameasset/Animations.java @@ -2373,7 +2373,7 @@ private static void moveToolBonesToHands(LivingEntityPatch entitypatch, Asset }; public static final AnimationEvent.E0 SET_TOOLS_BACK_WHEN_MOUNT = (entitypatch, animation, params) -> { - if (!entitypatch.getHoldingItemCapability(InteractionHand.MAIN_HAND).availableOnHorse() && entitypatch.getArmature() instanceof ToolHolderArmature toolArmature) { + if (!entitypatch.getHoldingItemCapability(InteractionHand.MAIN_HAND).availableOnHorse(entitypatch) && entitypatch.getArmature() instanceof ToolHolderArmature toolArmature) { moveToolBonesToBack(entitypatch, animation, toolArmature); } }; @@ -2477,7 +2477,7 @@ private static void moveToolBonesToHands(LivingEntityPatch entitypatch, Asset public static final AnimationEvent.E2 SET_TOOLS_BACK_WHEN_MOUNT_AND_ITEM_CHANGED = (entitypatch, animation, params) -> { if (entitypatch.getArmature() instanceof ToolHolderArmature humanoidArmature) { - if (!params.first().availableOnHorse()) { + if (!params.first().availableOnHorse(entitypatch)) { moveToolBonesToBack(entitypatch, animation, humanoidArmature); } else { moveToolBonesToHands(entitypatch, animation, humanoidArmature); diff --git a/neoforge/src/main/java/yesman/epicfight/main/EpicFightMod.java b/neoforge/src/main/java/yesman/epicfight/main/EpicFightMod.java index 5e3639c8a..6c06d532a 100644 --- a/neoforge/src/main/java/yesman/epicfight/main/EpicFightMod.java +++ b/neoforge/src/main/java/yesman/epicfight/main/EpicFightMod.java @@ -1,5 +1,7 @@ package yesman.epicfight.main; +import yesman.epicfight.api.ex_cap.modules.core.listeners.*; +import yesman.epicfight.api.ex_cap.modules.hooks.ExCapRegistryHooks; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -49,6 +51,7 @@ import yesman.epicfight.api.data.reloader.ItemCapabilityReloadListener; import yesman.epicfight.api.data.reloader.MobPatchReloadListener; import yesman.epicfight.api.data.reloader.SkillReloadListener; +import yesman.epicfight.api.event.EpicFightEventHooks; import yesman.epicfight.client.events.engine.IEventBasedEngine; import yesman.epicfight.client.gui.screen.SkillBookScreen; import yesman.epicfight.client.gui.screen.config.EpicFightSettingScreen; @@ -87,22 +90,16 @@ import yesman.epicfight.world.capabilities.EpicFightCapabilities; import yesman.epicfight.world.capabilities.entitypatch.Faction; import yesman.epicfight.world.capabilities.entitypatch.Factions; +import yesman.epicfight.world.capabilities.item.*; import yesman.epicfight.world.capabilities.item.CapabilityItem.Styles; import yesman.epicfight.world.capabilities.item.CapabilityItem.WeaponCategories; -import yesman.epicfight.world.capabilities.item.ItemKeywordReloadListener; -import yesman.epicfight.world.capabilities.item.Style; -import yesman.epicfight.world.capabilities.item.WeaponCategory; -import yesman.epicfight.world.capabilities.item.WeaponTypeReloadListener; import yesman.epicfight.world.capabilities.provider.CommonEntityPatchProvider; import yesman.epicfight.world.gamerule.EpicFightGameRules; import yesman.epicfight.world.item.SkillBookItem; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; @@ -148,6 +145,8 @@ public static String format(String s) { return String.format(s, MODID); } + + public static void logAndStacktraceIfDevSide(BiConsumer logFunction, String message, Function exceptionProvider) { logAndStacktraceIfDevSide(logFunction, message, exceptionProvider, message); } @@ -214,13 +213,13 @@ public EpicFightMod(IEventBus modEventBus, ModContainer modContainer) { WidgetTheme.ENUM_MANAGER.registerEnumCls(EpicFightMod.prefix("color_determinator_theme"), ColorDeterminator.Theme.class); WidgetTheme.ENUM_MANAGER.registerEnumCls(EpicFightMod.prefix("anchored_button_built_in_theme"), AnchoredButton.BuiltInTheme.class); } - EpicFightRegistries.DEFERRED_REGISTRIES.forEach(deferredRegistry -> deferredRegistry.register(modEventBus)); if (EpicFightSharedConstants.isPhysicalClient()) { modEventBus.addListener(ComputeShaderProvider::epicfight$registerComputeShaders); } loadModCompatibilityModules(modEventBus); + } private List> getCompatibilityModules(final boolean isClientSide) { @@ -307,6 +306,17 @@ private void doCommonStuff(final FMLCommonSetupEvent event) { event.enqueueWork(WeaponTypeReloadListener::registerDefaultWeaponTypes); event.enqueueWork(EpicFightMobEffects::addOffhandModifier); event.enqueueWork(EpicFightExtensibleEnums::initExtensibleEnums); + event.enqueueWork(this::addRegistries); + } + + private void addRegistries() + { + EpicFightEventHooks.Registry.EX_CAP_DATA_CREATION.registerEvent(ExCapRegistryHooks::registerData, 1); + EpicFightEventHooks.Registry.EX_CAP_BUILDER_CREATION.registerEvent(ExCapRegistryHooks::registerExCapBuilders, 1); + EpicFightEventHooks.Registry.EX_CAP_CONDITIONAL_REGISTRATION.registerEvent(ExCapRegistryHooks::registerConditionals, 1); + EpicFightEventHooks.Registry.EX_CAP_MOVESET_REGISTRY.registerEvent(ExCapRegistryHooks::registerExCapMovesets, 1); + EpicFightEventHooks.Registry.EX_CAP_DATA_POPULATION.registerEvent(ExCapRegistryHooks::registerExCapMethods, 1); + EpicFightEventHooks.Registry.WEAPON_CAPABILITY_PRESET.registerEvent(ExCapRegistryHooks::registerWeaponCapabilities, 1); } /** @@ -337,6 +347,13 @@ public void addPackFindersEvent(AddPackFindersEvent event) { private void addReloadListnerEvent(final AddReloadListenerEvent event) { event.addListener(new ColliderPreset()); event.addListener(new SkillReloadListener()); + //ExCap ------------------------------------ + event.addListener(new ExCapBuilderReloadListener()); + event.addListener(new ExCapConditionalReloadListener()); + event.addListener(new ExCapMovesetReloadListener()); + event.addListener(new ExCapDataCreationReloadListener()); + event.addListener(new ExCapDataReloadListener()); + // ----------------------------------------- event.addListener(new WeaponTypeReloadListener()); event.addListener(new ItemKeywordReloadListener()); event.addListener(new ItemCapabilityReloadListener()); diff --git a/neoforge/src/main/java/yesman/epicfight/mixin/common/MixinCrossbowAttack.java b/neoforge/src/main/java/yesman/epicfight/mixin/common/MixinCrossbowAttack.java index 1ff79493f..aed43a198 100644 --- a/neoforge/src/main/java/yesman/epicfight/mixin/common/MixinCrossbowAttack.java +++ b/neoforge/src/main/java/yesman/epicfight/mixin/common/MixinCrossbowAttack.java @@ -23,8 +23,6 @@ public abstract class MixinCrossbowAttack { private void epicfight$crossbowAttack(RangedAttackMob self, LivingEntity target, float velocity) { self.performRangedAttack(target, velocity); - EpicFightCapabilities.getUnparameterizedEntityPatch((Entity)self, LivingEntityPatch.class).ifPresent(entitypatch -> { - entitypatch.playShootingAnimation(); - }); + EpicFightCapabilities.getUnparameterizedEntityPatch((Entity)self, LivingEntityPatch.class).ifPresent(LivingEntityPatch::playShootingAnimation); } } diff --git a/neoforge/src/main/java/yesman/epicfight/mixin/common/MixinTridentAttack.java b/neoforge/src/main/java/yesman/epicfight/mixin/common/MixinTridentAttack.java new file mode 100644 index 000000000..43b5fffba --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/mixin/common/MixinTridentAttack.java @@ -0,0 +1,20 @@ +package yesman.epicfight.mixin.common; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TridentItem; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import yesman.epicfight.world.capabilities.EpicFightCapabilities; +import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; + +@Mixin(TridentItem.class) +public abstract class MixinTridentAttack { + @Inject(method = "releaseUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z", shift = At.Shift.AFTER)) + public void releaseUsing(ItemStack stack, Level level, LivingEntity entityLiving, int timeLeft, CallbackInfo ci) { + EpicFightCapabilities.getUnparameterizedEntityPatch(entityLiving, LivingEntityPatch.class).ifPresent(LivingEntityPatch::playShootingAnimation); + } +} diff --git a/neoforge/src/main/java/yesman/epicfight/registry/entries/EpicFightAttributes.java b/neoforge/src/main/java/yesman/epicfight/registry/entries/EpicFightAttributes.java index 99077da02..bd12615c5 100644 --- a/neoforge/src/main/java/yesman/epicfight/registry/entries/EpicFightAttributes.java +++ b/neoforge/src/main/java/yesman/epicfight/registry/entries/EpicFightAttributes.java @@ -16,6 +16,7 @@ import net.neoforged.neoforge.event.entity.EntityAttributeModificationEvent; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; +import yesman.epicfight.EpicFight; import yesman.epicfight.main.EpicFightMod; import yesman.epicfight.world.capabilities.entitypatch.boss.WitherGhostPatch; import yesman.epicfight.world.capabilities.entitypatch.boss.WitherPatch; @@ -58,8 +59,8 @@ private EpicFightAttributes() {} // Modifier ids for epicfight attribute public static final ResourceLocation ARMOR_NEGATION_MODIFIER = EpicFightMod.identifier("armor_negation"); - public static final ResourceLocation MAX_STRIKE_MODIFIER = EpicFightMod.identifier("max_strikes"); - public static final ResourceLocation IMPACT_MODIFIER = EpicFightMod.identifier("impact"); + public static final ResourceLocation MAX_STRIKE_MODIFIER = EpicFight.identifier("max_strikes"); + public static final ResourceLocation IMPACT_MODIFIER = EpicFight.identifier("impact"); public static final ResourceLocation ATTACK_DAMAGE_MODIFIER = EpicFightMod.identifier("attack_damage"); public static final ResourceLocation ATTACK_SPEED_MODIFIER = EpicFightMod.identifier("attack_speed"); diff --git a/neoforge/src/main/java/yesman/epicfight/skill/common/ComboAttacks.java b/neoforge/src/main/java/yesman/epicfight/skill/common/ComboAttacks.java index 42ee86545..1972f621c 100644 --- a/neoforge/src/main/java/yesman/epicfight/skill/common/ComboAttacks.java +++ b/neoforge/src/main/java/yesman/epicfight/skill/common/ComboAttacks.java @@ -124,26 +124,27 @@ public void executeOnServer(SkillContainer skillContainer, CompoundTag args) { if (player.isPassenger()) { Entity entity = player.getVehicle(); - if ((entity instanceof PlayerRideableJumping rideable && rideable.canJump()) && cap.availableOnHorse() && cap.getMountAttackMotion() != null) { - comboCounter %= cap.getMountAttackMotion().size(); - attackMotion = cap.getMountAttackMotion().get(comboCounter); + if ((entity instanceof PlayerRideableJumping rideable && rideable.canJump()) && cap.availableOnHorse(executor) && cap.getMountAttackMotion(executor) != null) { + comboCounter %= cap.getMountAttackMotion(executor).size(); + attackMotion = cap.getMountAttackMotion(executor).get(comboCounter); comboCounter++; } } else { List> combo = cap.getAutoAttackMotion(executor); - if (combo == null) { + if (combo == null || combo.isEmpty()) { return; } int comboSize = combo.size(); + //Improve array safety by doing a wrap and abs instead. if (airAttack) { - attackMotion = combo.get(comboSize - 1); + attackMotion = combo.get(Math.abs(comboSize - 1) % comboSize); } else if (dashAttack) { - attackMotion = combo.get(comboSize - 2); + attackMotion = combo.get(Math.abs(comboSize - 2) % comboSize); } else { - attackMotion = combo.get(comboCounter); + attackMotion = combo.get(Math.abs(comboCounter) % comboSize); // Grows the combo counter when doing combo attacks comboCounter = (comboCounter + 1) % (comboSize - 2); diff --git a/neoforge/src/main/java/yesman/epicfight/skill/guard/GuardSkill.java b/neoforge/src/main/java/yesman/epicfight/skill/guard/GuardSkill.java index 4d9d90804..52d06c297 100644 --- a/neoforge/src/main/java/yesman/epicfight/skill/guard/GuardSkill.java +++ b/neoforge/src/main/java/yesman/epicfight/skill/guard/GuardSkill.java @@ -57,6 +57,7 @@ import javax.annotation.Nullable; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; @@ -64,26 +65,26 @@ public class GuardSkill extends Skill implements HoldableSkill { public static class Builder extends SkillBuilder { - protected final Map, ?>> guardMotions = new HashMap<> (); - protected final Map, ?>> advancedGuardMotions = new HashMap<> (); - protected final Map, ?>> guardBreakMotions = new HashMap<> (); + protected Map, ?>> guardMotions = new HashMap<> (); + protected Map, ?>> advancedGuardMotions = new HashMap<> (); + protected Map, ?>> guardBreakMotions = new HashMap<> (); public Builder(Function constructor) { super(constructor); } - public Builder addGuardMotion(WeaponCategory weaponCategory, BiFunction, AnimationAccessor> function) { - this.guardMotions.put(weaponCategory, function); + public Builder addGuardMotion(WeaponCategory weaponCategory, BiFunction, ?> function) { + guardMotions.put(weaponCategory, function); return this; } public Builder addAdvancedGuardMotion(WeaponCategory weaponCategory, BiFunction, ?> function) { - this.advancedGuardMotions.put(weaponCategory, function); + advancedGuardMotions.put(weaponCategory, function); return this; } - public Builder addGuardBreakMotion(WeaponCategory weaponCategory, BiFunction, AnimationAccessor> function) { - this.guardBreakMotions.put(weaponCategory, function); + public Builder addGuardBreakMotion(WeaponCategory weaponCategory, BiFunction, ?> function) { + guardBreakMotions.put(weaponCategory, function); return this; } } @@ -94,7 +95,6 @@ public static GuardSkill.Builder createGuardBuilder(Function Animations.GREATSWORD_GUARD_HIT) .addGuardMotion(WeaponCategories.UCHIGATANA, (item, player) -> Animations.UCHIGATANA_GUARD_HIT) .addGuardMotion(WeaponCategories.LONGSWORD, (item, player) -> Animations.LONGSWORD_GUARD_HIT) - .addGuardMotion(WeaponCategories.SPEAR, (item, player) -> item.getStyle(player) == Styles.TWO_HAND ? Animations.SPEAR_GUARD_HIT : null) .addGuardMotion(WeaponCategories.SWORD, (item, player) -> item.getStyle(player) == Styles.ONE_HAND ? Animations.SWORD_GUARD_HIT : Animations.SWORD_DUAL_GUARD_HIT) .addGuardMotion(WeaponCategories.TACHI, (item, player) -> Animations.LONGSWORD_GUARD_HIT) .addGuardBreakMotion(WeaponCategories.AXE, (item, player) -> Animations.BIPED_COMMON_NEUTRALIZED) @@ -106,8 +106,7 @@ public static GuardSkill.Builder createGuardBuilder(Function Animations.BIPED_COMMON_NEUTRALIZED) .setCategory(SkillCategories.GUARD) .setActivateType(ActivateType.HELD) - .setResource(Resource.STAMINA) - ; + .setResource(Resource.STAMINA); } protected final Map, ?>> guardMotions; @@ -279,10 +278,7 @@ public void cancelOnClient(SkillContainer container, CompoundTag arguments) { @Override public void startHolding(SkillContainer container) { container.activate(); - - container.runOnServer(serverplayerpatch -> { - EpicFightNetworkManager.sendToAllPlayerTrackingThisEntity(SPSetSkillContainerValue.activate(container.getSlot(), true, serverplayerpatch.getOriginal().getId()), serverplayerpatch.getOriginal()); - }); + container.runOnServer(serverplayerpatch -> EpicFightNetworkManager.sendToAllPlayerTrackingThisEntity(SPSetSkillContainerValue.activate(container.getSlot(), true, serverplayerpatch.getOriginal().getId()), serverplayerpatch.getOriginal())); } @Override @@ -337,29 +333,30 @@ public boolean isHoldingWeaponAvailable(PlayerPatch playerpatch, CapabilityIt if (!guardMotions.containsKey(itemCapability.getWeaponCategory())) { return false; } - - Object motion = guardMotions.get(itemCapability.getWeaponCategory()).apply(itemCapability, playerpatch); - + + Object motion = guardMotions.get(itemCapability.getWeaponCategory()).apply(itemCapability, playerpatch); + return motion != null; } /** * Not safe from null pointer exception * Must call isAvailableState first to check if it's safe - * + * * @return AnimationAccessor */ - @SuppressWarnings("unchecked") - @Nullable + @SuppressWarnings("unchecked") + @Nullable protected AnimationAccessor getGuardMotion(SkillContainer container, PlayerPatch playerpatch, CapabilityItem itemCapability, BlockType blockType) { AnimationAccessor animation = itemCapability.getGuardMotion(this, blockType, playerpatch); if (animation != null) { return animation; } - - return (AnimationAccessor)this.getGuardMotionMap(blockType).getOrDefault(itemCapability.getWeaponCategory(), (a, b) -> null).apply(itemCapability, playerpatch); - } + + //TODO: Improve safety on the guard motions for later and deferring it to another PR. + return (AnimationAccessor)this.getGuardMotionMap(blockType).getOrDefault(itemCapability.getWeaponCategory(), (a, b) -> null).apply(itemCapability, playerpatch); + } @Override public void updateContainer(SkillContainer container) { diff --git a/neoforge/src/main/java/yesman/epicfight/skill/guard/ParryingSkill.java b/neoforge/src/main/java/yesman/epicfight/skill/guard/ParryingSkill.java index 5f19664b1..fd250a45c 100644 --- a/neoforge/src/main/java/yesman/epicfight/skill/guard/ParryingSkill.java +++ b/neoforge/src/main/java/yesman/epicfight/skill/guard/ParryingSkill.java @@ -35,14 +35,10 @@ public class ParryingSkill extends GuardSkill { public static GuardSkill.Builder createActiveGuardBuilder() { return GuardSkill.createGuardBuilder(ParryingSkill::new) - .addAdvancedGuardMotion(WeaponCategories.SWORD, (itemCap, playerpatch) -> itemCap.getStyle(playerpatch) == Styles.ONE_HAND ? - List.of(Animations.SWORD_GUARD_ACTIVE_HIT1, Animations.SWORD_GUARD_ACTIVE_HIT2) : List.of(Animations.SWORD_GUARD_ACTIVE_HIT2, Animations.SWORD_GUARD_ACTIVE_HIT3)) - .addAdvancedGuardMotion(WeaponCategories.LONGSWORD, (itemCap, playerpatch) -> - List.of(Animations.LONGSWORD_GUARD_ACTIVE_HIT1, Animations.LONGSWORD_GUARD_ACTIVE_HIT2 )) - .addAdvancedGuardMotion(WeaponCategories.UCHIGATANA, (itemCap, playerpatch) -> - List.of(Animations.SWORD_GUARD_ACTIVE_HIT1, Animations.SWORD_GUARD_ACTIVE_HIT2 )) - .addAdvancedGuardMotion(WeaponCategories.TACHI, (itemCap, playerpatch) -> - List.of(Animations.LONGSWORD_GUARD_ACTIVE_HIT1, Animations.LONGSWORD_GUARD_ACTIVE_HIT2 )); + .addAdvancedGuardMotion(WeaponCategories.SWORD, (itemCap, playerpatch) -> itemCap.getStyle(playerpatch) == Styles.ONE_HAND ? List.of(Animations.SWORD_GUARD_ACTIVE_HIT1, Animations.SWORD_GUARD_ACTIVE_HIT2) : List.of(Animations.SWORD_GUARD_ACTIVE_HIT2, Animations.SWORD_GUARD_ACTIVE_HIT3)) + .addAdvancedGuardMotion(WeaponCategories.LONGSWORD, (itemCap, playerpatch) -> List.of(Animations.LONGSWORD_GUARD_ACTIVE_HIT1, Animations.LONGSWORD_GUARD_ACTIVE_HIT2 )) + .addAdvancedGuardMotion(WeaponCategories.UCHIGATANA, (itemCap, playerpatch) -> List.of(Animations.SWORD_GUARD_ACTIVE_HIT1, Animations.SWORD_GUARD_ACTIVE_HIT2 )) + .addAdvancedGuardMotion(WeaponCategories.TACHI, (itemCap, playerpatch) -> List.of(Animations.LONGSWORD_GUARD_ACTIVE_HIT1, Animations.LONGSWORD_GUARD_ACTIVE_HIT2 )); } private int parryWindow; @@ -87,7 +83,6 @@ public void startHolding(SkillContainer skillContainer) { skillContainer.runOnServer(serverExecutor -> { int lastActive = skillContainer.getDataManager().getDataValue(EpicFightSkillDataKeys.LAST_ACTIVE); - if (serverExecutor.getOriginal().tickCount - lastActive > this.parryWindow * 2) { skillContainer.getDataManager().setDataSync(EpicFightSkillDataKeys.LAST_ACTIVE, serverExecutor.getOriginal().tickCount); } @@ -153,29 +148,27 @@ protected boolean isBlockableSource(DamageSource damageSource, boolean advanced) return (damageSource.is(DamageTypeTags.IS_PROJECTILE) && advanced) || super.isBlockableSource(damageSource, false); } - @SuppressWarnings("unchecked") @Nullable protected AnimationAccessor getGuardMotion(SkillContainer container, PlayerPatch playerpatch, CapabilityItem itemCapability, BlockType blockType) { - AnimationAccessor animation = itemCapability.getGuardMotion(this, blockType, playerpatch); - - if (animation != null) { - return animation; - } - - if (blockType == BlockType.ADVANCED_GUARD) { - List> motions = (List>)this.getGuardMotionMap(blockType).getOrDefault(itemCapability.getWeaponCategory(), (a, b) -> null).apply(itemCapability, playerpatch); - - if (motions != null) { - SkillDataManager dataManager = container.getDataManager(); - int motionCounter = dataManager.getDataValue(EpicFightSkillDataKeys.PARRY_MOTION_COUNTER); - dataManager.setDataF(EpicFightSkillDataKeys.PARRY_MOTION_COUNTER, (v) -> v + 1); - motionCounter %= motions.size(); - - return motions.get(motionCounter); - } - } - - return super.getGuardMotion(container, playerpatch, itemCapability, blockType); + if (blockType != BlockType.ADVANCED_GUARD) + { + return super.getGuardMotion(container, playerpatch, itemCapability, blockType); + } + SkillDataManager dataManager = container.getDataManager(); + AnimationAccessor result = itemCapability.getGuardMotion(this, blockType, playerpatch); + if (result == null) + { + @SuppressWarnings("unchecked") + List> motions = (List>)this.getGuardMotionMap(blockType).getOrDefault(itemCapability.getWeaponCategory(), (a, b) -> null).apply(itemCapability, playerpatch); + + if (motions != null) { + int motionCounter = dataManager.getDataValue(EpicFightSkillDataKeys.PARRY_MOTION_COUNTER); + motionCounter %= motions.size(); + result = motions.get(motionCounter); + } + } + dataManager.setDataSyncF(EpicFightSkillDataKeys.PARRY_MOTION_COUNTER, (v) -> v + 1); + return result != null ? result : super.getGuardMotion(container, playerpatch, itemCapability, blockType); } @Override diff --git a/neoforge/src/main/java/yesman/epicfight/skill/identity/RevelationSkill.java b/neoforge/src/main/java/yesman/epicfight/skill/identity/RevelationSkill.java index d58c6ed65..c85cd993e 100644 --- a/neoforge/src/main/java/yesman/epicfight/skill/identity/RevelationSkill.java +++ b/neoforge/src/main/java/yesman/epicfight/skill/identity/RevelationSkill.java @@ -28,6 +28,7 @@ import yesman.epicfight.world.capabilities.entitypatch.player.PlayerPatch; import yesman.epicfight.world.capabilities.item.CapabilityItem; import yesman.epicfight.world.capabilities.item.CapabilityItem.WeaponCategories; +import yesman.epicfight.world.capabilities.item.WeaponCapability; import yesman.epicfight.world.capabilities.item.WeaponCategory; import java.util.Map; @@ -125,9 +126,7 @@ public void onInitiate(SkillContainer skillContainer, EntityEventListener eventL eventListener.registerEvent( EpicFightEventHooks.Player.SET_TARGET, - event -> { - skillContainer.getDataManager().setDataSync(EpicFightSkillDataKeys.STACKS, 0); - }, + event -> skillContainer.getDataManager().setDataSync(EpicFightSkillDataKeys.STACKS, 0), this ); @@ -176,7 +175,10 @@ public void executeOnServer(SkillContainer container, CompoundTag arguments) { CapabilityItem holdingItem = container.getExecutor().getHoldingItemCapability(InteractionHand.MAIN_HAND); AnimationAccessor animation = this.motions.containsKey(holdingItem.getWeaponCategory()) ? this.motions.get(holdingItem.getWeaponCategory()).apply(holdingItem, container.getExecutor()) : Animations.REVELATION_ONEHAND; - + if (holdingItem instanceof WeaponCapability weaponCap) + { + animation = weaponCap.getCurrentSet(container.getServerExecutor()).getRevelation() != null ? weaponCap.getCurrentSet(container.getServerExecutor()).getRevelation() : animation; + } container.getExecutor().playAnimationSynchronized(animation, 0.0F); } diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/BowCapability.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/BowCapability.java index 3ba81744a..b2746310f 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/BowCapability.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/BowCapability.java @@ -7,11 +7,11 @@ import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; public class BowCapability extends RangedWeaponCapability { - protected BowCapability(RangedWeaponCapability.Builder builder) { + public BowCapability(RangedWeaponCapability.Builder builder) { super(builder); } - - @Override + + @Override public LivingMotion getLivingMotion(LivingEntityPatch entitypatch, InteractionHand hand) { return entitypatch.getOriginal().isUsingItem() && entitypatch.getOriginal().getUseItem().getUseAnimation() == UseAnim.BOW ? LivingMotions.AIM : null; } diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/CapabilityItem.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/CapabilityItem.java index d524b7bf9..15560f8e3 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/CapabilityItem.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/CapabilityItem.java @@ -220,9 +220,16 @@ public List> getAutoAttackMotion(Pl return getBasicAutoAttackMotions(); } - public List> getMountAttackMotion() { - return null; + public List> getMountAttackMotion(PlayerPatch playerPatch) { + return getMountAttackMotion(); } + + /// Use {@link #getMountAttackMotion(PlayerPatch)} for dynamic assigning, this is used as legacy fallback. + @Deprecated() + public List> getMountAttackMotion() + { + return null; + } @Nullable public Skill getInnateSkill(PlayerPatch playerpatch, ItemStack itemstack) { @@ -230,9 +237,16 @@ public Skill getInnateSkill(PlayerPatch playerpatch, ItemStack itemstack) { } @Nullable - public Skill getPassiveSkill() { - return null; + public Skill getPassiveSkill(PlayerPatch playerPatch) { + return getPassiveSkill(); } + + /// Use {@link #getPassiveSkill(PlayerPatch)} for dynamic allocation, this is primarily a fallback. + @Deprecated @Nullable + public Skill getPassiveSkill() + { + return null; + } public WeaponCategory getWeaponCategory() { return this.weaponCategory; @@ -258,7 +272,7 @@ public void changeWeaponInnateSkill(ServerPlayerPatch playerpatch, ItemStack ite toRemote.and(new SPSetRemotePlayerSkill(SkillSlots.WEAPON_INNATE, playerpatch.getOriginal().getId(), Skill.holderOrNull(weaponInnateSkill))); - Skill passiveSkill = this.getPassiveSkill(); + Skill passiveSkill = this.getPassiveSkill(playerpatch); SkillContainer passiveSkillContainer = playerpatch.getSkill(SkillSlots.WEAPON_PASSIVE); if (passiveSkill != null) { @@ -369,10 +383,17 @@ public CapabilityItem findRecursive(ItemStack item) { return this; } - public boolean availableOnHorse() { - return true; + public boolean availableOnHorse(LivingEntityPatch entityPatch) { + return availableOnHorse(); } - + + /// Use {@link #availableOnHorse(LivingEntityPatch)} instead for allowing living entity patch parameterization. + @Deprecated + public boolean availableOnHorse() + { + return true; + } + public boolean checkOffhandValid(LivingEntityPatch entitypatch) { return this.getStyle(entitypatch).canUseOffhand() && EpicFightCapabilities.getItemStackCapability(entitypatch.getOriginal().getOffhandItem()).canHoldInOffhandAlone(); } diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/CrossbowCapability.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/CrossbowCapability.java index 01839f560..595e40b61 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/CrossbowCapability.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/CrossbowCapability.java @@ -8,15 +8,15 @@ import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; public class CrossbowCapability extends RangedWeaponCapability { - protected CrossbowCapability(RangedWeaponCapability.Builder builder) { + public CrossbowCapability(RangedWeaponCapability.Builder builder) { super(builder); } @Override - public LivingMotion getLivingMotion(LivingEntityPatch entitypatch, InteractionHand hand) { - return entitypatch.getEntityState().canUseItem() && - entitypatch.getOriginal().getMainHandItem().getItem() instanceof ProjectileWeaponItem && - CrossbowItem.isCharged(entitypatch.getOriginal().getMainHandItem()) + public LivingMotion getLivingMotion(LivingEntityPatch entityPatch, InteractionHand interactionHand) { + return entityPatch.getEntityState().canUseItem() && + entityPatch.getOriginal().getMainHandItem().getItem() instanceof ProjectileWeaponItem && + CrossbowItem.isCharged(entityPatch.getOriginal().getMainHandItem()) ? LivingMotions.AIM : null; } } \ No newline at end of file diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/GloveCapability.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/GloveCapability.java index 1a0a29cfd..55be5ce4a 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/GloveCapability.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/GloveCapability.java @@ -8,7 +8,7 @@ public class GloveCapability extends WeaponCapability { - protected GloveCapability(WeaponCapability.Builder builder) { + public GloveCapability(WeaponCapability.Builder builder) { super(builder); } diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/RangedWeaponCapability.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/RangedWeaponCapability.java index eae19bfb4..ab9ccb71f 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/RangedWeaponCapability.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/RangedWeaponCapability.java @@ -11,63 +11,58 @@ import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; public class RangedWeaponCapability extends CapabilityItem { - protected Map> rangeAnimationModifiers; - protected ZoomInType zoomInType; - - protected RangedWeaponCapability(RangedWeaponCapability.Builder builder) { - super(builder); - - RangedWeaponCapability.Builder rangedBuilder = (RangedWeaponCapability.Builder)builder; - this.rangeAnimationModifiers = rangedBuilder.rangeAnimationModifiers; - this.zoomInType = rangedBuilder.zoomInType; - } - - @Override - public Map> getLivingMotionModifier(LivingEntityPatch playerdata, InteractionHand hand) { - if (hand == InteractionHand.MAIN_HAND) { - return this.rangeAnimationModifiers; - } - - return super.getLivingMotionModifier(playerdata, hand); - } + protected Map> rangeAnimationModifiers; + protected ZoomInType zoomInType; - @Override - public boolean availableOnHorse() { - return true; - } - - @Override - public boolean canBePlacedOffhand() { - return false; - } - - @Override - public ZoomInType getZoomInType() { - return this.zoomInType; - } - - public static RangedWeaponCapability.Builder builder() { - return new RangedWeaponCapability.Builder(); - } - - public static class Builder extends CapabilityItem.Builder { - private Map> rangeAnimationModifiers; - private ZoomInType zoomInType = ZoomInType.USE_TICK; - - protected Builder() { - this.category = WeaponCategories.RANGED; - this.constructor = RangedWeaponCapability::new; - this.rangeAnimationModifiers = Maps.newHashMap(); - } - - public Builder addAnimationsModifier(LivingMotion livingMotion, AnimationAccessor animations) { - this.rangeAnimationModifiers.put(livingMotion, animations); - return this; - } - - public Builder zoomInType(ZoomInType zoomInType) { - this.zoomInType = zoomInType; - return this; - } - } + protected RangedWeaponCapability(RangedWeaponCapability.Builder builder) { + super(builder); + + RangedWeaponCapability.Builder rangedBuilder = builder; + this.rangeAnimationModifiers = rangedBuilder.rangeAnimationModifiers; + this.zoomInType = rangedBuilder.zoomInType; + } + + @Override + public Map> getLivingMotionModifier(LivingEntityPatch playerdata, InteractionHand hand) { + if (hand == InteractionHand.MAIN_HAND) { + return this.rangeAnimationModifiers; + } + + return super.getLivingMotionModifier(playerdata, hand); + } + + @Override + public boolean canBePlacedOffhand() { + return false; + } + + @Override + public ZoomInType getZoomInType() { + return this.zoomInType; + } + + public static RangedWeaponCapability.Builder builder() { + return new RangedWeaponCapability.Builder(); + } + + public static class Builder extends CapabilityItem.Builder { + private Map> rangeAnimationModifiers; + private ZoomInType zoomInType = ZoomInType.USE_TICK; + + protected Builder() { + this.category = WeaponCategories.RANGED; + this.constructor = RangedWeaponCapability::new; + this.rangeAnimationModifiers = Maps.newHashMap(); + } + + public Builder addAnimationsModifier(LivingMotion livingMotion, AnimationAccessor animations) { + this.rangeAnimationModifiers.put(livingMotion, animations); + return this; + } + + public Builder zoomInType(ZoomInType zoomInType) { + this.zoomInType = zoomInType; + return this; + } + } } \ No newline at end of file diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/ShieldCapability.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/ShieldCapability.java index 740f304d4..c851acca7 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/ShieldCapability.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/ShieldCapability.java @@ -13,8 +13,8 @@ import yesman.epicfight.gameasset.Animations; import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; -public class ShieldCapability extends CapabilityItem { - protected ShieldCapability(CapabilityItem.Builder builder) { +public class ShieldCapability extends WeaponCapability { + public ShieldCapability(WeaponCapability.Builder builder) { super(builder); } @@ -22,10 +22,10 @@ protected ShieldCapability(CapabilityItem.Builder builder) { * Avoid duplicated usage with guard skill */ @Override - public UseAnim getUseAnimation(LivingEntityPatch entitypatch) { + public UseAnim getUseAnimation(LivingEntityPatch entityPatch) { return UseAnim.NONE; } - + @Override public Map> getLivingMotionModifier(LivingEntityPatch playerdata, InteractionHand hand) { return ImmutableMap.of(LivingMotions.BLOCK_SHIELD, Animations.BIPED_BLOCK); diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/StyleManager.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/StyleManager.java new file mode 100644 index 000000000..7e08f9b76 --- /dev/null +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/StyleManager.java @@ -0,0 +1,13 @@ +package yesman.epicfight.world.capabilities.item; + +import net.minecraft.resources.ResourceLocation; + +import java.util.Map; + +/** + * This class is meant to be the prototype of a new class that aims to replace ExtensibleEnum into a RL/Identifier + */ +public class StyleManager +{ + public static Map styleMap; +} diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/TridentCapability.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/TridentCapability.java index 2fc8da980..555113f2b 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/TridentCapability.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/TridentCapability.java @@ -6,7 +6,7 @@ import net.minecraft.world.item.UseAnim; import net.minecraft.world.item.enchantment.Enchantments; import org.jetbrains.annotations.NotNull; -import yesman.epicfight.api.animation.AnimationManager.AnimationAccessor; +import yesman.epicfight.api.animation.AnimationManager; import yesman.epicfight.api.animation.LivingMotion; import yesman.epicfight.api.animation.LivingMotions; import yesman.epicfight.api.animation.types.AttackAnimation; @@ -23,57 +23,57 @@ import java.util.List; public class TridentCapability extends RangedWeaponCapability { - private List> attackMotion; - private List> mountAttackMotion; - - public TridentCapability(RangedWeaponCapability.Builder builder) { - super(builder); - - this.attackMotion = List.of(Animations.TRIDENT_AUTO1, Animations.TRIDENT_AUTO2, Animations.TRIDENT_AUTO3, Animations.SPEAR_DASH, Animations.SPEAR_ONEHAND_AIR_SLASH); - this.mountAttackMotion = List.of(Animations.SPEAR_MOUNT_ATTACK); - } - - @Override @NotNull - public Style getStyle(LivingEntityPatch entitypatch) { - return Styles.ONE_HAND; - } - - @Override - public SoundEvent getHitSound() { - return EpicFightSounds.BLADE_HIT.get(); - } - - @Override - public HitParticleType getHitParticle() { - return EpicFightParticles.HIT_BLADE.get(); - } - - @Override - public List> getAutoAttackMotion(PlayerPatch playerpatch) { - return this.attackMotion; - } - - @Override - public List> getMountAttackMotion() { - return this.mountAttackMotion; - } - - @Override - public LivingMotion getLivingMotion(LivingEntityPatch entitypatch, InteractionHand hand) { - return entitypatch.getOriginal().isUsingItem() && entitypatch.getOriginal().getUseItem().getUseAnimation() == UseAnim.SPEAR ? LivingMotions.AIM : null; - } - - @Nullable - @Override - public Skill getInnateSkill(PlayerPatch playerpatch, ItemStack itemstack) { - if (itemstack.getEnchantmentLevel(playerpatch.getLevel().holderOrThrow(Enchantments.RIPTIDE)) > 0) { - return EpicFightSkills.TSUNAMI.get(); - } else if (itemstack.getEnchantmentLevel(playerpatch.getLevel().holderOrThrow(Enchantments.CHANNELING)) > 0) { - return EpicFightSkills.WRATHFUL_LIGHTING.get(); - } else if (itemstack.getEnchantmentLevel(playerpatch.getLevel().holderOrThrow(Enchantments.LOYALTY)) > 0) { - return EpicFightSkills.EVERLASTING_ALLEGIANCE.get(); - } else { - return null; - } - } + private List> attackMotion; + private List> mountAttackMotion; + + public TridentCapability(RangedWeaponCapability.Builder builder) { + super(builder); + + this.attackMotion = List.of(Animations.TRIDENT_AUTO1, Animations.TRIDENT_AUTO2, Animations.TRIDENT_AUTO3, Animations.SPEAR_DASH, Animations.SPEAR_ONEHAND_AIR_SLASH); + this.mountAttackMotion = List.of(Animations.SPEAR_MOUNT_ATTACK); + } + + @Override @NotNull + public Style getStyle(LivingEntityPatch entitypatch) { + return Styles.ONE_HAND; + } + + @Override + public SoundEvent getHitSound() { + return EpicFightSounds.BLADE_HIT.get(); + } + + @Override + public HitParticleType getHitParticle() { + return EpicFightParticles.HIT_BLADE.get(); + } + + @Override + public List> getAutoAttackMotion(PlayerPatch playerpatch) { + return this.attackMotion; + } + + @Override + public List> getMountAttackMotion(PlayerPatch livingentitypatch) { + return this.mountAttackMotion; + } + + @Override + public LivingMotion getLivingMotion(LivingEntityPatch entitypatch, InteractionHand hand) { + return entitypatch.getOriginal().isUsingItem() && entitypatch.getOriginal().getUseItem().getUseAnimation() == UseAnim.SPEAR ? LivingMotions.AIM : null; + } + + @Nullable + @Override + public Skill getInnateSkill(PlayerPatch playerpatch, ItemStack itemstack) { + if (itemstack.getEnchantmentLevel(playerpatch.getLevel().holderOrThrow(Enchantments.RIPTIDE)) > 0) { + return EpicFightSkills.TSUNAMI.get(); + } else if (itemstack.getEnchantmentLevel(playerpatch.getLevel().holderOrThrow(Enchantments.CHANNELING)) > 0) { + return EpicFightSkills.WRATHFUL_LIGHTING.get(); + } else if (itemstack.getEnchantmentLevel(playerpatch.getLevel().holderOrThrow(Enchantments.LOYALTY)) > 0) { + return EpicFightSkills.EVERLASTING_ALLEGIANCE.get(); + } else { + return null; + } + } } \ No newline at end of file diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponCapability.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponCapability.java index 352fd4de0..7903c6576 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponCapability.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponCapability.java @@ -3,12 +3,21 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import io.netty.util.internal.StringUtil; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.TagParser; +import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.UseAnim; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import yesman.epicfight.EpicFight; import yesman.epicfight.api.animation.AnimationManager; import yesman.epicfight.api.animation.AnimationManager.AnimationAccessor; import yesman.epicfight.api.animation.LivingMotion; @@ -17,27 +26,41 @@ import yesman.epicfight.api.animation.types.MainFrameAnimation; import yesman.epicfight.api.animation.types.StaticAnimation; import yesman.epicfight.api.event.types.player.ModifyComboCounter; -import yesman.epicfight.main.EpicFightMod; +import yesman.epicfight.gameasset.ColliderPreset; import yesman.epicfight.particle.HitParticleType; -import yesman.epicfight.registry.entries.EpicFightParticles; -import yesman.epicfight.registry.entries.EpicFightSounds; +import yesman.epicfight.registry.entries.*; import yesman.epicfight.skill.Skill; +import yesman.epicfight.skill.SkillContainer; +import yesman.epicfight.skill.SkillSlots; +import yesman.epicfight.skill.guard.GuardSkill; import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; import yesman.epicfight.world.capabilities.entitypatch.player.PlayerPatch; +import yesman.epicfight.api.ex_cap.modules.core.data.MoveSet; +import yesman.epicfight.api.ex_cap.modules.core.provider.CoreWeaponCapabilityProvider; +import yesman.epicfight.api.ex_cap.modules.core.provider.ProviderConditional; import java.util.List; import java.util.Map; import java.util.function.Function; public class WeaponCapability extends CapabilityItem { + protected final CoreWeaponCapabilityProvider coreProvider; + @Deprecated protected final Function, Style> stylegetter; + @Deprecated protected final Function, Boolean> weaponCombinationPredicator; + @Deprecated protected final Skill passiveSkill; + protected final boolean offHandAlone; protected final SoundEvent smashingSound; protected final SoundEvent hitSound; protected final HitParticleType hitParticle; + protected final Map moveSets; + @Deprecated protected final Map>> autoAttackMotions; + @Deprecated protected final Map> innateSkill; + @Deprecated protected final Map>> livingMotionModifiers; protected final boolean canBePlacedOffhand; @Deprecated @@ -48,49 +71,134 @@ public class WeaponCapability extends CapabilityItem { protected WeaponCapability(WeaponCapability.Builder builder) { super(builder); - - WeaponCapability.Builder weaponBuilder = (WeaponCapability.Builder)builder; - - this.autoAttackMotions = weaponBuilder.autoAttackMotionMap; - this.innateSkill = weaponBuilder.innateSkillByStyle; - this.livingMotionModifiers = weaponBuilder.livingMotionModifiers; - this.stylegetter = weaponBuilder.styleProvider; - this.weaponCombinationPredicator = weaponBuilder.weaponCombinationPredicator; - this.passiveSkill = weaponBuilder.passiveSkill; - this.smashingSound = weaponBuilder.swingSound; - this.hitParticle = weaponBuilder.hitParticle; - this.hitSound = weaponBuilder.hitSound; - this.canBePlacedOffhand = weaponBuilder.canBePlacedOffhand; - this.comboCancel = weaponBuilder.comboCancel; - this.comboCounterHandler = weaponBuilder.comboCounterHandler; - this.zoomInType = weaponBuilder.zoomInType; - this.reach = weaponBuilder.reach; + this.coreProvider = builder.provider; + this.moveSets = builder.moveSets; + this.offHandAlone = builder.offHandAlone; + this.autoAttackMotions = builder.autoAttackMotionMap; + this.innateSkill = builder.innateSkillByStyle; + this.livingMotionModifiers = builder.livingMotionModifiers; + this.stylegetter = builder.styleProvider; + this.weaponCombinationPredicator = builder.weaponCombinationPredicator; + this.passiveSkill = builder.passiveSkill; + this.smashingSound = builder.swingSound; + this.hitParticle = builder.hitParticle; + this.hitSound = builder.hitSound; + this.canBePlacedOffhand = builder.canBePlacedOffhand; + this.comboCancel = builder.comboCancel; + this.comboCounterHandler = builder.comboCounterHandler; + this.zoomInType = builder.zoomInType; + this.reach = builder.reach; } - - @Override + + + + public MoveSet getCurrentSet(LivingEntityPatch patch) + { + Style style = getStyle(patch); + return moveSets.getOrDefault(style, moveSets.get(Styles.COMMON)); + } + + private AnimationAccessor processGuard(List> motions, GuardSkill.BlockType blockType, PlayerPatch playerpatch, SkillContainer container, int counter) + { + if (!motions.isEmpty()) { + AnimationAccessor result = motions.get(counter % motions.size()); + if (blockType == GuardSkill.BlockType.ADVANCED_GUARD && !playerpatch.isLogicalClient()) { + result = motions.get(container.getDataManager().getDataValue(EpicFightSkillDataKeys.PARRY_MOTION_COUNTER) % motions.size()); + container.getDataManager().setDataSyncF(EpicFightSkillDataKeys.PARRY_MOTION_COUNTER, count -> count + 1); + } + return result; + } + return null; + } + + @Override + public AnimationAccessor getGuardMotion(GuardSkill skill, GuardSkill.BlockType blockType, PlayerPatch playerpatch) + { + MoveSet currentSet = getCurrentSet(playerpatch); + SkillContainer container = playerpatch.getSkill(SkillSlots.GUARD); + int counter = blockType == GuardSkill.BlockType.ADVANCED_GUARD && container.getDataManager().hasData(EpicFightSkillDataKeys.PARRY_MOTION_COUNTER) ? container.getDataManager().getDataValue(EpicFightSkillDataKeys.PARRY_MOTION_COUNTER) : 0; + if (currentSet != null) { + Map>>> skillSpecificGuardMotions = currentSet.getSkillSpecificGuardAnimations(); + Map>> defaultGuardMotions = currentSet.getDefaultGuardAnimations(); + if (skillSpecificGuardMotions != null && skillSpecificGuardMotions.containsKey(skill) && skillSpecificGuardMotions.get(skill).containsKey(blockType)) { + List> motions = skillSpecificGuardMotions.get(skill).get(blockType); + return processGuard(motions, blockType, playerpatch, container, counter); + } else if (defaultGuardMotions != null && defaultGuardMotions.containsKey(blockType)) { + List> motions = defaultGuardMotions.get(blockType); + return processGuard(motions, blockType, playerpatch, container, counter); + } + } + return super.getGuardMotion(skill, blockType, playerpatch); + } + + @Override public final List> getAutoAttackMotion(PlayerPatch playerpatch) { - return this.autoAttackMotions.getOrDefault(this.getStyle(playerpatch), this.autoAttackMotions.get(Styles.COMMON)); + MoveSet set = getCurrentSet(playerpatch); + if (set == null) { + //Fallback + List> attacks = autoAttackMotions.getOrDefault(getStyle(playerpatch), autoAttackMotions.get(Styles.COMMON)); + if (attacks == null || attacks.isEmpty()) { + return super.getAutoAttackMotion(playerpatch); + } + return attacks; + } + return set.getComboAttackAnimations(); } @Override public final Skill getInnateSkill(PlayerPatch playerpatch, ItemStack itemstack) { - Function innateProvider = this.innateSkill.getOrDefault(this.getStyle(playerpatch), this.innateSkill.get(Styles.COMMON)); - return innateProvider == null ? null : innateProvider.apply(itemstack); + MoveSet set = getCurrentSet(playerpatch); + if (set == null) { + //Fallback Logic + if (innateSkill.get(getStyle(playerpatch)) == null) + return null; + return innateSkill.get(getStyle(playerpatch)).apply(itemstack); + } + return set.getWeaponInnateSkill() == null ? null : set.getWeaponInnateSkill().apply(itemstack, playerpatch); } @Override - public Skill getPassiveSkill() { - return this.passiveSkill; + public Skill getPassiveSkill(PlayerPatch playerPatch) { + MoveSet set = getCurrentSet(playerPatch); + if (set == null) { + //Fallback logic + return getPassiveSkill(); + } + return set.getWeaponPassiveSkill(); } - + + /// Legacy method + public Skill getPassiveSkill() + { + return passiveSkill; + } + @Override - public final List> getMountAttackMotion() { - return this.autoAttackMotions.get(Styles.MOUNT); - } + public final List> getMountAttackMotion(PlayerPatch playerpatch) { + MoveSet set = getCurrentSet(playerpatch); + if (set == null) { + //Fallback logic + return this.autoAttackMotions.get(Styles.MOUNT); + } + return set.getMountAttackAnimations(); + } + + /// Legacy method used by addons + @Deprecated + public final List> getMountAttackMotion() + { + return this.autoAttackMotions.get(Styles.MOUNT); + } @Override @NotNull - public Style getStyle(LivingEntityPatch entitypatch) { - return this.stylegetter.apply(entitypatch); + public Style getStyle(LivingEntityPatch entityPatch) { + Style style = coreProvider.getStyle(entityPatch); + if (style == null) + { + //Fallback + return this.stylegetter.apply(entityPatch); + } + return style; } @Override @@ -127,67 +235,115 @@ public int handleComboCounter(ModifyComboCounter.Causal causal, PlayerPatch e public ZoomInType getZoomInType() { return this.zoomInType; } - - @Override + + @Override public Map> getLivingMotionModifier(LivingEntityPatch player, InteractionHand hand) { - if (this.livingMotionModifiers == null || hand == InteractionHand.OFF_HAND) { - return super.getLivingMotionModifier(player, hand); - } - - Map> motions = this.livingMotionModifiers.getOrDefault(this.getStyle(player), Maps.newHashMap()); - this.livingMotionModifiers.getOrDefault(Styles.COMMON, Maps.newHashMap()).forEach(motions::putIfAbsent); - - return motions; + MoveSet set = getCurrentSet(player); + if (set == null || set.getLivingMotionModifiers() == null) + { + //Fallback to legacy + if (this.livingMotionModifiers == null || hand == InteractionHand.OFF_HAND) { + return super.getLivingMotionModifier(player, hand); + } + Map> motions = this.livingMotionModifiers.getOrDefault(this.getStyle(player), Maps.newHashMap()); + this.livingMotionModifiers.getOrDefault(Styles.COMMON, Maps.newHashMap()).forEach(motions::putIfAbsent); + + return motions; + } + Map> result = Maps.newHashMap(); + result.putAll(set.getLivingMotionModifiers()); + return result; } @Override - public UseAnim getUseAnimation(LivingEntityPatch entitypatch) { - if (this.livingMotionModifiers != null) { - Style style = this.getStyle(entitypatch); - - if (this.livingMotionModifiers.containsKey(style)) { - if (this.livingMotionModifiers.get(style).containsKey(LivingMotions.BLOCK)) { - return UseAnim.BLOCK; - } - } - } - + public UseAnim getUseAnimation(LivingEntityPatch entityPatch) { + MoveSet set = getCurrentSet(entityPatch); + if (set == null || set.getLivingMotionModifiers() == null) + { + //Fallback + if (this.livingMotionModifiers != null) { + Style style = this.getStyle(entityPatch); + if (this.livingMotionModifiers.containsKey(style)) { + if (this.livingMotionModifiers.get(style).containsKey(LivingMotions.BLOCK)) { + return UseAnim.BLOCK; + } + } + } + } + else if (set.getLivingMotionModifiers().containsKey(LivingMotions.BLOCK)) { + return UseAnim.BLOCK; + } return UseAnim.NONE; } @Override public boolean canHoldInOffhandAlone() { - return false; + return offHandAlone; } @Override public boolean checkOffhandValid(LivingEntityPatch entitypatch) { - return super.checkOffhandValid(entitypatch) || this.weaponCombinationPredicator.apply(entitypatch); + Boolean valid = coreProvider.checkVisibleOffHand(entitypatch); + if (valid == null) { + valid = super.checkOffhandValid(entitypatch) || weaponCombinationPredicator.apply(entitypatch); + } else { + valid = valid || super.checkOffhandValid(entitypatch); + } + return valid; } @Override - public boolean availableOnHorse() { - return this.autoAttackMotions.containsKey(Styles.MOUNT); + public boolean availableOnHorse(LivingEntityPatch entityPatch) { + MoveSet set = getCurrentSet(entityPatch); + if (set == null || set.getMountAttackAnimations() == null || set.getMountAttackAnimations().isEmpty()) + return availableOnHorse(); + return true; } - - @Override + + @Override + public boolean availableOnHorse() { + return this.autoAttackMotions.containsKey(Styles.MOUNT); + } + + @Override public float getReach() { return this.reach; } public static WeaponCapability.Builder builder() { - return new WeaponCapability.Builder(); + return new Builder(); } - - public static class Builder extends CapabilityItem.Builder { - Function, Style> styleProvider; + + @Override + public LivingMotion getLivingMotion(LivingEntityPatch entitypatch, InteractionHand hand) { + MoveSet set = getCurrentSet(entitypatch); + if (set == null || set.getCustomMotion().apply(entitypatch, hand) == null) + return super.getLivingMotion(entitypatch, hand); + return set.getCustomMotion().apply(entitypatch, hand); + } + + /// All fields marked with {@link Deprecated} have been moved to {@link MoveSet} and exist as legacy fallback options to prevent addons from breaking. + public static class Builder extends CapabilityItem.Builder { + CoreWeaponCapabilityProvider provider; + @Deprecated + Function, Style> styleProvider; + @Deprecated Function, Boolean> weaponCombinationPredicator; + @Deprecated Skill passiveSkill; SoundEvent swingSound; SoundEvent hitSound; HitParticleType hitParticle; + Map moveSets; + double baseAP; + double aPScaling; + double impactBase; + double impactScaling; + @Deprecated Map>> autoAttackMotionMap; + @Deprecated Map> innateSkillByStyle; + @Deprecated Map>> livingMotionModifiers; @Deprecated Function comboCancel; @@ -195,14 +351,77 @@ public static class Builder extends CapabilityItem.Builder>> entry + : this.autoAttackMotionMap.entrySet()) { + + copy.autoAttackMotionMap.put( + entry.getKey(), + Lists.newArrayList(entry.getValue()) + ); + } + } + + if (this.innateSkillByStyle != null) { + copy.innateSkillByStyle = Maps.newHashMap(this.innateSkillByStyle); + } + + if (this.livingMotionModifiers != null) { + copy.livingMotionModifiers = Maps.newHashMap(); + + for (Map.Entry>> entry + : this.livingMotionModifiers.entrySet()) { + + copy.livingMotionModifiers.put( + entry.getKey(), + Maps.newHashMap(entry.getValue()) + ); + } + } + return copy; + } protected Builder() { + this.provider = new CoreWeaponCapabilityProvider(); + this.offHandAlone = false; this.constructor = WeaponCapability::new; this.styleProvider = (entitypatch) -> Styles.ONE_HAND; this.weaponCombinationPredicator = (entitypatch) -> false; this.passiveSkill = null; this.swingSound = EpicFightSounds.WHOOSH.get(); this.hitSound = EpicFightSounds.BLUNT_HIT.get(); + this.moveSets = Maps.newHashMap(); this.hitParticle = EpicFightParticles.HIT_BLADE.get(); this.autoAttackMotionMap = Maps.newHashMap(); this.innateSkillByStyle = Maps.newHashMap(); @@ -212,12 +431,40 @@ protected Builder() { this.comboCounterHandler = ModifyComboCounter.ComboCounterHandler.DEFAULT_COMBO_HANDLER; this.zoomInType = ZoomInType.NONE; this.reach = 0.2F; + this.baseAP = 0; + this.aPScaling = 1; + this.impactBase = 1; + this.impactScaling = 1; } + + public Builder offHandAlone(final boolean offHandAlone) { + this.offHandAlone = offHandAlone; + return this; + } public Builder styleProvider(Function, Style> styleProvider) { this.styleProvider = styleProvider; return this; } + + public Builder setTierValues(double baseAP, double aPScaling, double impactBase, double impactScaling) + { + this.baseAP = baseAP; + this.aPScaling = aPScaling; + this.impactBase = impactBase; + this.impactScaling = impactScaling; + return this; + } + + /** + * This is not to be called statically and only called during registration. + * @param tier the tier value used by Yesman + */ + public void modifyTierAttributes(int tier) + { + if (tier != 0) this.addStyleAttibutes(Styles.COMMON, EpicFightAttributes.ARMOR_NEGATION, EpicFightAttributes.getArmorNegationModifier(baseAP + aPScaling * tier)); + this.addStyleAttibutes(Styles.COMMON, EpicFightAttributes.IMPACT, EpicFightAttributes.getImpactModifier(impactBase + impactScaling * tier)); + } public Builder passiveSkill(Skill passiveSkill) { this.passiveSkill = passiveSkill; @@ -228,6 +475,18 @@ public Builder swingSound(SoundEvent swingSound) { this.swingSound = swingSound; return this; } + + public Builder addConditionals(ProviderConditional... conditionals) + { + provider.addConditional(conditionals); + return this; + } + + public Builder addConditionals(List conditionals) + { + provider.addConditional(conditionals); + return this; + } public Builder hitSound(SoundEvent hitSound) { this.hitSound = hitSound; @@ -238,6 +497,11 @@ public Builder hitParticle(HitParticleType hitParticle) { this.hitParticle = hitParticle; return this; } + + public Builder addMoveSet(Style style, MoveSet.MoveSetBuilder moveSet) { + moveSets.put(style, moveSet.build()); + return this; + } public Builder canBePlacedOffhand(boolean canBePlacedOffhand) { this.canBePlacedOffhand = canBePlacedOffhand; @@ -248,10 +512,45 @@ public Builder reach(float reach) { this.reach = reach; return this; } + + public static WeaponCapability.Builder deserializeBuilder(JsonElement element) throws JsonParseException + { + WeaponCapability.Builder builder = builder(); + JsonObject tag = element.getAsJsonObject(); + + //Unlike the Legacy WeaponType deserialization method, this is much more simple and strict. + + try { + if (!tag.has("category") || StringUtil.isNullOrEmpty(tag.get("category").getAsString())) { + throw new IllegalArgumentException("Define weapon category."); + } + + builder.category(WeaponCategory.ENUM_MANAGER.getOrThrow(tag.get("category").getAsString())); + builder.collider(ColliderPreset.deserializeSimpleCollider(TagParser.parseTag(tag.get("collider").getAsString()))); + + if (tag.has("hit_particle")) { + ParticleType particleType = BuiltInRegistries.PARTICLE_TYPE.get(ResourceLocation.parse(tag.get("hit_particle").getAsString())); + builder.hitParticle((HitParticleType)particleType); + } + + if (tag.has("swing_sound")) { + SoundEvent sound = BuiltInRegistries.SOUND_EVENT.get(ResourceLocation.parse(tag.get("swing_sound").getAsString())); + builder.swingSound(sound); + } + + if (tag.has("hit_sound")) { + SoundEvent sound = BuiltInRegistries.SOUND_EVENT.get(ResourceLocation.parse(tag.get("hit_sound").getAsString())); + builder.hitSound(sound); + } + } catch (Exception e) { + throw new JsonParseException(e.getMessage()); + } + return builder; + } public Builder livingMotionModifier(Style wieldStyle, LivingMotion livingMotion, AnimationAccessor animation) { if (AnimationManager.checkNull(animation)) { - EpicFightMod.LOGGER.warn("Unable to put an empty animation to weapon capability builder: " + livingMotion + ", " + animation); + EpicFight.LOGGER.warn("Unable to put an empty animation to weapon capability builder: {}, {}", livingMotion, animation); return this; } diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponCapabilityPresets.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponCapabilityPresets.java index bb1e11f5c..f8d1b7933 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponCapabilityPresets.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponCapabilityPresets.java @@ -1,396 +1,53 @@ package yesman.epicfight.world.capabilities.item; -import java.util.function.Function; - -import net.minecraft.world.InteractionHand; +import com.google.common.collect.Lists; +import yesman.epicfight.api.ex_cap.modules.core.data.ExCapData; +import yesman.epicfight.api.ex_cap.modules.core.managers.DatasetManager; +import yesman.epicfight.api.ex_cap.modules.core.managers.ExCapManager; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.Tier; import net.minecraft.world.item.TieredItem; import net.minecraft.world.item.Tiers; -import yesman.epicfight.api.animation.LivingMotions; -import yesman.epicfight.gameasset.Animations; -import yesman.epicfight.gameasset.ColliderPreset; -import yesman.epicfight.registry.entries.EpicFightAttributes; -import yesman.epicfight.registry.entries.EpicFightParticles; -import yesman.epicfight.registry.entries.EpicFightSkillDataKeys; -import yesman.epicfight.registry.entries.EpicFightSkills; -import yesman.epicfight.registry.entries.EpicFightSounds; -import yesman.epicfight.skill.SkillSlots; -import yesman.epicfight.world.capabilities.EpicFightCapabilities; -import yesman.epicfight.world.capabilities.entitypatch.player.PlayerPatch; -import yesman.epicfight.world.capabilities.item.CapabilityItem.Styles; -import yesman.epicfight.world.capabilities.item.CapabilityItem.WeaponCategories; -import yesman.epicfight.world.capabilities.item.CapabilityItem.ZoomInType; +import yesman.epicfight.EpicFight; + +import java.util.List; +import java.util.Map; public abstract class WeaponCapabilityPresets { public static int vanillaTierToLevel(Tier tier) { if (tier instanceof Tiers vanillaTier) { switch (vanillaTier) { - case WOOD -> {return 0;} - case STONE -> {return 1;} - case IRON -> {return 2;} - case DIAMOND -> {return 3;} - case GOLD -> {return 0;} - case NETHERITE -> {return 4;} + case WOOD, GOLD -> {return 0;} + case STONE -> {return 1;} + case IRON -> {return 2;} + case DIAMOND -> {return 3;} + case NETHERITE -> {return 4;} } } - double sqrt = Math.sqrt(tier.getUses()); - + // Custom tier mapping return sqrt < 10.0D ? 0 : (int)Math.round(sqrt / 10.0D); } - - public static final Function AXE = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.AXE) - .hitSound(EpicFightSounds.BLADE_HIT.get()) - .collider(ColliderPreset.TOOLS) - .newStyleCombo(Styles.ONE_HAND, Animations.AXE_AUTO1, Animations.AXE_AUTO2, Animations.AXE_DASH, Animations.AXE_AIRSLASH) - .newStyleCombo(Styles.MOUNT, Animations.SWORD_MOUNT_ATTACK) - .innateSkill(Styles.ONE_HAND, (itemstack) -> EpicFightSkills.THE_GUILLOTINE.get()) - .livingMotionModifier(Styles.ONE_HAND, LivingMotions.BLOCK, Animations.SWORD_GUARD); - - if (item instanceof TieredItem tieredItem) { - int tierLevel = vanillaTierToLevel(tieredItem.getTier()); - - if (tierLevel != 0) { - builder.addStyleAttibutes(CapabilityItem.Styles.COMMON, EpicFightAttributes.ARMOR_NEGATION, EpicFightAttributes.getArmorNegationModifier(10.0D * tierLevel)); - } - - builder.addStyleAttibutes(CapabilityItem.Styles.COMMON, EpicFightAttributes.IMPACT, EpicFightAttributes.getImpactModifier(0.7D + 0.3D * tierLevel)); - } - - return builder; - }; - - public static final Function HOE = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.HOE) - .hitSound(EpicFightSounds.BLADE_HIT.get()) - .collider(ColliderPreset.TOOLS).newStyleCombo(Styles.ONE_HAND, Animations.TOOL_AUTO1, Animations.TOOL_AUTO2, Animations.TOOL_DASH, Animations.SWORD_AIR_SLASH) - .newStyleCombo(Styles.MOUNT, Animations.SWORD_MOUNT_ATTACK); - - if (item instanceof TieredItem tieredItem) { - int tierLevel = vanillaTierToLevel(tieredItem.getTier());; - builder.addStyleAttibutes(CapabilityItem.Styles.COMMON, EpicFightAttributes.IMPACT, EpicFightAttributes.getImpactModifier(-0.4D + 0.1D * tierLevel)); - } - - return builder; - }; - - public static final Function PICKAXE = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.PICKAXE) - .hitSound(EpicFightSounds.BLADE_HIT.get()) - .collider(ColliderPreset.TOOLS) - .newStyleCombo(Styles.ONE_HAND, Animations.AXE_AUTO1, Animations.AXE_AUTO2, Animations.AXE_DASH, Animations.AXE_AIRSLASH) - .newStyleCombo(Styles.MOUNT, Animations.SWORD_MOUNT_ATTACK); - - if (item instanceof TieredItem tieredItem) { - int tierLevel = vanillaTierToLevel(tieredItem.getTier());; - - if (tierLevel != 0) { - builder.addStyleAttibutes(CapabilityItem.Styles.COMMON, EpicFightAttributes.ARMOR_NEGATION, EpicFightAttributes.getArmorNegationModifier(6.0D * tierLevel)); - } - - builder.addStyleAttibutes(CapabilityItem.Styles.COMMON, EpicFightAttributes.IMPACT, EpicFightAttributes.getImpactModifier(0.4D + 0.1D * tierLevel)); - } - - return builder; - }; - - public static final Function SHOVEL = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.SHOVEL) - .collider(ColliderPreset.TOOLS) - .newStyleCombo(Styles.ONE_HAND, Animations.AXE_AUTO1, Animations.AXE_AUTO2, Animations.AXE_DASH, Animations.AXE_AIRSLASH) - .newStyleCombo(Styles.MOUNT, Animations.SWORD_MOUNT_ATTACK); - - if (item instanceof TieredItem tieredItem) { - int tierLevel = vanillaTierToLevel(tieredItem.getTier());; - builder.addStyleAttibutes(CapabilityItem.Styles.COMMON, EpicFightAttributes.IMPACT, EpicFightAttributes.getImpactModifier(0.8D + 0.4D * tierLevel)); - } - - return builder; - }; - - public static final Function SWORD = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.SWORD) - .styleProvider((playerpatch) -> playerpatch.getHoldingItemCapability(InteractionHand.OFF_HAND).getWeaponCategory() == WeaponCategories.SWORD ? Styles.TWO_HAND : Styles.ONE_HAND) - .collider(ColliderPreset.SWORD) - .newStyleCombo(Styles.ONE_HAND, Animations.SWORD_AUTO1, Animations.SWORD_AUTO2, Animations.SWORD_AUTO3, Animations.SWORD_DASH, Animations.SWORD_AIR_SLASH) - .newStyleCombo(Styles.TWO_HAND, Animations.SWORD_DUAL_AUTO1, Animations.SWORD_DUAL_AUTO2, Animations.SWORD_DUAL_AUTO3, Animations.SWORD_DUAL_DASH, Animations.SWORD_DUAL_AIR_SLASH) - .newStyleCombo(Styles.MOUNT, Animations.SWORD_MOUNT_ATTACK) - .innateSkill(Styles.ONE_HAND, (itemstack) -> EpicFightSkills.SWEEPING_EDGE.get()) - .innateSkill(Styles.TWO_HAND, (itemstack) -> EpicFightSkills.DANCING_EDGE.get()) - .livingMotionModifier(Styles.ONE_HAND, LivingMotions.BLOCK, Animations.SWORD_GUARD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.BLOCK, Animations.SWORD_DUAL_GUARD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.IDLE, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.KNEEL, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.WALK, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.CHASE, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.RUN, Animations.BIPED_RUN_DUAL) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SNEAK, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SWIM, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FLOAT, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FALL, Animations.BIPED_HOLD_DUAL_WEAPON) - .weaponCombinationPredicator((entitypatch) -> EpicFightCapabilities.getItemStackCapability(entitypatch.getOriginal().getOffhandItem()).getWeaponCategory() == WeaponCategories.SWORD); - - if (item instanceof TieredItem tieredItem) { - builder.hitSound(tieredItem.getTier() == Tiers.WOOD ? EpicFightSounds.BLUNT_HIT.get() : EpicFightSounds.BLADE_HIT.get()); - builder.hitParticle(tieredItem.getTier() == Tiers.WOOD ? EpicFightParticles.HIT_BLUNT.get() : EpicFightParticles.HIT_BLADE.get()); - } - - return builder; - }; - public static final Function SPEAR = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.SPEAR) - .swingSound(EpicFightSounds.WHOOSH_ROD.get()) - .styleProvider((playerpatch) -> (playerpatch.getHoldingItemCapability(InteractionHand.OFF_HAND).getWeaponCategory() == WeaponCategories.SHIELD) ? Styles.ONE_HAND : Styles.TWO_HAND) - .collider(ColliderPreset.SPEAR) - .canBePlacedOffhand(false) - .reach(1.0F) - .newStyleCombo(Styles.ONE_HAND, Animations.SPEAR_ONEHAND_AUTO, Animations.SPEAR_DASH, Animations.SPEAR_ONEHAND_AIR_SLASH) - .newStyleCombo(Styles.TWO_HAND, Animations.SPEAR_TWOHAND_AUTO1, Animations.SPEAR_TWOHAND_AUTO2, Animations.SPEAR_DASH, Animations.SPEAR_TWOHAND_AIR_SLASH) - .newStyleCombo(Styles.MOUNT, Animations.SPEAR_MOUNT_ATTACK) - .innateSkill(Styles.ONE_HAND, (itemstack) -> EpicFightSkills.HEARTPIERCER.get()) - .innateSkill(Styles.TWO_HAND, (itemstack) -> EpicFightSkills.GRASPING_SPIRE.get()) - .livingMotionModifier(Styles.ONE_HAND, LivingMotions.RUN, Animations.BIPED_RUN_SPEAR) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.IDLE, Animations.BIPED_HOLD_SPEAR) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.WALK, Animations.BIPED_WALK_SPEAR) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.CHASE, Animations.BIPED_WALK_SPEAR) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.RUN, Animations.BIPED_RUN_SPEAR) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SWIM, Animations.BIPED_HOLD_SPEAR) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.BLOCK, Animations.SPEAR_GUARD); - - if (item instanceof TieredItem tieredItem) { - builder.hitSound(tieredItem.getTier() == Tiers.WOOD ? EpicFightSounds.BLUNT_HIT.get() : EpicFightSounds.BLADE_HIT.get()); - builder.hitParticle(tieredItem.getTier() == Tiers.WOOD ? EpicFightParticles.HIT_BLUNT.get() : EpicFightParticles.HIT_BLADE.get()); - } - - return builder; - }; - - public static final Function GREATSWORD = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.GREATSWORD) - .styleProvider((playerpatch) -> Styles.TWO_HAND) - .collider(ColliderPreset.GREATSWORD) - .swingSound(EpicFightSounds.WHOOSH_BIG.get()) - .canBePlacedOffhand(false) - .reach(1.0F) - .newStyleCombo(Styles.TWO_HAND, Animations.GREATSWORD_AUTO1, Animations.GREATSWORD_AUTO2, Animations.GREATSWORD_DASH, Animations.GREATSWORD_AIR_SLASH) - .innateSkill(Styles.TWO_HAND, (itemstack) -> EpicFightSkills.STEEL_WHIRLWIND.get()) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.IDLE, Animations.BIPED_HOLD_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.WALK, Animations.BIPED_WALK_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.CHASE, Animations.BIPED_WALK_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.RUN, Animations.BIPED_RUN_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.JUMP, Animations.BIPED_HOLD_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.KNEEL, Animations.BIPED_HOLD_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SNEAK, Animations.BIPED_HOLD_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SWIM, Animations.BIPED_HOLD_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FLY, Animations.BIPED_HOLD_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.CREATIVE_FLY, Animations.BIPED_HOLD_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.CREATIVE_IDLE, Animations.BIPED_HOLD_GREATSWORD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.BLOCK, Animations.GREATSWORD_GUARD); - - if (item instanceof TieredItem tieredItem) { - builder.hitSound(tieredItem.getTier() == Tiers.WOOD ? EpicFightSounds.BLUNT_HIT.get() : EpicFightSounds.BLADE_HIT.get()); - builder.hitParticle(tieredItem.getTier() == Tiers.WOOD ? EpicFightParticles.HIT_BLUNT.get() : EpicFightParticles.HIT_BLADE.get()); - } - - return builder; - }; - - public static final Function UCHIGATANA = (item) -> - WeaponCapability.builder() - .category(WeaponCategories.UCHIGATANA) - .styleProvider((entitypatch) -> { - if (entitypatch instanceof PlayerPatch playerpatch && (playerpatch.getSkill(SkillSlots.WEAPON_PASSIVE).getDataManager().hasData(EpicFightSkillDataKeys.SHEATH) && - playerpatch.getSkill(SkillSlots.WEAPON_PASSIVE).getDataManager().getDataValue(EpicFightSkillDataKeys.SHEATH))) { - return Styles.SHEATH; - } - return Styles.TWO_HAND; - }) - .passiveSkill(EpicFightSkills.BATTOJUTSU_PASSIVE.get()) - .hitSound(EpicFightSounds.BLADE_HIT.get()) - .collider(ColliderPreset.UCHIGATANA) - .canBePlacedOffhand(false) - .newStyleCombo(Styles.SHEATH, Animations.UCHIGATANA_SHEATHING_AUTO, Animations.UCHIGATANA_SHEATHING_DASH, Animations.UCHIGATANA_SHEATH_AIR_SLASH) - .newStyleCombo(Styles.TWO_HAND, Animations.UCHIGATANA_AUTO1, Animations.UCHIGATANA_AUTO2, Animations.UCHIGATANA_AUTO3, Animations.UCHIGATANA_DASH, Animations.UCHIGATANA_AIR_SLASH) - .newStyleCombo(Styles.MOUNT, Animations.SWORD_MOUNT_ATTACK) - .innateSkill(Styles.SHEATH, (itemstack) -> EpicFightSkills.BATTOJUTSU.get()) - .innateSkill(Styles.TWO_HAND, (itemstack) -> EpicFightSkills.BATTOJUTSU.get()) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.IDLE, Animations.BIPED_HOLD_UCHIGATANA) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.KNEEL, Animations.BIPED_HOLD_UCHIGATANA) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.WALK, Animations.BIPED_WALK_UCHIGATANA) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.CHASE, Animations.BIPED_WALK_UCHIGATANA) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.RUN, Animations.BIPED_RUN_UCHIGATANA) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SNEAK, Animations.BIPED_WALK_UCHIGATANA) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SWIM, Animations.BIPED_HOLD_UCHIGATANA) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FLOAT, Animations.BIPED_HOLD_UCHIGATANA) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FALL, Animations.BIPED_HOLD_UCHIGATANA) - .livingMotionModifier(Styles.SHEATH, LivingMotions.IDLE, Animations.BIPED_HOLD_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.SHEATH, LivingMotions.KNEEL, Animations.BIPED_HOLD_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.SHEATH, LivingMotions.WALK, Animations.BIPED_WALK_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.SHEATH, LivingMotions.CHASE, Animations.BIPED_HOLD_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.SHEATH, LivingMotions.RUN, Animations.BIPED_RUN_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.SHEATH, LivingMotions.SNEAK, Animations.BIPED_HOLD_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.SHEATH, LivingMotions.SWIM, Animations.BIPED_HOLD_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.SHEATH, LivingMotions.FLOAT, Animations.BIPED_HOLD_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.SHEATH, LivingMotions.FALL, Animations.BIPED_HOLD_UCHIGATANA_SHEATHING) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.BLOCK, Animations.UCHIGATANA_GUARD); - - public static final Function TACHI = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.TACHI) - .styleProvider((playerpatch) -> Styles.TWO_HAND) - .collider(ColliderPreset.TACHI) - .canBePlacedOffhand(false) - .newStyleCombo(Styles.TWO_HAND, Animations.TACHI_AUTO1, Animations.TACHI_AUTO2, Animations.TACHI_AUTO3, Animations.TACHI_DASH, Animations.LONGSWORD_AIR_SLASH) - .newStyleCombo(Styles.MOUNT, Animations.SWORD_MOUNT_ATTACK) - .innateSkill(Styles.TWO_HAND, (itemstack) -> EpicFightSkills.RUSHING_TEMPO.get()) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.IDLE, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.KNEEL, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.WALK, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.CHASE, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.RUN, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SNEAK, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SWIM, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FLOAT, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FALL, Animations.BIPED_HOLD_TACHI) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.BLOCK, Animations.LONGSWORD_GUARD); - - if (item instanceof TieredItem tieredItem) { - builder.hitSound(tieredItem.getTier() == Tiers.WOOD ? EpicFightSounds.BLUNT_HIT.get() : EpicFightSounds.BLADE_HIT.get()); - builder.hitParticle(tieredItem.getTier() == Tiers.WOOD ? EpicFightParticles.HIT_BLUNT.get() : EpicFightParticles.HIT_BLADE.get()); - } - - return builder; - }; - - public static final Function LONGSWORD = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.LONGSWORD) - .styleProvider((playerpatch) -> { - if (playerpatch.getHoldingItemCapability(InteractionHand.OFF_HAND).getWeaponCategory() == WeaponCategories.SHIELD) { - return Styles.ONE_HAND; - } else if (playerpatch instanceof PlayerPatch tplayerpatch) { - return tplayerpatch.getSkill(SkillSlots.WEAPON_INNATE).isActivated() ? Styles.OCHS : Styles.TWO_HAND; - } - - return Styles.TWO_HAND; - }) - .collider(ColliderPreset.LONGSWORD) - .canBePlacedOffhand(false) - .newStyleCombo(Styles.ONE_HAND, Animations.LONGSWORD_AUTO1, Animations.LONGSWORD_AUTO2, Animations.LONGSWORD_AUTO3, Animations.LONGSWORD_DASH, Animations.LONGSWORD_AIR_SLASH) - .newStyleCombo(Styles.TWO_HAND, Animations.LONGSWORD_AUTO1, Animations.LONGSWORD_AUTO2, Animations.LONGSWORD_AUTO3, Animations.LONGSWORD_DASH, Animations.LONGSWORD_AIR_SLASH) - .newStyleCombo(Styles.OCHS, Animations.LONGSWORD_LIECHTENAUER_AUTO1, Animations.LONGSWORD_LIECHTENAUER_AUTO2, Animations.LONGSWORD_LIECHTENAUER_AUTO3, Animations.LONGSWORD_DASH, Animations.LONGSWORD_AIR_SLASH) - .innateSkill(Styles.ONE_HAND, (itemstack) -> EpicFightSkills.SHARP_STAB.get()) - .innateSkill(Styles.TWO_HAND, (itemstack) -> EpicFightSkills.LIECHTENAUER.get()) - .innateSkill(Styles.OCHS, (itemstack) -> EpicFightSkills.LIECHTENAUER.get()) - .livingMotionModifier(Styles.COMMON, LivingMotions.IDLE, Animations.BIPED_HOLD_LONGSWORD) - .livingMotionModifier(Styles.COMMON, LivingMotions.WALK, Animations.BIPED_WALK_LONGSWORD) - .livingMotionModifier(Styles.COMMON, LivingMotions.CHASE, Animations.BIPED_WALK_LONGSWORD) - .livingMotionModifier(Styles.COMMON, LivingMotions.RUN, Animations.BIPED_RUN_LONGSWORD) - .livingMotionModifier(Styles.COMMON, LivingMotions.SNEAK, Animations.BIPED_HOLD_LONGSWORD) - .livingMotionModifier(Styles.COMMON, LivingMotions.KNEEL, Animations.BIPED_HOLD_LONGSWORD) - .livingMotionModifier(Styles.COMMON, LivingMotions.JUMP, Animations.BIPED_HOLD_LONGSWORD) - .livingMotionModifier(Styles.COMMON, LivingMotions.SWIM, Animations.BIPED_HOLD_LONGSWORD) - .livingMotionModifier(Styles.COMMON, LivingMotions.BLOCK, Animations.LONGSWORD_GUARD) - .livingMotionModifier(Styles.OCHS, LivingMotions.IDLE, Animations.BIPED_HOLD_LIECHTENAUER) - .livingMotionModifier(Styles.OCHS, LivingMotions.WALK, Animations.BIPED_WALK_LIECHTENAUER) - .livingMotionModifier(Styles.OCHS, LivingMotions.CHASE, Animations.BIPED_WALK_LIECHTENAUER) - .livingMotionModifier(Styles.OCHS, LivingMotions.RUN, Animations.BIPED_HOLD_LIECHTENAUER) - .livingMotionModifier(Styles.OCHS, LivingMotions.SNEAK, Animations.BIPED_HOLD_LIECHTENAUER) - .livingMotionModifier(Styles.OCHS, LivingMotions.KNEEL, Animations.BIPED_HOLD_LIECHTENAUER) - .livingMotionModifier(Styles.OCHS, LivingMotions.JUMP, Animations.BIPED_HOLD_LIECHTENAUER) - .livingMotionModifier(Styles.OCHS, LivingMotions.SWIM, Animations.BIPED_HOLD_LIECHTENAUER) - .livingMotionModifier(Styles.ONE_HAND, LivingMotions.BLOCK, Animations.SWORD_GUARD) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.BLOCK, Animations.LONGSWORD_GUARD) - .livingMotionModifier(Styles.OCHS, LivingMotions.BLOCK, Animations.LONGSWORD_GUARD); - - if (item instanceof TieredItem tieredItem) { - builder.hitSound(tieredItem.getTier() == Tiers.WOOD ? EpicFightSounds.BLUNT_HIT.get() : EpicFightSounds.BLADE_HIT.get()); - builder.hitParticle(tieredItem.getTier() == Tiers.WOOD ? EpicFightParticles.HIT_BLUNT.get() : EpicFightParticles.HIT_BLADE.get()); - } - - return builder; - }; - - public static final Function DAGGER = (item) -> { - WeaponCapability.Builder builder = WeaponCapability.builder() - .category(WeaponCategories.DAGGER) - .styleProvider((playerpatch) -> playerpatch.getHoldingItemCapability(InteractionHand.OFF_HAND).getWeaponCategory() == WeaponCategories.DAGGER ? Styles.TWO_HAND : Styles.ONE_HAND) - .swingSound(EpicFightSounds.WHOOSH_SMALL.get()) - .collider(ColliderPreset.DAGGER) - .weaponCombinationPredicator((entitypatch) -> EpicFightCapabilities.getItemStackCapability(entitypatch.getOriginal().getOffhandItem()).getWeaponCategory() == WeaponCategories.DAGGER) - .newStyleCombo(Styles.ONE_HAND, Animations.DAGGER_AUTO1, Animations.DAGGER_AUTO2, Animations.DAGGER_AUTO3, Animations.DAGGER_DASH, Animations.DAGGER_AIR_SLASH) - .newStyleCombo(Styles.TWO_HAND, Animations.DAGGER_DUAL_AUTO1, Animations.DAGGER_DUAL_AUTO2, Animations.DAGGER_DUAL_AUTO3, Animations.DAGGER_DUAL_AUTO4, Animations.DAGGER_DUAL_DASH, Animations.DAGGER_DUAL_AIR_SLASH) - .newStyleCombo(Styles.MOUNT, Animations.SWORD_MOUNT_ATTACK) - .innateSkill(Styles.ONE_HAND, (itemstack) -> EpicFightSkills.EVISCERATE.get()) - .innateSkill(Styles.TWO_HAND, (itemstack) -> EpicFightSkills.BLADE_RUSH.get()) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.IDLE, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.KNEEL, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.WALK, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.CHASE, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.RUN, Animations.BIPED_RUN_DUAL) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SNEAK, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.SWIM, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FLOAT, Animations.BIPED_HOLD_DUAL_WEAPON) - .livingMotionModifier(Styles.TWO_HAND, LivingMotions.FALL, Animations.BIPED_HOLD_DUAL_WEAPON); - - if (item instanceof TieredItem tieredItem) { - builder.hitSound(tieredItem.getTier() == Tiers.WOOD ? EpicFightSounds.BLUNT_HIT.get() : EpicFightSounds.BLADE_HIT.get()); - builder.hitParticle(tieredItem.getTier() == Tiers.WOOD ? EpicFightParticles.HIT_BLUNT.get() : EpicFightParticles.HIT_BLADE.get()); - } - - return builder; - }; - public static final Function FIST = (item) -> WeaponCapability.builder() - .newStyleCombo(Styles.ONE_HAND, Animations.FIST_AUTO1, Animations.FIST_AUTO2, Animations.FIST_AUTO3, Animations.FIST_DASH, Animations.FIST_AIR_SLASH) - .innateSkill(Styles.ONE_HAND, (itemstack) -> EpicFightSkills.RELENTLESS_COMBO.get()) - .category(WeaponCategories.FIST) - .constructor(GloveCapability::new); - - public static final Function BOW = (item) -> RangedWeaponCapability.builder() - .zoomInType(ZoomInType.USE_TICK) - .addAnimationsModifier(LivingMotions.IDLE, Animations.BIPED_IDLE) - .addAnimationsModifier(LivingMotions.WALK, Animations.BIPED_WALK) - .addAnimationsModifier(LivingMotions.AIM, Animations.BIPED_BOW_AIM) - .addAnimationsModifier(LivingMotions.SHOT, Animations.BIPED_BOW_SHOT) - .constructor(BowCapability::new); - - public static final Function CROSSBOW = (item) -> RangedWeaponCapability.builder() - .zoomInType(ZoomInType.AIMING) - .addAnimationsModifier(LivingMotions.IDLE, Animations.BIPED_HOLD_CROSSBOW) - .addAnimationsModifier(LivingMotions.KNEEL, Animations.BIPED_HOLD_CROSSBOW) - .addAnimationsModifier(LivingMotions.WALK, Animations.BIPED_HOLD_CROSSBOW) - .addAnimationsModifier(LivingMotions.RUN, Animations.BIPED_HOLD_CROSSBOW) - .addAnimationsModifier(LivingMotions.SNEAK, Animations.BIPED_HOLD_CROSSBOW) - .addAnimationsModifier(LivingMotions.SWIM, Animations.BIPED_HOLD_CROSSBOW) - .addAnimationsModifier(LivingMotions.FLOAT, Animations.BIPED_HOLD_CROSSBOW) - .addAnimationsModifier(LivingMotions.FALL, Animations.BIPED_HOLD_CROSSBOW) - .addAnimationsModifier(LivingMotions.RELOAD, Animations.BIPED_CROSSBOW_RELOAD) - .addAnimationsModifier(LivingMotions.AIM, Animations.BIPED_CROSSBOW_AIM) - .addAnimationsModifier(LivingMotions.SHOT, Animations.BIPED_CROSSBOW_SHOT) - .constructor(CrossbowCapability::new); - - public static final Function TRIDENT = (item) -> RangedWeaponCapability.builder() - .zoomInType(ZoomInType.USE_TICK) - .addAnimationsModifier(LivingMotions.IDLE, Animations.BIPED_IDLE) - .addAnimationsModifier(LivingMotions.WALK, Animations.BIPED_WALK) - .addAnimationsModifier(LivingMotions.AIM, Animations.BIPED_JAVELIN_AIM) - .addAnimationsModifier(LivingMotions.SHOT, Animations.BIPED_JAVELIN_THROW) - .constructor(TridentCapability::new) - .collider(ColliderPreset.SPEAR) - .category(WeaponCategories.TRIDENT); - - public static final Function> SHIELD = (item) -> CapabilityItem.builder() - .constructor(ShieldCapability::new) - .category(WeaponCategories.SHIELD); + public static WeaponCapability.Builder exCapRegistration(Map.Entry entry, Item item) + { + if (entry == null) return new WeaponCapability.Builder(); + List data = Lists.newArrayList(); + ExCapManager.retrieveExCapData(entry.getKey()).forEach(exCapData -> data.add(exCapData.build())); + WeaponCapability.Builder copy = entry.getValue().copy(); + handleTieredStats(copy, item); + data.forEach(exCapData -> exCapData.apply(copy)); + EpicFight.LOGGER.debug(copy.toString()); + return copy; + } + + private static void handleTieredStats(WeaponCapability.Builder builder, Item item) + { + if (item instanceof TieredItem tieredItem) { + int tierLevel = vanillaTierToLevel(tieredItem.getTier()); + builder.modifyTierAttributes(tierLevel); + } + } } diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponTypeReloadListener.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponTypeReloadListener.java index 2f9effddd..073b5f08a 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponTypeReloadListener.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/item/WeaponTypeReloadListener.java @@ -39,10 +39,7 @@ import yesman.epicfight.world.capabilities.entitypatch.LivingEntityPatch; import yesman.epicfight.world.capabilities.provider.ExtraEntryProvider; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -51,22 +48,6 @@ public class WeaponTypeReloadListener extends SimpleJsonResourceReloadListener { public static void registerDefaultWeaponTypes() { Map>> typeEntry = Maps.newHashMap(); - typeEntry.put(EpicFight.identifier("axe"), WeaponCapabilityPresets.AXE); - typeEntry.put(EpicFight.identifier("fist"), WeaponCapabilityPresets.FIST); - typeEntry.put(EpicFight.identifier("hoe"), WeaponCapabilityPresets.HOE); - typeEntry.put(EpicFight.identifier("pickaxe"), WeaponCapabilityPresets.PICKAXE); - typeEntry.put(EpicFight.identifier("shovel"), WeaponCapabilityPresets.SHOVEL); - typeEntry.put(EpicFight.identifier("sword"), WeaponCapabilityPresets.SWORD); - typeEntry.put(EpicFight.identifier("spear"), WeaponCapabilityPresets.SPEAR); - typeEntry.put(EpicFight.identifier("greatsword"), WeaponCapabilityPresets.GREATSWORD); - typeEntry.put(EpicFight.identifier("uchigatana"), WeaponCapabilityPresets.UCHIGATANA); - typeEntry.put(EpicFight.identifier("tachi"), WeaponCapabilityPresets.TACHI); - typeEntry.put(EpicFight.identifier("longsword"), WeaponCapabilityPresets.LONGSWORD); - typeEntry.put(EpicFight.identifier("dagger"), WeaponCapabilityPresets.DAGGER); - typeEntry.put(EpicFight.identifier("bow"), WeaponCapabilityPresets.BOW); - typeEntry.put(EpicFight.identifier("crossbow"), WeaponCapabilityPresets.CROSSBOW); - typeEntry.put(EpicFight.identifier("trident"), WeaponCapabilityPresets.TRIDENT); - typeEntry.put(EpicFight.identifier("shield"), WeaponCapabilityPresets.SHIELD); WeaponCapabilityPresetRegistryEvent weaponCapabilityPresetRegistryEvent = new WeaponCapabilityPresetRegistryEvent(typeEntry); EpicFightEventHooks.Registry.WEAPON_CAPABILITY_PRESET.post(weaponCapabilityPresetRegistryEvent); @@ -86,25 +67,24 @@ public WeaponTypeReloadListener() { @Override protected void apply(Map packEntry, ResourceManager resourceManager, ProfilerFiller profilerFiller) { clear(); - - for (Map.Entry entry : packEntry.entrySet()) { + packEntry.forEach((key, value) -> { CompoundTag compTag = null; try { - compTag = TagParser.parseTag(entry.getValue().toString()); + compTag = TagParser.parseTag(value.toString()); } catch (CommandSyntaxException e) { e.printStackTrace(); } try { final CompoundTag comptagFinal = compTag; - PRESETS.put(entry.getKey(), (itemstack) -> deserializeWeaponCapabilityBuilder(entry.getKey(), comptagFinal)); - CAPABILITY_COMPOUNDS.put(entry.getKey(), compTag); + PRESETS.put(key, (itemstack) -> deserializeWeaponCapabilityBuilder(key, comptagFinal)); + CAPABILITY_COMPOUNDS.put(key, compTag); } catch (Exception e) { - EpicFight.LOGGER.warn("Error while deserializing weapon type datapack: " + entry.getKey()); + EpicFight.LOGGER.warn("Error while deserializing weapon type datapack: " + key); e.printStackTrace(); } - } + }); } public static Function> getOrThrow(String typeName) { @@ -313,6 +293,7 @@ public static void clear() { public static void processServerPacket(SPDatapackSync packet) { if (packet.packetType() == SPDatapackSync.PacketType.WEAPON_TYPE) { PRESETS.clear(); + // registerDefaultWeaponTypes(); for (CompoundTag tag : packet.tags()) { diff --git a/neoforge/src/main/java/yesman/epicfight/world/capabilities/provider/CommonItemCapabilityProvider.java b/neoforge/src/main/java/yesman/epicfight/world/capabilities/provider/CommonItemCapabilityProvider.java index c153e76f7..a9547350c 100644 --- a/neoforge/src/main/java/yesman/epicfight/world/capabilities/provider/CommonItemCapabilityProvider.java +++ b/neoforge/src/main/java/yesman/epicfight/world/capabilities/provider/CommonItemCapabilityProvider.java @@ -4,6 +4,8 @@ import java.util.Map; import java.util.function.Function; +import yesman.epicfight.api.ex_cap.modules.assets.Builders; +import yesman.epicfight.api.ex_cap.modules.core.managers.BuilderManager; import org.jetbrains.annotations.Nullable; import net.minecraft.core.registries.BuiltInRegistries; @@ -40,14 +42,14 @@ private CommonItemCapabilityProvider() {} public void registerWeaponTypesByClass() { this.typedCapabilities.put(ArmorItem.class, (item) -> ArmorCapability.builder().byItem(item)); - this.typedCapabilities.put(ShieldItem.class, WeaponCapabilityPresets.SHIELD); - this.typedCapabilities.put(SwordItem.class, WeaponCapabilityPresets.SWORD); - this.typedCapabilities.put(PickaxeItem.class, WeaponCapabilityPresets.PICKAXE); - this.typedCapabilities.put(AxeItem.class, WeaponCapabilityPresets.AXE); - this.typedCapabilities.put(ShovelItem.class, WeaponCapabilityPresets.SHOVEL); - this.typedCapabilities.put(HoeItem.class, WeaponCapabilityPresets.HOE); - this.typedCapabilities.put(BowItem.class, WeaponCapabilityPresets.BOW); - this.typedCapabilities.put(CrossbowItem.class, WeaponCapabilityPresets.CROSSBOW); + this.typedCapabilities.put(ShieldItem.class, item -> WeaponCapabilityPresets.exCapRegistration(BuilderManager.getEntry(Builders.SHIELD.id()), item)); + this.typedCapabilities.put(SwordItem.class, item -> WeaponCapabilityPresets.exCapRegistration(BuilderManager.getEntry(Builders.SWORD.id()), item)); + this.typedCapabilities.put(PickaxeItem.class, item -> WeaponCapabilityPresets.exCapRegistration(BuilderManager.getEntry(Builders.PICKAXE.id()), item)); + this.typedCapabilities.put(AxeItem.class, item -> WeaponCapabilityPresets.exCapRegistration(BuilderManager.getEntry(Builders.AXE.id()), item)); + this.typedCapabilities.put(ShovelItem.class, item -> WeaponCapabilityPresets.exCapRegistration(BuilderManager.getEntry(Builders.SHOVEL.id()), item)); + this.typedCapabilities.put(HoeItem.class, item -> WeaponCapabilityPresets.exCapRegistration(BuilderManager.getEntry(Builders.HOE.id()), item)); + this.typedCapabilities.put(BowItem.class, item -> WeaponCapabilityPresets.exCapRegistration(BuilderManager.getEntry(Builders.BOW.id()), item)); + this.typedCapabilities.put(CrossbowItem.class, item -> WeaponCapabilityPresets.exCapRegistration(BuilderManager.getEntry(Builders.CROSSBOW.id()), item)); this.typedCapabilities.put(MapItem.class, (item) -> MapCapability.builder()); } diff --git a/neoforge/src/main/resources/epicfight.mixins.json b/neoforge/src/main/resources/epicfight.mixins.json index 3ed6e5ac9..e584824b5 100644 --- a/neoforge/src/main/resources/epicfight.mixins.json +++ b/neoforge/src/main/resources/epicfight.mixins.json @@ -41,6 +41,7 @@ "common.MixinServerCommonPacketListenerImpl", "common.MixinServerEntity", "common.MixinThrownTrident", + "common.MixinTridentAttack", "common.MixinWitherBoss", "common.MixinWitherBossAccessor" ],