Skip to content

Commit 4a7c7b0

Browse files
committed
- Fix Counter infinite recursion
- Tags Get Packet - Cooldowns Resetting on Dimension Change / Teleport
1 parent 1a77728 commit 4a7c7b0

4 files changed

Lines changed: 60 additions & 13 deletions

File tree

src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCounter.java

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,21 @@
33
import cpw.mods.fml.relauncher.Side;
44
import cpw.mods.fml.relauncher.SideOnly;
55
import kamkeel.npcs.addon.DBCAddon;
6+
import noppes.npcs.AbstractDataAbilities;
67
import noppes.npcs.controllers.AnimationController;
8+
import kamkeel.npcs.controllers.data.ability.Ability;
79
import kamkeel.npcs.controllers.data.ability.enums.UserType;
810
import kamkeel.npcs.controllers.data.ability.gui.AbilityFieldDefs;
11+
import net.minecraft.entity.Entity;
912
import net.minecraft.entity.EntityLivingBase;
13+
import net.minecraft.entity.player.EntityPlayer;
1014
import net.minecraft.nbt.NBTTagCompound;
15+
import net.minecraft.util.DamageSource;
1116
import noppes.npcs.controllers.data.Animation;
17+
import noppes.npcs.controllers.data.PlayerData;
1218
import noppes.npcs.api.ability.type.IAbilityCounter;
1319
import noppes.npcs.client.gui.builder.FieldDef;
20+
import noppes.npcs.entity.EntityNPCInterface;
1421

1522
import java.util.Arrays;
1623
import java.util.List;
@@ -25,6 +32,11 @@ public class AbilityCounter extends AbilityDefend implements IAbilityCounter {
2532
private int counterAnimationId = -1;
2633
private String counterAnimationName = "Ability_Guard_Counter";
2734

35+
// True only while this counter is synchronously dispatching its retaliation damage.
36+
// Another counter that is hit by that retaliation inspects this flag on the source
37+
// entity's active counter to avoid reacting and creating infinite mutual retaliation.
38+
private transient boolean retaliating;
39+
2840
public AbilityCounter() {
2941
this.typeId = "ability.cnpc.counter";
3042
this.name = "Counter";
@@ -60,6 +72,35 @@ public String toString() {
6072
// DEFEND HOOKS
6173
// ═══════════════════════════════════════════════════════════════════
6274

75+
@Override
76+
protected boolean isValidDamageSource(DamageSource source) {
77+
if (!super.isValidDamageSource(source)) {
78+
return false;
79+
}
80+
// Break counter-vs-counter recursion: if the hit is itself a retaliation
81+
// from another counter that is mid-dispatch, don't counter it back.
82+
Entity sourceEntity = source.getEntity();
83+
AbstractDataAbilities abilities = getAbilitiesOf(sourceEntity);
84+
if (abilities != null) {
85+
Ability current = abilities.getCurrentAbility();
86+
if (current instanceof AbilityCounter && ((AbilityCounter) current).retaliating) {
87+
return false;
88+
}
89+
}
90+
return true;
91+
}
92+
93+
private static AbstractDataAbilities getAbilitiesOf(Entity entity) {
94+
if (entity instanceof EntityPlayer) {
95+
PlayerData pData = PlayerData.get((EntityPlayer) entity);
96+
return pData != null ? pData.abilityData : null;
97+
}
98+
if (entity instanceof EntityNPCInterface) {
99+
return ((EntityNPCInterface) entity).abilities;
100+
}
101+
return null;
102+
}
103+
63104
@Override
64105
protected float performDefend(EntityLivingBase attacker, float amount) {
65106
// For PERCENT mode with DBC, use the full DBC-calculated damage, not vanilla base
@@ -78,13 +119,24 @@ protected float performDefend(EntityLivingBase attacker, float amount) {
78119

79120
// Counter-attack through the standard ability damage pipeline.
80121
// DBCAbilityExtender handles DBC stat routing (ignore flags, scaling, etc.) automatically.
81-
if (caster != null && attacker.isEntityAlive() && damage > 0) {
82-
applyAbilityDamage(caster, attacker, damage, 0);
122+
if (caster != null && attacker != null && attacker.isEntityAlive() && damage > 0) {
123+
retaliating = true;
124+
try {
125+
applyAbilityDamage(caster, attacker, damage, 0);
126+
} finally {
127+
retaliating = false;
128+
}
83129
}
84130

85131
return 0;
86132
}
87133

134+
@Override
135+
public void reset() {
136+
super.reset();
137+
retaliating = false;
138+
}
139+
88140
// ═══════════════════════════════════════════════════════════════════
89141
// OVERRIDES
90142
// ═══════════════════════════════════════════════════════════════════

src/main/java/kamkeel/npcs/network/packets/request/category/CategoryItemsRequestPacket.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
7373

7474
// Send tag map for the items
7575
HashMap<String, HashSet<UUID>> tagMap = getTagMapByCat(type, categoryId);
76-
if (tagMap != null && !tagMap.isEmpty()) {
76+
if (tagMap != null) {
7777
TagController.sendCategoryTagMap((EntityPlayerMP) player, tagMap);
7878
}
7979
}

src/main/java/kamkeel/npcs/network/packets/request/tags/TagsGetPacket.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import kamkeel.npcs.network.AbstractPacket;
77
import kamkeel.npcs.network.PacketChannel;
88
import kamkeel.npcs.network.PacketHandler;
9-
import kamkeel.npcs.network.PacketUtil;
10-
import kamkeel.npcs.network.enums.EnumItemPacketType;
119
import kamkeel.npcs.network.enums.EnumRequestPacket;
1210
import net.minecraft.entity.player.EntityPlayer;
1311
import net.minecraft.entity.player.EntityPlayerMP;
@@ -38,9 +36,6 @@ public void sendData(ByteBuf out) throws IOException {
3836

3937
@Override
4038
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
41-
if (!PacketUtil.verifyItemPacket(packetName, player, EnumItemPacketType.WAND, EnumItemPacketType.CLONER))
42-
return;
43-
4439
NoppesUtilServer.sendTagDataAll((EntityPlayerMP) player);
4540
}
4641

src/main/java/noppes/npcs/controllers/data/PlayerAbilityData.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -773,21 +773,21 @@ public void onEntityReconstructed(boolean clearCooldowns, boolean clearToggles)
773773
}
774774

775775
/**
776-
* Fully reset ability state when changing dimensions.
777-
* Clears cooldowns so the player can immediately use abilities in the new dimension.
776+
* Fully reset transient ability execution state when changing dimensions.
777+
* Cooldowns are preserved so dimension changes cannot bypass them.
778778
* Keeps active toggles (dimension change shouldn't reset ongoing effects).
779779
*/
780780
public void resetOnDimensionChange() {
781781
trackingAbilityPosition = false;
782-
onEntityReconstructed(true, false);
782+
onEntityReconstructed(false, false);
783783
}
784784

785785
/**
786786
* Reset ability state when a large-distance teleport is detected during execution.
787-
* Same behavior as dimension changesilent cleanup, clear cooldowns, keep toggles.
787+
* Same behavior as dimension change: silent cleanup, preserve cooldowns, keep toggles.
788788
*/
789789
public void resetOnTeleport() {
790-
onEntityReconstructed(true, false);
790+
onEntityReconstructed(false, false);
791791
}
792792

793793
/**

0 commit comments

Comments
 (0)