From 5ee853c4c82e04ba033ec774f1b1e70a0920c66a Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Sat, 30 May 2020 14:07:46 -0700 Subject: [PATCH] Add ExhaustionEvent.GetExhaustionCap Closes #152 --- .../applecore/api/hunger/ExhaustionEvent.java | 21 +++++++++++++++++++ java/squeek/applecore/asm/Hooks.java | 10 +++++++++ .../applecore/asm/module/ModuleFoodStats.java | 13 ++++++++++++ .../asm/reference/FoodStatsModifications.java | 2 +- .../applecore/example/ExhaustionModifier.java | 16 +++++++++++++- 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/java/squeek/applecore/api/hunger/ExhaustionEvent.java b/java/squeek/applecore/api/hunger/ExhaustionEvent.java index 90e555c..dc96276 100644 --- a/java/squeek/applecore/api/hunger/ExhaustionEvent.java +++ b/java/squeek/applecore/api/hunger/ExhaustionEvent.java @@ -174,4 +174,25 @@ public Exhausted(EntityPlayer player, float exhaustionToRemove, float currentExh deltaHunger = 0; } } + + /** + * Fired every time the exhaustion level is capped to allow control over the cap. + * + * This event is fired in {@link FoodStats#addExhaustion}.
+ *
+ * {@link #exhaustionLevelCap} contains the exhaustion level that will be used to cap the exhaustion level.
+ *
+ * This event is not {@link Cancelable}.
+ *
+ * This event does not have a result. {@link HasResult}
+ */ + public static class GetExhaustionCap extends ExhaustionEvent + { + public float exhaustionLevelCap = 40f; + + public GetExhaustionCap(EntityPlayer player) + { + super(player); + } + } } \ No newline at end of file diff --git a/java/squeek/applecore/asm/Hooks.java b/java/squeek/applecore/asm/Hooks.java index ee82140..2429744 100644 --- a/java/squeek/applecore/asm/Hooks.java +++ b/java/squeek/applecore/asm/Hooks.java @@ -314,6 +314,16 @@ public static float onExhaustionAdded(FoodStats foodStats, float deltaExhaustion return event.deltaExhaustion; } + public static float getExhaustionCap(FoodStats foodStats) + { + verifyFoodStats(foodStats, null); + + EntityPlayer player = ((IAppleCoreFoodStats) foodStats).getPlayer(); + ExhaustionEvent.GetExhaustionCap event = new ExhaustionEvent.GetExhaustionCap(player); + MinecraftForge.EVENT_BUS.post(event); + return event.exhaustionLevelCap; + } + public static float fireExhaustingActionEvent(EntityPlayer player, ExhaustionEvent.ExhaustingActions source, float deltaExhaustion) { ExhaustionEvent.ExhaustingAction event = new ExhaustionEvent.ExhaustingAction(player, source, deltaExhaustion); diff --git a/java/squeek/applecore/asm/module/ModuleFoodStats.java b/java/squeek/applecore/asm/module/ModuleFoodStats.java index 39a13b9..09e3ab3 100644 --- a/java/squeek/applecore/asm/module/ModuleFoodStats.java +++ b/java/squeek/applecore/asm/module/ModuleFoodStats.java @@ -361,6 +361,19 @@ private void hookAddExhaustion(ClassNode classNode, MethodNode addExhaustionMeth toInject.add(new VarInsnNode(FSTORE, 1)); addExhaustionMethodNode.instructions.insertBefore(ASMHelper.findFirstInstruction(addExhaustionMethodNode), toInject); + + // Replace the 40.0f constant with GetExhaustionCap call + InsnList replacement = new InsnList(); + replacement.add(new VarInsnNode(ALOAD, 0)); + replacement.add(new MethodInsnNode(INVOKESTATIC, ASMHelper.toInternalClassName(ASMConstants.HOOKS), "getExhaustionCap", ASMHelper.toMethodDescriptor("F", ASMConstants.FOOD_STATS), false)); + + InsnList needle = new InsnList(); + needle.add(new LdcInsnNode(new Float("40.0"))); + + if (ASMHelper.findAndReplaceAll(addExhaustionMethodNode.instructions, needle, replacement) == 0) + { + throw new RuntimeException("Failed to inject GetExhaustionCap"); + } } private boolean tryAddFieldGetter(ClassNode classNode, String methodName, String fieldName, String fieldDescriptor) diff --git a/java/squeek/applecore/asm/reference/FoodStatsModifications.java b/java/squeek/applecore/asm/reference/FoodStatsModifications.java index 7009c0d..5d4e92d 100644 --- a/java/squeek/applecore/asm/reference/FoodStatsModifications.java +++ b/java/squeek/applecore/asm/reference/FoodStatsModifications.java @@ -67,7 +67,7 @@ public void addExhaustion(float exhaustion) { exhaustion = Hooks.onExhaustionAdded(this, exhaustion); - // the body of the base function + this.foodExhaustionLevel = Math.min(this.foodExhaustionLevel + exhaustion, Hooks.getExhaustionCap(this)); } // start unmodified diff --git a/java/squeek/applecore/example/ExhaustionModifier.java b/java/squeek/applecore/example/ExhaustionModifier.java index da28989..5553e1d 100644 --- a/java/squeek/applecore/example/ExhaustionModifier.java +++ b/java/squeek/applecore/example/ExhaustionModifier.java @@ -1,6 +1,7 @@ package squeek.applecore.example; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import squeek.applecore.api.AppleCoreAPI; import squeek.applecore.api.hunger.ExhaustionEvent; public class ExhaustionModifier @@ -17,6 +18,8 @@ public void onExhausted(ExhaustionEvent.Exhausted event) // this will enable hunger loss in peaceful difficulty if (event.player.getFoodStats().getSaturationLevel() <= 0) event.deltaHunger = -1; + + AppleCoreExample.LOG.info("onExhausted exhaustion=" + AppleCoreAPI.accessor.getExhaustion(event.player)); } @SubscribeEvent @@ -29,10 +32,21 @@ public void onExhaustionAddition(ExhaustionEvent.ExhaustionAddition event) @SubscribeEvent public void onExhaustingAction(ExhaustionEvent.ExhaustingAction event) { - if (event.source == ExhaustionEvent.ExhaustingActions.NORMAL_JUMP || event.source == ExhaustionEvent.ExhaustingActions.SPRINTING_JUMP) + if (event.source == ExhaustionEvent.ExhaustingActions.NORMAL_JUMP) { // random exhaustion each jump event.deltaExhaustion *= Math.random(); } + else if (event.source == ExhaustionEvent.ExhaustingActions.SPRINTING_JUMP) + { + // note: this is over the default cap of 40, but also over the modified cap + event.deltaExhaustion = 100.0f; + } + } + + @SubscribeEvent + public void getExhaustionCap(ExhaustionEvent.GetExhaustionCap event) + { + event.exhaustionLevelCap = 90.0f; } } \ No newline at end of file