mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 05:27:37 +00:00
- Fix Counter infinite recursion
- Tags Get Packet - Cooldowns Resetting on Dimension Change / Teleport
This commit is contained in:
1 parent
1a77728bcd
commit
4a7c7b09c7
4 files changed
+60
-13
No files matched your search
@@ -3,14 +3,21 @@ package kamkeel.npcs.controllers.data.ability.type;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import kamkeel.npcs.addon.DBCAddon;
|
||||
import noppes.npcs.AbstractDataAbilities;
|
||||
import noppes.npcs.controllers.AnimationController;
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.enums.UserType;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.AbilityFieldDefs;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import noppes.npcs.controllers.data.Animation;
|
||||
import noppes.npcs.controllers.data.PlayerData;
|
||||
import noppes.npcs.api.ability.type.IAbilityCounter;
|
||||
import noppes.npcs.client.gui.builder.FieldDef;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -25,6 +32,11 @@ public class AbilityCounter extends AbilityDefend implements IAbilityCounter {
|
||||
private int counterAnimationId = -1;
|
||||
private String counterAnimationName = "Ability_Guard_Counter";
|
||||
|
||||
// True only while this counter is synchronously dispatching its retaliation damage.
|
||||
// Another counter that is hit by that retaliation inspects this flag on the source
|
||||
// entity's active counter to avoid reacting and creating infinite mutual retaliation.
|
||||
private transient boolean retaliating;
|
||||
|
||||
public AbilityCounter() {
|
||||
this.typeId = "ability.cnpc.counter";
|
||||
this.name = "Counter";
|
||||
@@ -60,6 +72,35 @@ public class AbilityCounter extends AbilityDefend implements IAbilityCounter {
|
||||
// DEFEND HOOKS
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
@Override
|
||||
protected boolean isValidDamageSource(DamageSource source) {
|
||||
if (!super.isValidDamageSource(source)) {
|
||||
return false;
|
||||
}
|
||||
// Break counter-vs-counter recursion: if the hit is itself a retaliation
|
||||
// from another counter that is mid-dispatch, don't counter it back.
|
||||
Entity sourceEntity = source.getEntity();
|
||||
AbstractDataAbilities abilities = getAbilitiesOf(sourceEntity);
|
||||
if (abilities != null) {
|
||||
Ability current = abilities.getCurrentAbility();
|
||||
if (current instanceof AbilityCounter && ((AbilityCounter) current).retaliating) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static AbstractDataAbilities getAbilitiesOf(Entity entity) {
|
||||
if (entity instanceof EntityPlayer) {
|
||||
PlayerData pData = PlayerData.get((EntityPlayer) entity);
|
||||
return pData != null ? pData.abilityData : null;
|
||||
}
|
||||
if (entity instanceof EntityNPCInterface) {
|
||||
return ((EntityNPCInterface) entity).abilities;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float performDefend(EntityLivingBase attacker, float amount) {
|
||||
// For PERCENT mode with DBC, use the full DBC-calculated damage, not vanilla base
|
||||
@@ -78,13 +119,24 @@ public class AbilityCounter extends AbilityDefend implements IAbilityCounter {
|
||||
|
||||
// Counter-attack through the standard ability damage pipeline.
|
||||
// DBCAbilityExtender handles DBC stat routing (ignore flags, scaling, etc.) automatically.
|
||||
if (caster != null && attacker.isEntityAlive() && damage > 0) {
|
||||
applyAbilityDamage(caster, attacker, damage, 0);
|
||||
if (caster != null && attacker != null && attacker.isEntityAlive() && damage > 0) {
|
||||
retaliating = true;
|
||||
try {
|
||||
applyAbilityDamage(caster, attacker, damage, 0);
|
||||
} finally {
|
||||
retaliating = false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
retaliating = false;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// OVERRIDES
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ public final class CategoryItemsRequestPacket extends AbstractPacket {
|
||||
|
||||
// Send tag map for the items
|
||||
HashMap<String, HashSet<UUID>> tagMap = getTagMapByCat(type, categoryId);
|
||||
if (tagMap != null && !tagMap.isEmpty()) {
|
||||
if (tagMap != null) {
|
||||
TagController.sendCategoryTagMap((EntityPlayerMP) player, tagMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import io.netty.buffer.ByteBuf;
|
||||
import kamkeel.npcs.network.AbstractPacket;
|
||||
import kamkeel.npcs.network.PacketChannel;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import kamkeel.npcs.network.enums.EnumItemPacketType;
|
||||
import kamkeel.npcs.network.enums.EnumRequestPacket;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
@@ -38,9 +36,6 @@ public final class TagsGetPacket extends AbstractPacket {
|
||||
|
||||
@Override
|
||||
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
|
||||
if (!PacketUtil.verifyItemPacket(packetName, player, EnumItemPacketType.WAND, EnumItemPacketType.CLONER))
|
||||
return;
|
||||
|
||||
NoppesUtilServer.sendTagDataAll((EntityPlayerMP) player);
|
||||
}
|
||||
|
||||
|
||||
@@ -773,21 +773,21 @@ public class PlayerAbilityData extends AbstractDataAbilities implements IPlayerA
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully reset ability state when changing dimensions.
|
||||
* Clears cooldowns so the player can immediately use abilities in the new dimension.
|
||||
* Fully reset transient ability execution state when changing dimensions.
|
||||
* Cooldowns are preserved so dimension changes cannot bypass them.
|
||||
* Keeps active toggles (dimension change shouldn't reset ongoing effects).
|
||||
*/
|
||||
public void resetOnDimensionChange() {
|
||||
trackingAbilityPosition = false;
|
||||
onEntityReconstructed(true, false);
|
||||
onEntityReconstructed(false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset ability state when a large-distance teleport is detected during execution.
|
||||
* Same behavior as dimension change — silent cleanup, clear cooldowns, keep toggles.
|
||||
* Same behavior as dimension change: silent cleanup, preserve cooldowns, keep toggles.
|
||||
*/
|
||||
public void resetOnTeleport() {
|
||||
onEntityReconstructed(true, false);
|
||||
onEntityReconstructed(false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user