Punchy Fix
A Forge 1.20.1‑side client‑only add‑on mod. When a Java‑based mod or KubeJS 6 script calls the player‑arm‑swing method (LivingEntity.swing(), including KubeJS’s player.swing()), this mod makes the closed‑source Punchy mod play its normal‑item‑use interact animation, instead of doing nothing or triggering an attack animation.
Mechanism
- KubeJS 6’s
player.swing()ultimately invokesLivingEntity.swing(hand, true). - Punchy itself mixes‑into this method; a normal swing is recorded by Punchy as an attack.
- This mod intercepts
swing()beforehand with a higher‑priority Mixin (priority 1500). If it confirms that the swing is not an attack, mining action, or a tracked item‑use action, it writes aUSE_ITEMtrigger into Punchy’sUseActionTracker. Once Punchy’sUseItemStateMachinereceives this trigger, it will play the normal‑item‑use animation. Punchy’s own swing‑related mixin, upon detecting an existing use trigger, will no‑longer mark this swing as an attack. - Guard conditions: Swing echoes occurring within 1 second after a client‑side attack request or a mining request will not be bridged, to prevent genuine attacks / mining actions from being misidentified as item‑use actions. No suppression is applied to item‑use events: every
swing()call reaching the client will trigger the use animation, and rapid repeated clicks will be interrupted and restarted by Punchy’s native animation logic.
KubeJS Usage
ItemEvents.rightClick(event=>{
let player = event.player;
player.swing(); // Arm‑swing animation will play successfully
})
Calls to player.swing(hand) from any Java mod will also be bridged automatically, requiring no extra API dependency on this mod.

