mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 04:57:27 +00:00
Add Max to Energy Entities to prevent any long-term issues / errors
This commit is contained in:
1 parent
e330b517a8
commit
6fdf9daf24
21 files changed
+102
-48
No files matched your search
@@ -47,6 +47,10 @@ public class EnergyLifespanData implements IEnergyLifespanData {
|
||||
public void readNBT(NBTTagCompound nbt) {
|
||||
maxDistance = nbt.getFloat("maxDistance");
|
||||
maxLifetime = nbt.getInteger("maxLifetime");
|
||||
|
||||
// Sanitize: ensure minimum values so entities don't die instantly or live forever
|
||||
if (Float.isNaN(maxDistance) || Float.isInfinite(maxDistance) || maxDistance <= 0) maxDistance = 150.0f;
|
||||
if (maxLifetime <= 0) maxLifetime = 200;
|
||||
}
|
||||
|
||||
public EnergyLifespanData copy() {
|
||||
|
||||
@@ -184,12 +184,12 @@ public class AbilityBeam extends AbilityEnergyProjectile<EntityAbilityBeam> impl
|
||||
defs.add(FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback));
|
||||
defs.add(FieldDef.section("ability.section.beam"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("ability.beamWidth", this::getBeamWidth, this::setBeamWidth),
|
||||
FieldDef.floatField("ability.headSize", this::getHeadSize, this::setHeadSize)
|
||||
FieldDef.floatField("ability.beamWidth", this::getBeamWidth, this::setBeamWidth).range(0.1f, 100.0f),
|
||||
FieldDef.floatField("ability.headSize", this::getHeadSize, this::setHeadSize).range(0.1f, 100.0f)
|
||||
));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime)
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance).range(1.0f, 500.0f),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).range(1, 1200)
|
||||
));
|
||||
defs.add(FieldDef.section("ability.section.homing"));
|
||||
defs.add(FieldDef.boolField("gui.enabled", this::isHoming, this::setHoming).hover("ability.hover.homing"));
|
||||
|
||||
@@ -208,14 +208,14 @@ public class AbilityDisc extends AbilityEnergyProjectile<EntityAbilityDisc> impl
|
||||
defs.add(FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback));
|
||||
defs.add(FieldDef.section("ability.section.disc"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("gui.radius", this::getDiscRadius, this::setDiscRadius),
|
||||
FieldDef.floatField("gui.thickness", this::getDiscThickness, this::setDiscThickness)
|
||||
FieldDef.floatField("gui.radius", this::getDiscRadius, this::setDiscRadius).range(0.1f, 100.0f),
|
||||
FieldDef.floatField("gui.thickness", this::getDiscThickness, this::setDiscThickness).range(0.05f, 100.0f)
|
||||
));
|
||||
defs.add(FieldDef.boolField("ability.vertical", this::isVertical, this::setVertical)
|
||||
.hover("ability.hover.vertical"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime)
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance).range(1.0f, 500.0f),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).range(1, 1200)
|
||||
));
|
||||
defs.add(FieldDef.section("ability.section.homing"));
|
||||
defs.add(FieldDef.boolField("gui.enabled", this::isHoming, this::setHoming).hover("ability.hover.homing"));
|
||||
|
||||
@@ -132,7 +132,7 @@ public class AbilityDome extends AbilityEnergyBarrier {
|
||||
@Override
|
||||
protected void addBarrierTypeDefinitions(List<FieldDef> defs) {
|
||||
defs.add(FieldDef.floatField("ability.domeRadius", this::getDomeRadius, this::setDomeRadius)
|
||||
.range(1.0f, 30.0f));
|
||||
.range(1.0f, 50.0f));
|
||||
defs.add(FieldDef.boolField("ability.followCaster", this::isFollowCaster, this::setFollowCaster)
|
||||
.hover("ability.hover.followCaster"));
|
||||
}
|
||||
|
||||
+1
-1
@@ -247,7 +247,7 @@ public abstract class AbilityEnergyBarrier extends AbilityEnergy {
|
||||
.visibleWhen(this::isUseHealth));
|
||||
defs.add(FieldDef.boolField("ability.useDuration", this::isUseDuration, this::setUseDuration));
|
||||
defs.add(FieldDef.intField("ability.duration", this::getBarrierDuration, this::setBarrierDuration)
|
||||
.range(1, 6000).visibleWhen(this::isUseDuration));
|
||||
.range(1, 12000).visibleWhen(this::isUseDuration));
|
||||
defs.add(FieldDef.floatField("ability.defaultMultiplier", this::getDefaultMultiplier, this::setDefaultMultiplier));
|
||||
|
||||
// Knockback section
|
||||
|
||||
+5
-5
@@ -218,14 +218,14 @@ public class AbilityLaserShot extends AbilityEnergyProjectile<EntityAbilityLaser
|
||||
));
|
||||
defs.add(FieldDef.section("ability.section.beam"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("ability.laserWidth", this::getLaserWidth, this::setLaserWidth),
|
||||
FieldDef.floatField("ability.expansionSpeed", this::getExpansionSpeed, this::setExpansionSpeed)
|
||||
FieldDef.floatField("ability.laserWidth", this::getLaserWidth, this::setLaserWidth).range(0.1f, 100.0f),
|
||||
FieldDef.floatField("ability.expansionSpeed", this::getExpansionSpeed, this::setExpansionSpeed).range(0.1f, 50.0f)
|
||||
));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.intField("ability.lingerTicks", this::getLingerTicks, this::setLingerTicks),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime)
|
||||
FieldDef.intField("ability.lingerTicks", this::getLingerTicks, this::setLingerTicks).range(1, 200),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).range(1, 1200)
|
||||
));
|
||||
defs.add(FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance));
|
||||
defs.add(FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance).range(1.0f, 500.0f));
|
||||
defs.add(FieldDef.boolField("ability.dieOnImpact", this::isDieOnImpact, this::setDieOnImpact));
|
||||
defs.add(FieldDef.section("ability.section.explosive"));
|
||||
defs.add(FieldDef.boolField("gui.enabled", this::isExplosive, this::setExplosive).hover("ability.hover.explosive"));
|
||||
|
||||
@@ -172,12 +172,12 @@ public class AbilityOrb extends AbilityEnergyProjectile<EntityAbilityOrb> implem
|
||||
FieldDef.floatField("stats.speed", this::getOrbSpeed, this::setOrbSpeed)
|
||||
));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("stats.size", this::getOrbSize, this::setOrbSize),
|
||||
FieldDef.floatField("stats.size", this::getOrbSize, this::setOrbSize).range(0.1f, 100.0f),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback)
|
||||
));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime)
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance).range(1.0f, 500.0f),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).range(1, 1200)
|
||||
));
|
||||
defs.add(FieldDef.section("ability.section.homing"));
|
||||
defs.add(FieldDef.boolField("gui.enabled", this::isHoming, this::setHoming).hover("ability.hover.homing"));
|
||||
|
||||
@@ -145,8 +145,8 @@ public class AbilityShield extends AbilityEnergyBarrier {
|
||||
@Override
|
||||
protected void addBarrierTypeDefinitions(List<FieldDef> defs) {
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("gui.width", this::getShieldWidth, this::setShieldWidth).range(0.5f, 10.0f),
|
||||
FieldDef.floatField("gui.height", this::getShieldHeight, this::setShieldHeight).range(0.5f, 10.0f)
|
||||
FieldDef.floatField("gui.width", this::getShieldWidth, this::setShieldWidth).range(0.5f, 100.0f),
|
||||
FieldDef.floatField("gui.height", this::getShieldHeight, this::setShieldHeight).range(0.5f, 100.0f)
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -183,14 +183,14 @@ public class AbilitySlicer extends AbilityEnergyProjectile<EntityEnergySlicer> {
|
||||
defs.add(FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback));
|
||||
defs.add(FieldDef.section("ability.section.slicer"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("gui.width", this::getSliceWidth, this::setSliceWidth).range(0.5f, 20.0f),
|
||||
FieldDef.floatField("gui.thickness", this::getSliceThickness, this::setSliceThickness).range(0.05f, 2.0f)
|
||||
FieldDef.floatField("gui.width", this::getSliceWidth, this::setSliceWidth).range(0.5f, 100.0f),
|
||||
FieldDef.floatField("gui.thickness", this::getSliceThickness, this::setSliceThickness).range(0.05f, 100.0f)
|
||||
));
|
||||
defs.add(FieldDef.boolField("ability.piercing", this::isPiercing, this::setPiercing)
|
||||
.hover("ability.hover.piercing"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime)
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance).range(1.0f, 500.0f),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).range(1, 1200)
|
||||
));
|
||||
defs.add(FieldDef.section("ability.section.explosive"));
|
||||
defs.add(FieldDef.boolField("gui.enabled", this::isExplosive, this::setExplosive).hover("ability.hover.explosive"));
|
||||
|
||||
@@ -260,14 +260,14 @@ public class AbilitySweeper extends AbilityEnergy implements IAbilitySweeper {
|
||||
),
|
||||
FieldDef.section("ability.section.beam"),
|
||||
FieldDef.row(
|
||||
FieldDef.floatField("gui.length", this::getBeamLength, this::setBeamLength),
|
||||
FieldDef.floatField("gui.width", this::getBeamWidth, this::setBeamWidth)
|
||||
FieldDef.floatField("gui.length", this::getBeamLength, this::setBeamLength).range(0.5f, 100.0f),
|
||||
FieldDef.floatField("gui.width", this::getBeamWidth, this::setBeamWidth).range(0.1f, 100.0f)
|
||||
),
|
||||
FieldDef.row(
|
||||
FieldDef.floatField("gui.height", this::getBeamHeight, this::setBeamHeight),
|
||||
FieldDef.floatField("ability.sweepSpeed", this::getSweepSpeed, this::setSweepSpeed)
|
||||
FieldDef.floatField("gui.height", this::getBeamHeight, this::setBeamHeight).range(0.1f, 100.0f),
|
||||
FieldDef.floatField("ability.sweepSpeed", this::getSweepSpeed, this::setSweepSpeed).range(0.1f, 30.0f)
|
||||
),
|
||||
FieldDef.intField("ability.rotations", this::getNumberOfRotations, this::setNumberOfRotations),
|
||||
FieldDef.intField("ability.rotations", this::getNumberOfRotations, this::setNumberOfRotations).range(1, 20),
|
||||
FieldDef.row(
|
||||
FieldDef.boolField("ability.piercing", this::isPiercing, this::setPiercing)
|
||||
.hover("ability.hover.piercing"),
|
||||
|
||||
@@ -205,8 +205,8 @@ public class AbilityWall extends AbilityEnergyBarrier {
|
||||
protected void addBarrierTypeDefinitions(List<FieldDef> defs) {
|
||||
defs.add(FieldDef.section("ability.section.panel"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.floatField("gui.width", this::getPanelWidth, this::setPanelWidth).range(0.5f, 20.0f),
|
||||
FieldDef.floatField("gui.height", this::getPanelHeight, this::setPanelHeight).range(0.5f, 20.0f)
|
||||
FieldDef.floatField("gui.width", this::getPanelWidth, this::setPanelWidth).range(0.5f, 100.0f),
|
||||
FieldDef.floatField("gui.height", this::getPanelHeight, this::setPanelHeight).range(0.5f, 100.0f)
|
||||
));
|
||||
defs.add(FieldDef.floatField("ability.heightOffset", this::getHeightOffset, this::setHeightOffset)
|
||||
.min(Float.NEGATIVE_INFINITY));
|
||||
|
||||
@@ -694,8 +694,8 @@ public class EntityAbilityBeam extends EntityEnergyProjectile {
|
||||
|
||||
@Override
|
||||
protected void readProjectileNBT(NBTTagCompound nbt) {
|
||||
this.beamWidth = nbt.hasKey("BeamWidth") ? nbt.getFloat("BeamWidth") : 0.3f;
|
||||
this.headSize = nbt.hasKey("HeadSize") ? nbt.getFloat("HeadSize") : 0.5f;
|
||||
this.beamWidth = sanitize(nbt.hasKey("BeamWidth") ? nbt.getFloat("BeamWidth") : 0.3f, 0.3f, MAX_ENTITY_SIZE);
|
||||
this.headSize = sanitize(nbt.hasKey("HeadSize") ? nbt.getFloat("HeadSize") : 0.5f, 0.5f, MAX_ENTITY_SIZE);
|
||||
this.headOffsetX = nbt.hasKey("HeadOffsetX") ? nbt.getDouble("HeadOffsetX") : 0;
|
||||
this.headOffsetY = nbt.hasKey("HeadOffsetY") ? nbt.getDouble("HeadOffsetY") : 0;
|
||||
this.headOffsetZ = nbt.hasKey("HeadOffsetZ") ? nbt.getDouble("HeadOffsetZ") : 0;
|
||||
|
||||
@@ -38,6 +38,9 @@ public class EntityAbilityDisc extends EntityEnergyProjectile {
|
||||
// Disc shape properties
|
||||
private float discRadius = 1.0f; // Width of disc
|
||||
private float discThickness = 0.2f; // Height of disc
|
||||
|
||||
// Boomerang owner-gone tracking
|
||||
private int returnOwnerNullTicks = 0;
|
||||
private boolean vertical = false; // false = horizontal (flat), true = vertical (thin edge forward)
|
||||
|
||||
// Charging state (disc-specific target sizes)
|
||||
@@ -274,6 +277,7 @@ public class EntityAbilityDisc extends EntityEnergyProjectile {
|
||||
if (returning) {
|
||||
Entity owner = getOwnerEntity();
|
||||
if (owner != null) {
|
||||
returnOwnerNullTicks = 0;
|
||||
double distToOwner = Math.sqrt(
|
||||
(posX - owner.posX) * (posX - owner.posX) +
|
||||
(posY - owner.posY) * (posY - owner.posY) +
|
||||
@@ -281,8 +285,9 @@ public class EntityAbilityDisc extends EntityEnergyProjectile {
|
||||
);
|
||||
return distToOwner < 1.5;
|
||||
}
|
||||
// Owner gone but returning - keep going toward last known position
|
||||
return false;
|
||||
// Owner gone while returning - grace period then die
|
||||
returnOwnerNullTicks++;
|
||||
return returnOwnerNullTicks > 100;
|
||||
}
|
||||
|
||||
// Not returning yet - don't die from distance (we'll trigger return above)
|
||||
@@ -487,8 +492,8 @@ public class EntityAbilityDisc extends EntityEnergyProjectile {
|
||||
protected void readProjectileNBT(NBTTagCompound nbt) {
|
||||
this.boomerang = nbt.hasKey("Boomerang") && nbt.getBoolean("Boomerang");
|
||||
this.boomerangDelay = nbt.hasKey("BoomerangDelay") ? nbt.getInteger("BoomerangDelay") : 40;
|
||||
this.discRadius = nbt.hasKey("DiscRadius") ? nbt.getFloat("DiscRadius") : 1.0f;
|
||||
this.discThickness = nbt.hasKey("DiscThickness") ? nbt.getFloat("DiscThickness") : 0.2f;
|
||||
this.discRadius = sanitize(nbt.hasKey("DiscRadius") ? nbt.getFloat("DiscRadius") : 1.0f, 1.0f, MAX_ENTITY_SIZE);
|
||||
this.discThickness = sanitize(nbt.hasKey("DiscThickness") ? nbt.getFloat("DiscThickness") : 0.2f, 0.2f, MAX_ENTITY_SIZE);
|
||||
this.vertical = nbt.hasKey("Vertical") ? nbt.getBoolean("Vertical") : false;
|
||||
this.returning = nbt.hasKey("Returning") && nbt.getBoolean("Returning");
|
||||
// Charging state (common fields handled by base)
|
||||
|
||||
@@ -473,7 +473,7 @@ public class EntityAbilityLaser extends EntityEnergyProjectile {
|
||||
|
||||
@Override
|
||||
protected void readProjectileNBT(NBTTagCompound nbt) {
|
||||
this.laserWidth = nbt.hasKey("LaserWidth") ? nbt.getFloat("LaserWidth") : 0.2f;
|
||||
this.laserWidth = sanitize(nbt.hasKey("LaserWidth") ? nbt.getFloat("LaserWidth") : 0.2f, 0.2f, MAX_ENTITY_SIZE);
|
||||
this.expansionSpeed = nbt.hasKey("ExpansionSpeed") ? nbt.getFloat("ExpansionSpeed") : 2.0f;
|
||||
this.lingerTicks = nbt.hasKey("LingerTicks") ? nbt.getInteger("LingerTicks") : 10;
|
||||
this.dieOnImpact = nbt.getBoolean("DieOnImpact");
|
||||
|
||||
@@ -129,6 +129,12 @@ public class EntityAbilitySweeper extends EntityEnergyAbility {
|
||||
return;
|
||||
}
|
||||
|
||||
// Absolute hard lifetime cap (safety net)
|
||||
if (ticksExisted > HARD_LIFETIME_CAP) {
|
||||
this.setDead();
|
||||
return;
|
||||
}
|
||||
|
||||
Entity owner = getOwnerEntity();
|
||||
if (owner != null && owner.isDead) {
|
||||
this.setDead();
|
||||
@@ -330,9 +336,9 @@ public class EntityAbilitySweeper extends EntityEnergyAbility {
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
readEnergyBaseNBT(nbt);
|
||||
this.beamLength = nbt.getFloat("BeamLength");
|
||||
this.beamWidth = nbt.getFloat("BeamWidth");
|
||||
this.beamHeight = nbt.getFloat("BeamHeight");
|
||||
this.beamLength = sanitize(nbt.getFloat("BeamLength"), 10.0f, MAX_ENTITY_SIZE);
|
||||
this.beamWidth = sanitize(nbt.getFloat("BeamWidth"), 0.3f, MAX_ENTITY_SIZE);
|
||||
this.beamHeight = sanitize(nbt.getFloat("BeamHeight"), 0.8f, MAX_ENTITY_SIZE);
|
||||
this.sweepSpeed = nbt.getFloat("SweepSpeed");
|
||||
this.numberOfRotations = nbt.getInteger("NumRotations");
|
||||
this.completedRotations = nbt.getInteger("CompletedRotations");
|
||||
|
||||
@@ -18,6 +18,13 @@ import net.minecraft.world.World;
|
||||
*/
|
||||
public abstract class EntityEnergyAbility extends Entity implements IEntityAdditionalSpawnData {
|
||||
|
||||
// ==================== SAFETY CONSTANTS ====================
|
||||
protected static final int CHARGE_TIMEOUT_GRACE = 60; // Ticks of grace after charge should have ended
|
||||
protected static final int HARD_LIFETIME_CAP = 1200; // 60 seconds absolute max for projectiles/sweepers
|
||||
protected static final int BARRIER_HARD_LIFETIME_CAP = 12000; // 10 minutes absolute max for barriers
|
||||
protected static final float MAX_ENTITY_SIZE = 100.0f; // Max size/width/length for any energy entity
|
||||
protected static final float MAX_ENTITY_RADIUS = 50.0f; // Max radius for dome barriers
|
||||
|
||||
// ==================== VISUAL PROPERTIES ====================
|
||||
protected EnergyDisplayData displayData = new EnergyDisplayData();
|
||||
protected EnergyLightningData lightningData = new EnergyLightningData();
|
||||
@@ -272,6 +279,17 @@ public abstract class EntityEnergyAbility extends Entity implements IEntityAddit
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// ==================== SAFETY HELPERS ====================
|
||||
|
||||
/**
|
||||
* Sanitize a float value loaded from NBT or external sources.
|
||||
* Guards against NaN, Infinity, negative values, and values exceeding a max.
|
||||
*/
|
||||
protected static float sanitize(float value, float fallback, float max) {
|
||||
if (Float.isNaN(value) || Float.isInfinite(value) || value < 0) return fallback;
|
||||
return Math.min(value, max);
|
||||
}
|
||||
|
||||
// ==================== NBT HELPERS ====================
|
||||
|
||||
/**
|
||||
|
||||
@@ -174,6 +174,13 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Absolute hard lifetime cap (safety net for barriers with no duration)
|
||||
if (ticksAlive > BARRIER_HARD_LIFETIME_CAP) {
|
||||
onBarrierDestroyed();
|
||||
this.setDead();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reset hit flash
|
||||
if (getHitFlash() > 0) {
|
||||
setHitFlash((byte) (getHitFlash() - 1));
|
||||
|
||||
@@ -216,8 +216,8 @@ public class EntityEnergyDome extends EntityEnergyBarrier {
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
readBarrierBaseNBT(nbt);
|
||||
this.domeRadius = nbt.getFloat("DomeRadius");
|
||||
this.targetDomeRadius = nbt.hasKey("TargetDomeRadius") ? nbt.getFloat("TargetDomeRadius") : domeRadius;
|
||||
this.domeRadius = sanitize(nbt.getFloat("DomeRadius"), 5.0f, MAX_ENTITY_RADIUS);
|
||||
this.targetDomeRadius = sanitize(nbt.hasKey("TargetDomeRadius") ? nbt.getFloat("TargetDomeRadius") : domeRadius, 5.0f, MAX_ENTITY_RADIUS);
|
||||
this.followCaster = nbt.hasKey("FollowCaster") && nbt.getBoolean("FollowCaster");
|
||||
}
|
||||
|
||||
|
||||
@@ -365,8 +365,10 @@ public class EntityEnergyPanel extends EntityEnergyBarrier {
|
||||
this.mode = (modeOrdinal >= 0 && modeOrdinal < PanelMode.values().length)
|
||||
? PanelMode.values()[modeOrdinal] : PanelMode.PLACED;
|
||||
panelData.readNBT(nbt);
|
||||
this.targetPanelWidth = nbt.hasKey("TargetPanelWidth") ? nbt.getFloat("TargetPanelWidth") : panelData.panelWidth;
|
||||
this.targetPanelHeight = nbt.hasKey("TargetPanelHeight") ? nbt.getFloat("TargetPanelHeight") : panelData.panelHeight;
|
||||
panelData.panelWidth = Math.min(panelData.panelWidth, MAX_ENTITY_SIZE);
|
||||
panelData.panelHeight = Math.min(panelData.panelHeight, MAX_ENTITY_SIZE);
|
||||
this.targetPanelWidth = sanitize(nbt.hasKey("TargetPanelWidth") ? nbt.getFloat("TargetPanelWidth") : panelData.panelWidth, 3.0f, MAX_ENTITY_SIZE);
|
||||
this.targetPanelHeight = sanitize(nbt.hasKey("TargetPanelHeight") ? nbt.getFloat("TargetPanelHeight") : panelData.panelHeight, 3.0f, MAX_ENTITY_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -219,6 +219,18 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
|
||||
}
|
||||
}
|
||||
|
||||
// Charging timeout - if charge phase exceeded with grace period, force kill
|
||||
if (isCharging() && chargeTick > chargeDuration + CHARGE_TIMEOUT_GRACE) {
|
||||
this.setDead();
|
||||
return;
|
||||
}
|
||||
|
||||
// Absolute hard lifetime cap (safety net for any stuck state)
|
||||
if (ticksExisted > HARD_LIFETIME_CAP) {
|
||||
this.setDead();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set death time on first tick if not already set (handles chunk load/unload)
|
||||
// Skip during charging phase - lifetime starts when the entity actually fires
|
||||
if (deathWorldTime < 0 && worldObj != null && !isCharging()) {
|
||||
@@ -911,7 +923,7 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
|
||||
protected void readBaseNBT(NBTTagCompound nbt) {
|
||||
readEnergyBaseNBT(nbt);
|
||||
|
||||
this.size = nbt.getFloat("Size");
|
||||
this.size = sanitize(nbt.getFloat("Size"), 1.0f, MAX_ENTITY_SIZE);
|
||||
|
||||
// Read effects list
|
||||
this.effects.clear();
|
||||
|
||||
@@ -328,8 +328,8 @@ public class EntityEnergySlicer extends EntityEnergyProjectile {
|
||||
@Override
|
||||
protected void readProjectileNBT(NBTTagCompound nbt) {
|
||||
readChargingNBT(nbt);
|
||||
this.sliceWidth = nbt.hasKey("SliceWidth") ? nbt.getFloat("SliceWidth") : 3.0f;
|
||||
this.sliceThickness = nbt.hasKey("SliceThickness") ? nbt.getFloat("SliceThickness") : 0.15f;
|
||||
this.sliceWidth = sanitize(nbt.hasKey("SliceWidth") ? nbt.getFloat("SliceWidth") : 3.0f, 3.0f, MAX_ENTITY_SIZE);
|
||||
this.sliceThickness = sanitize(nbt.hasKey("SliceThickness") ? nbt.getFloat("SliceThickness") : 0.15f, 0.15f, MAX_ENTITY_SIZE);
|
||||
this.piercing = !nbt.hasKey("Piercing") || nbt.getBoolean("Piercing");
|
||||
this.targetSliceWidth = nbt.hasKey("TargetSliceWidth") ? nbt.getFloat("TargetSliceWidth") : sliceWidth;
|
||||
this.targetSliceThickness = nbt.hasKey("TargetSliceThickness") ? nbt.getFloat("TargetSliceThickness") : sliceThickness;
|
||||
|
||||
Reference in new issue
Block a user