### Gradle Properties Version Example Source: https://epicfight-docs.readthedocs.io/API/Starting Example of setting the Epic Fight version in the `gradle.properties` file. ```properties epicfight_version=21.12.5 ``` -------------------------------- ### Example Patched Entity Renderer Source: https://epicfight-docs.readthedocs.io/API/Starting An example of a patched entity renderer that extends PHumanoidRenderer. ```java public class YourEntityPatchRenderer extends PHumanoidRenderer, YourEntityRenderer, HumanoidMesh> { public DummyEntityRendererEfPatch(EntityRendererProvider.Context context, EntityType entityType) { super(Meshes.BIPED, context, entityType); } } ``` -------------------------------- ### Registering Custom Animations Source: https://epicfight-docs.readthedocs.io/API/Starting Example of how to register custom animations for the Epic Fight mod. ```java import yesman.epicfight.api.animation.AnimationManager.AnimationRegistryEvent; import yesman.epicfight.api.animation.AnimationManager.AnimationAccessor; import yesman.epicfight.gameasset.Armatures.ArmatureAccessor; @EventBusSubscriber(modid = YourMod.MOD_ID) public class Animations { @SubscribeEvent public static void registerAnimations(AnimationRegistryEvent event) { event.newBuilder(YourMod.MOD_ID, Animations::build); } // Animation accessors for different animation types public static AnimationAccessor BIPED_IDLE; public static AnimationAccessor BIPED_WALK; public static AnimationAccessor BIPED_FLYING; public static AnimationAccessor TRIDENT_AUTO1; public static AnimationAccessor TRIDENT_AUTO2; public static AnimationAccessor TRIDENT_AUTO3; // Define the actual animations and their properties private static void build(AnimationManager.AnimationBuilder builder) { ArmatureAccessor armatureAccessor = Armatures.BIPED; BIPED_IDLE = builder.nextAccessor("biped/living/idle", (accessor) -> new StaticAnimation(true, accessor, armatureAccessor)); BIPED_WALK = builder.nextAccessor("biped/living/walk", (accessor) -> new MovementAnimation(true, accessor, armatureAccessor)); BIPED_FLYING = builder.nextAccessor("biped/living/fly", (accessor) -> new StaticAnimation(true, accessor, armatureAccessor)); TRIDENT_AUTO1 = builder.nextAccessor("biped/combat/trident_auto1", (accessor) -> new ComboAttackAnimation(0.3F, 0.05F, 0.16F, 0.45F, null, armatureAccessor.get().toolR, accessor, armatureAccessor)); TRIDENT_AUTO2 = builder.nextAccessor("biped/combat/trident_auto2", (accessor) -> new ComboAttackAnimation(0.05F, 0.25F, 0.36F, 0.55F, null, armatureAccessor.get().toolR, accessor, armatureAccessor)); TRIDENT_AUTO3 = builder.nextAccessor("biped/combat/trident_auto3", (accessor) -> new ComboAttackAnimation(0.2F, 0.3F, 0.46F, 0.9F, null, armatureAccessor.get().toolR, accessor, armatureAccessor)); } } ``` -------------------------------- ### NeoForge 1.21.1 Gradle Repositories Source: https://epicfight-docs.readthedocs.io/API/Starting Adds the Modrinth Maven repository for NeoForge 1.21.1 to the Gradle build. ```gradle repositories { exclusiveContent { forRepository { maven { name = "Modrinth"; url = "https://api.modrinth.com/maven" } } filter { includeGroup "maven.modrinth" } } } ``` -------------------------------- ### Example Patched Entity Class Source: https://epicfight-docs.readthedocs.io/API/Starting An example of a patched entity class that extends HumanoidMobPatch and customizes AI and animations. ```java public class YourEntityPatch extends HumanoidMobPatch { public YourEntityPatch(YourEntity original) { super(original, Factions.VILLAGER); } @Override public void updateMotion(boolean b) { super.commonMobUpdateMotion(b); } @Override protected void initAI() { super.initAI(); this.original.goalSelector.addGoal( 1, new AnimatedAttackGoal<>(this, new CombatBehaviors.Builder<>().build(this)) ); this.original.goalSelector.addGoal(2, new TargetChasingGoal(this, this.getOriginal(), 1.2f, true)); this.original.goalSelector.addGoal(3, new RandomStrollGoal(original, 1.0f)); this.original.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(original, Player.class, true)); } public void initAnimator(Animator animator) { super.initAnimator(animator); // All available living motions are listed in this enum: https://github.com/Epic-Fight/epicfight/blob/1.21.1/src/main/java/yesman/epicfight/api/animation/LivingMotions.java#L4-L6 animator.addLivingAnimation(LivingMotions.IDLE, Animations.BIPED_IDLE); animator.addLivingAnimation(LivingMotions.WALK, Animations.BIPED_WALK); animator.addLivingAnimation(LivingMotions.RUN, Animations.BIPED_RUN); animator.addLivingAnimation(LivingMotions.FALL, Animations.BIPED_FALL); animator.addLivingAnimation(LivingMotions.SIT, Animations.BIPED_SIT); animator.addLivingAnimation(LivingMotions.DEATH, Animations.BIPED_DEATH); animator.addLivingAnimation(LivingMotions.JUMP, Animations.BIPED_JUMP); animator.addLivingAnimation(LivingMotions.SLEEP, Animations.BIPED_SLEEPING); animator.addLivingAnimation(LivingMotions.AIM, Animations.BIPED_BOW_AIM); animator.addLivingAnimation(LivingMotions.SHOT, Animations.BIPED_BOW_SHOT); animator.addLivingAnimation(LivingMotions.DRINK, Animations.BIPED_DRINK); animator.addLivingAnimation(LivingMotions.EAT, Animations.BIPED_EAT); } } ``` -------------------------------- ### Forge 1.20.1 Gradle Repositories Source: https://epicfight-docs.readthedocs.io/API/Starting Adds the Modrinth Maven repository for Forge 1.20.1 to the Gradle build. ```gradle repositories { exclusiveContent { forRepository { maven { name = "Modrinth"; url = "https://api.modrinth.com/maven" } } forRepositories(fg.repository) filter { includeGroup "maven.modrinth" } } } ``` -------------------------------- ### Playing an Animation on an Entity Source: https://epicfight-docs.readthedocs.io/API/Starting Example of how to play the static Jump animation on an Epic Fight-patched entity when a player right-clicks it. ```java public class YourEntity extends PathfinderMob { // ... @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { final boolean isEpicFightModLoaded = ModList.get().isLoaded("epicfight"); if (isEpicFightModLoaded) { final LivingEntityPatch entityPatch = EpicFightCapabilities.getEntityPatch(this, LivingEntityPatch.class); entityPatch.playAnimationInstantly(Animations.BIPED_JUMP); } return super.mobInteract(player, hand); } } ``` -------------------------------- ### Retrieving Patched Entity Instance Source: https://epicfight-docs.readthedocs.io/API/Starting How to retrieve the patched entity instance from a vanilla entity. ```java final YourEntity entity = ...; final YourEntityPatch entityPatch = EpicFightCapabilities.getEntityPatch(entity, YourEntityPatch.class); ``` -------------------------------- ### NeoForge 1.21.1 Epic Fight Dependency Source: https://epicfight-docs.readthedocs.io/API/Starting Declares Epic Fight mod as an implementation dependency for NeoForge 1.21.1. ```gradle dependencies { implementation "maven.modrinth:epic-fight:${epicfight_version}" } ``` -------------------------------- ### Forge 1.20.1 Epic Fight Dependency Source: https://epicfight-docs.readthedocs.io/API/Starting Declares Epic Fight mod as a deobfuscated implementation dependency for Forge 1.20.1. ```gradle dependencies { implementation fg.deobf("maven.modrinth:epic-fight:${epicfight_version}") } ``` -------------------------------- ### Register the enum in your mod's constructor Source: https://epicfight-docs.readthedocs.io/API/Starting Register the enum in your mod’s constructor to make Epic Fight recognize the new slots. ```java @Mod(YourMod.MOD_ID) public class YourMod { public static final String MOD_ID = "your_mod_id"; public YourMod() { SkillSlot.ENUM_MANAGER.registerEnumCls(MOD_ID, MoreSkillSlots.class); } } ``` -------------------------------- ### Registering Patched Entity Renderer Source: https://epicfight-docs.readthedocs.io/API/Starting Code to register the patched entity renderer on the client side using the PatchedRenderersEvent.Add event. ```java @EventBusSubscriber(modid = YourMod.MOD_ID, value = Dist.CLIENT) public class EpicFightClientEvents { @SubscribeEvent public static void registerPatchedEntityRenderers(PatchedRenderersEvent.Add event) { event.addPatchedEntityRenderer(YourModEntities.THE_ENTITY.get(), entityType -> new YourEntityPatchRenderer( event.getContext(), entityType ) ); } } ``` -------------------------------- ### Creating Dynamic Asset Accessor - Animation Source: https://epicfight-docs.readthedocs.io/API/Utilities Example of creating a dynamic Animation accessor and checking for its presence. ```java public static final AssetAccessor MAY_EXIST_ANIMATION = AnimationManager.byKey(ResourceLocation.fromNamespaceAndPath(EpicFightMod.MODID, "my_entity/may_exist_idle_animation")); // Check if the resource exists if (MAY_EXIST_ANIMATION.isPresent()) { // do task when the resource exists } // Or use ifPresent MAY_EXIST_ANIMATION.ifPresent(theAnimation -> { // do task when the resource exists }); ``` -------------------------------- ### Creating Dynamic Asset Accessor - Armature Source: https://epicfight-docs.readthedocs.io/API/Utilities Example of creating a dynamic Armature accessor and checking for its presence. ```java public static final AssetAccessor MAY_EXIST_ARMATURE = Armatures.getOrCreate(ResourceLocation.fromNamespaceAndPath(MyMod.MODID, "entity/may_exist_entity"), MyArmature::new); // Check if the resource exists if (MAY_EXIST_ARMATURE.isPresent()) { // do task when the resource exists } // Or use ifPresent MAY_EXIST_ARMATURE.ifPresent(theArmature -> { // do task when the resource exists }); ``` -------------------------------- ### Registering Patched Entity and Armature Source: https://epicfight-docs.readthedocs.io/API/Starting Code to register the patched entity with EntityPatchRegistryEvent and its armature to prevent runtime crashes. ```java @EventBusSubscriber(modid = YourMod.MOD_ID) public class YourModEvents { @SubscribeEvent public static void registerPatchedEntities(EntityPatchRegistryEvent event) { event.getTypeEntry().put(YourModEntities.THE_ENTITY.get(), entity -> new YourEntityPatch((YourEntity) entity)); } @SubscribeEvent public static void commonSetup(FMLCommonSetupEvent event) { event.enqueueWork(YourModEvents::registerEntityTypeArmatures); } private static void registerEntityTypeArmatures() { Armatures.registerEntityTypeArmature(YourModEntities.THE_ENTITY.get(), Armatures.BIPED); } } ``` -------------------------------- ### Example of registering a subscriber with full arguments Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 This snippet shows how to register an event subscriber with a custom subscriber name and priority. ```java EpicFightEventHooks.Player.CHANGE_INNATE_SKILL.registerEvent( event -> { if (event.getToItemCapability().getInnateSkill(event.getPlayerPatch(), event.getTo()) == EpicFightSkills.SWEEPING_EDGE.get()) { System.out.println("Changed to Sweeping Edge skill."); } }, "MySubscriber", // Set the name of the subscriber 10 // Set priority ); ``` -------------------------------- ### Add translations for custom skill slots Source: https://epicfight-docs.readthedocs.io/API/Starting Add translations for these slots in your assets/your_mod_id/lang/en_us.json file. These entries control how the slot names appear in the game’s interface. ```json { "epicfight.skill_slot.passive4": "Passive 4", "epicfight.skill_slot.passive5": "Passive 5", "epicfight.skill_slot.identity2": "Identity 2" } ``` -------------------------------- ### Controller Integration Source: https://epicfight-docs.readthedocs.io/API/Input Example of integrating a controller mod by implementing IEpicFightControllerMod and registering it. ```java // Controlify mod is used as an example here. final class ControlifyModIntegration implements IEpicFightControllerMod { // Implement the required methods... } EpicFightControllerModProvider.set(YourMod.MODID, new ControlifyModIntegration()); ``` -------------------------------- ### Creating Dynamic Asset Accessor - Mesh Source: https://epicfight-docs.readthedocs.io/API/Utilities Example of creating a dynamic Mesh accessor and checking for its presence. ```java public static final AssetAccessor MAY_EXIST_MESH = Meshes.getOrCreate(ResourceLocation.fromNamespaceAndPath(MyMod.MODID, "entity/may_exist_entity"), jsonModelLoader -> jsonModelLoader.loadSkinnedMesh(MyMesh::new)); // Check if the resource exists if (MAY_EXIST_MESH.isPresent()) { // do task when the resource exists } // Or use ifPresent MAY_EXIST_MESH.ifPresent(theMesh -> { // do task when the resource exists }); ``` -------------------------------- ### Triggering a Custom Event Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 Example of how to post a custom event using a defined event hook. ```java MyEventHooks.MY_EVENT_HOOK.post(new MyEventHook()); ``` -------------------------------- ### Creating Built-in Asset Accessors - Animation Source: https://epicfight-docs.readthedocs.io/API/Utilities Example of creating an AnimationAccessor for a mod's animations, including registration. ```java public static AnimationAccessor MY_ENTITY_IDLE_ANIMATION; @SubscribeEvent public static void registerAnimations(AnimationRegistryEvent event) { event.newBuilder(MyMod.MODID, MyAnimations::build); } public static void build(AnimationBuilder builder) { MY_ENTITY_IDLE_ANIMATION = builder.nextAccessor("my_entity/idle", accessor -> new StaticAnimation(true, accessor, Armatures.MY_ENTITY)); } ``` -------------------------------- ### Adding custom extensible enums Source: https://epicfight-docs.readthedocs.io/API/Utilities Example of creating a new extensible enum for other developers to use. ```java public interface MyExtensibleEnum extends ExtendableEnum { ExtendableEnumManager ENUM_MANAGER = new ExtendableEnumManager<> ("my_extensible_enum"); } ``` ```java public enum MyExtensibleEnums implements MyExtensibleEnum { ENUM1, ENUM2, ENUM3; final int id; MyExtensibleEnums() { this.id = MyExtensibleEnum.ENUM_MANAGER.assign(this); } @Override public int universalOrdinal() { return this.id; } } ``` ```java @Mod(MyMod.MODID) public class MyMod { ... public MyMod(FMLJavaModLoadingContext context) { ... MyExtensibleEnum.ENUM_MANAGER.registerEnumCls(MyMod.MODID, MyExtensibleEnums.class); ... } ''' private void constructMod(final FMLConstructModEvent event) { ''' // This loads all enum classes specified by "registerEnumCls" event.enqueueWork(MyExtensibleEnum.ENUM_MANAGER::loadEnum); ''' } ''' } ``` -------------------------------- ### Define an enum for custom skill slots Source: https://epicfight-docs.readthedocs.io/API/Starting Define an enum that declares the additional skill slots your mod introduces to Epic Fight. Each enum constant represents a distinct slot. ```java public enum YourModSkillSlots implements SkillSlot { PASSIVE4(SkillCategories.PASSIVE), PASSIVE5(SkillCategories.PASSIVE), IDENTITY2(SkillCategories.IDENTITY), ; final SkillCategory category; final int id; YourModSkillSlots(SkillCategory category) { this.category = category; id = SkillSlot.ENUM_MANAGER.assign(this); } @Override public SkillCategory category() { return category; } @Override public int universalOrdinal() { return this.id; } } ``` -------------------------------- ### Creating Built-in Asset Accessors - Armature Source: https://epicfight-docs.readthedocs.io/API/Utilities Example of creating a static final ArmatureAccessor for a mod's assets. ```java public static final ArmatureAccessor MY_ARMATURE = ArmatureAccessor.create(MyMod.MODID, "entity/my_entity", MyArmature::new); ``` -------------------------------- ### Example of registering a subscriber for CHANGE_INNATE_SKILL event Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 This snippet demonstrates how to register an event subscriber that prints a message when the innate skill is set to Sweeping Edge. ```java EpicFightEventHooks.Player.CHANGE_INNATE_SKILL.registerEvent(event -> { if (event.getToItemCapability().getInnateSkill(event.getPlayerPatch(), event.getTo()) == EpicFightSkills.SWEEPING_EDGE.get()) { System.out.println("Changed to Sweeping Edge skill."); } }); ``` -------------------------------- ### Creating Built-in Asset Accessors - Mesh Source: https://epicfight-docs.readthedocs.io/API/Utilities Example of creating a static final MeshAccessor for a mod's assets. ```java public static final MeshAccessor MY_MESH = MeshAccessor.create(MyMod.MODID, "entity/my_entity", (jsonModelLoader) -> jsonModelLoader.loadSkinnedMesh(MyMesh::new)); ``` -------------------------------- ### Low-level Controller Access Source: https://epicfight-docs.readthedocs.io/API/Input Demonstrates how to access the EpicFightControllerMod API to get controller input modes and raw bindings. ```java @Nullable IEpicFightControllerMod controllerModApi = EpicFightControllerModProvider.get(); if (controllerModApi == null { // Null if no controller mod integration is available // (i.e., the controller mod is not installed, or Epic Fight does not support it). return; } // Checking the input mode InputMode inputMode = controllerModApi.getInputMode(); boolean supportsController = inputMode.supportsController(); // Getting raw controller binding ControllerBinding moveForward = controllerModApi.getBinding(MinecraftInputAction.MOVE_FORWARD); float analogue = moveForward.getAnalogueNow(); // OR ControllerBinding jump = controllerModApi.getBinding(MinecraftInputAction.JUMP); boolean justPressed = jump.isDigitalJustPressed(); ``` -------------------------------- ### Previous Animation Registration (before 20.9.7) Source: https://epicfight-docs.readthedocs.io/API/Migration Example of how animations were registered directly in older versions of Epic Fight. ```java @Mod.EventBusSubscriber(modid = YourMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) public class YourModAnimations { public static StaticAnimation CUSTOM; @SubscribeEvent public static void registerAnimations(AnimationRegistryEvent event) { event.getRegistryMap().put(YourMod.MOD_ID, Animation::build); } private static void build() { HumanoidArmature biped = Armatures.BIPED; CUSTOM = new StaticAnimation(true, "biped/living/custom", biped); } } ``` -------------------------------- ### Expanding Epic Fight extensible enums Source: https://epicfight-docs.readthedocs.io/API/Utilities Example of creating a custom enum class that extends an existing Epic Fight extensible enum (LivingMotion). ```java public enum MyLivingMotions implements LivingMotion { CRAWL, SKYDIVE, BULLET_RUN; final int id; MyLivingMotions() { // Ids are automatically assigned by Enum Manager this.id = LivingMotion.ENUM_MANAGER.assign(this); } @Override public int universalOrdinal() { // Return universal id for all enums extending LivingMotion return this.id; } } ``` ```java @Mod(MyMod.MODID) public class MyMod { ... public MyMod(FMLJavaModLoadingContext context) { ... LivingMotion.ENUM_MANAGER.registerEnumCls(MyMod.MODID, MyLivingMotions.class); ... } } ``` -------------------------------- ### New Animation Registration (20.9.7 and newer) Source: https://epicfight-docs.readthedocs.io/API/Migration Example of the new way to register animations using AnimationManager and Accessors in newer versions of Epic Fight. ```java import yesman.epicfight.api.animation.AnimationManager; import yesman.epicfight.api.animation.AnimationManager.AnimationAccessor; import yesman.epicfight.api.animation.AnimationManager.AnimationRegistryEvent; import yesman.epicfight.gameasset.Armatures.ArmatureAccessor; @Mod.EventBusSubscriber(modid = YourMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) public class YourModAnimations { public static AnimationAccessor CUSTOM; @SubscribeEvent public static void registerAnimations(AnimationRegistryEvent event) { event.newBuilder(YourMod.MOD_ID, Animation::build); } private static void build(AnimationManager.AnimationBuilder builder) { ArmatureAccessor armatureAccessor = Armatures.BIPED; CUSTOM = builder.nextAccessor("biped/living/custom", (accessor) -> new StaticAnimation(true, accessor, armatureAccessor)); } } ``` -------------------------------- ### Input Actions Source: https://epicfight-docs.readthedocs.io/API/Input Replaces direct use of `KeyMapping` with controller-compatible APIs. ```java - EpicFightKeyMappings.DODGE; // Raw access to KeyMapping, does not support controllers. + EpicFightInputAction.DODGE; // Use raw ".keyMapping()" if really necessary; prefer new supported APIs. ``` -------------------------------- ### BasicAttack Registration Comparison Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 Compares the registration of BasicAttack (now ComboAttacks in 1.21.1) between versions 1.20.1 and 1.21.1. ```java BASIC_ATTACK = modRegistry.build("basic_attack", BasicAttack::new, BasicAttack.createBasicAttackBuilder()); ``` ```java public static final DeferredRegister REGISTRY = DeferredRegister.create(EpicFightRegistries.Keys.SKILL, EpicFightMod.MODID); ... public static final DeferredHolder COMBO_ATTACKS = REGISTRY.register("combo_attacks", key -> ComboAttacks.createComboAttackBuilder().build(key) ); ``` -------------------------------- ### Eviscerate Skill Registration Comparison Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 Compares the registration of the Eviscerate skill, including its properties, between versions 1.20.1 and 1.21.1. ```java WeaponInnateSkill eviscerate = modRegistry.build("eviscerate", EviscerateSkill::new, WeaponInnateSkill.createWeaponInnateBuilder()); eviscerate.newProperty() .addProperty(AttackPhaseProperty.MAX_STRIKES_MODIFIER, ValueModifier.setter(1)) .addProperty(AttackPhaseProperty.IMPACT_MODIFIER, ValueModifier.setter(2.0F)) ... .newProperty() .addProperty(AttackPhaseProperty.MAX_STRIKES_MODIFIER, ValueModifier.setter(1)) .addProperty(AttackPhaseProperty.EXTRA_DAMAGE, Set.of(ExtraDamageInstance.SWEEPING_EDGE_ENCHANTMENT.create(), ExtraDamageInstance.EVISCERATE_LOST_HEALTH.create(0.1F))) ... EVISCERATE = eviscerate; ``` ```java public static final DeferredRegister REGISTRY = DeferredRegister.create(EpicFightRegistries.Keys.SKILL, EpicFightMod.MODID); ... public static final DeferredHolder EVISCERATE = REGISTRY.register("eviscerate", key -> WeaponInnateSkill.createWeaponInnateBuilder(EviscerateSkill::new) .newProperty() .addProperty(AttackPhaseProperty.MAX_STRIKES_MODIFIER, ValueModifier.setter(1)) .addProperty(AttackPhaseProperty.IMPACT_MODIFIER, ValueModifier.setter(2.0F)) ... .newProperty() .addProperty(AttackPhaseProperty.MAX_STRIKES_MODIFIER, ValueModifier.setter(1)) .addProperty(AttackPhaseProperty.EXTRA_DAMAGE, Set.of(ExtraDamageInstance.SWEEPING_EDGE_ENCHANTMENT.create(), ExtraDamageInstance.EVISCERATE_LOST_HEALTH.create(0.1F))) ... .build(key) ); ``` -------------------------------- ### Skill Event Listener Registration Comparison Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 Compares how skill events are registered and removed as listeners between versions 1.20.1 and 1.21.1. ```java public class BerserkerSkill extends PassiveSkill { ... public void onInitiate(SkillContainer container) { super.onInitiate(container); container.getExecutor().getEventListener().addEventListener(EventType.MODIFY_ATTACK_SPEED_EVENT, EVENT_UUID, (event) -> { // Do event tasks... }); ... } public void onRemoved(SkillContainer container) { super.onRemoved(container); container.getExecutor().getEventListener().removeListener(EventType.MODIFY_ATTACK_SPEED_EVENT, EVENT_UUID); ... } ... } ``` ```java public class BerserkerSkill extends PassiveSkill { public void onInitiate(SkillContainer container, EntityEventListener eventListener) { super.onInitiate(container, eventListener); eventListener.registerEvent( EpicFightEventHooks.Entity.MODIFY_ATTACK_SPEED, event -> { // Do event tasks... }, this ); } // public void onRemoved(SkillContainer container), No need to call remove methods, it's fully automated! } ``` -------------------------------- ### Event Cancelation and Context Aware Subscribers Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 Demonstrates how to use `CancelableEventHook` to cancel an event and `ContextAwareEventSubscription` to ensure a subscriber is still triggered even if the event is canceled. ```java EpicFightEventHooks.Entity.TAKE_DAMAGE_INCOME.registerEvent( event -> { if (event.getEntityPatch().getOriginal().getHealth() < 1.0F) { event.cancel(); // Cancel damage incoming event when the targetted entity's health is lower than 1.0 } }, "MyRegistrar", 10 // set priority 10 ); EpicFightEventHooks.Entity.TAKE_DAMAGE_INCOME.registerContextAwareEvent( (event, eventContext) -> { if (event.getEntityPatch().getOriginal().getHealth() < 1.0F && eventContext.isCanceledBy("MyRegistrar")) { event.getEntityPatch().getOriginal().kill(); // Kill the entity if the event is canceled by "MyRegistrar" } }, 1 // set priority 1 ); ``` -------------------------------- ### Creating Custom Event Hooks Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 Shows how to define custom event hooks, including sided event hooks and cancelable event hooks, within a dedicated class. ```java public final class MyEventHooks { // parameterize with your event class public static final EventHook MY_EVENT_HOOK = EventHook.createEventHook(); // subscribers only be triggered in server side even tho it's called in client public static final EventHook MY_SERVER_SIDE_EVENT_HOOK = EventHook.createSidedEventHook(LogicalSide.CLIENT); // Cancelable events allow interrupting the final task of the event public static final CancelableEventHook MY_CANCELABLE_EVENT_HOOK = CancelableEventHook.createEventHook(); // MyLivingEntityEventHook inherits `LivingEntityPatchEvent`, where you can trigger subscribers in `EntityEventListener` public static final EventHook MY_LIVING_ENTITY_EVENT_HOOK = EventHook.createEventHook(); private MyEventHooks() {} // prevents instantiation } ``` -------------------------------- ### Handling Input Actions - Discrete Source: https://epicfight-docs.readthedocs.io/API/Input Used for actions that should trigger once when pressed, such as attacking or dodging. ```java - while (isKeyPressed(EpicFightKeyMappings.ATTACK, true)) { - // ... - } + InputManager.triggerOnPress(EpicFightInputAction.ATTACK, true, (context) -> { + boolean triggeredByController = context.triggeredByController() // Optional context + // ... + }); ``` -------------------------------- ### Comparing Bindings Source: https://epicfight-docs.readthedocs.io/API/Input Determines if two actions share the same physical key or button. ```java - if (EpicFightKeyMappings.WEAPON_INNATE_SKILL.getKey().equals(EpicFightKeyMappings.ATTACK.getKey())) {} + if (InputManager.isBoundToSamePhysicalInput(EpicFightInputAction.WEAPON_INNATE_SKILL, EpicFightInputAction.ATTACK)) {} ``` -------------------------------- ### Checking if a Cancelable Event is Canceled Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 Demonstrates how to post a cancelable event and check its cancellation status. ```java if (!MyEventHooks.MY_CANCELABLE_EVENT_HOOK.post(new MyCancelableEventHook()).isCanceled()) { // Checks if event is canceled // Do tasks when the event is not canceled } ``` -------------------------------- ### Using EntityEventListener to Trigger Attachable Event Listeners Source: https://epicfight-docs.readthedocs.io/API/Porting/Porting-from-1.20.1-to-1.21.1 Illustrates how to trigger event hooks that inherit `LivingEntityPatchEvent` using `postWithListener` with an entity patch's event listener. ```java Entity entity; LivingEntityPatch entityPatch = EpicFightCapabilities.getEntityPatch(entity, LivingEntityPatch.class); // Extracts entity patch from entity MyEventHooks.MY_LIVING_ENTITY_EVENT_HOOK.postWithListener(new MyLivingEntityEventHook(entityPatch), entityPatch.getEventListener()); ``` -------------------------------- ### Handling Input Actions - Continuous Source: https://epicfight-docs.readthedocs.io/API/Input Used for actions that remain active while a key or button is held down, such as guard. ```java - if (minecraft.options.keyAttack.isDown()) {} + if (InputManager.isActionActive(MinecraftInputAction.ATTACK_DESTROY)) {} ``` -------------------------------- ### Player Movement State - Updating state Source: https://epicfight-docs.readthedocs.io/API/Input Updates player movement state using immutable objects for safer and more predictable updates. ```java - Minecraft.getInstance().player.input.jumping = true; // Bad: Mutable, unpredictable, and may not support controllers + final PlayerInputState updated = InputManager.getInputState(Minecraft.getInstance().player) + .withJumping(true); + InputManager.setInputState(updated); ``` -------------------------------- ### Player Movement State - Retrieving Direction Source: https://epicfight-docs.readthedocs.io/API/Input Retrieves player movement direction from input state. ```java - int forward = input.up ? 1 : 0; - int backward = input.down ? -1 : 0; - int left = input.left ? 1 : 0; - int right = input.right ? -1 : 0; - int vertic = forward + backward; - int horizon = left + right; + final MovementDirection movementDirection = MovementDirection.fromInputState(InputManager.getInputState(input)); + final int vertic = movementDirection.vertical(); + final int horizon = movementDirection.horizontal(); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.