mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 05:27:37 +00:00
Merge branch 'dev' of https://github.com/KAMKEEL/CustomNPC-Plus into dev
This commit is contained in:
commit
f832b3bf2d
5 files changed
+157
-4
No files matched your search
+15
@@ -10,6 +10,7 @@ import kamkeel.npcs.controllers.data.ability.data.energy.EnergyDisplayData;
|
||||
import kamkeel.npcs.controllers.data.ability.data.energy.EnergyHomingData;
|
||||
import kamkeel.npcs.controllers.data.ability.data.energy.EnergyLifespanData;
|
||||
import kamkeel.npcs.controllers.data.ability.data.ProjectileData;
|
||||
import kamkeel.npcs.controllers.data.energycharge.EnergyChargeTracker;
|
||||
import kamkeel.npcs.controllers.data.telegraph.Telegraph;
|
||||
import kamkeel.npcs.controllers.data.telegraph.TelegraphInstance;
|
||||
import kamkeel.npcs.controllers.data.telegraph.TelegraphType;
|
||||
@@ -287,6 +288,15 @@ public abstract class AbilityEnergyProjectile<E extends EntityEnergyProjectile>
|
||||
chargeVisualIds[index] = id;
|
||||
chargeVisualCaster = caster;
|
||||
EnergyChargeSpawnPacket.sendToTracking(id, previewEntity, caster);
|
||||
|
||||
// Register with server-side tracker for late-join support
|
||||
EnergyChargeTracker.Instance.add(new EnergyChargeTracker.ChargeEntry(
|
||||
id,
|
||||
previewEntity.getClass().getName(),
|
||||
previewEntity.exportSpawnNBT(),
|
||||
caster.getEntityId(),
|
||||
(int) caster.worldObj.getTotalWorldTime()
|
||||
));
|
||||
}
|
||||
|
||||
protected void removeChargeVisual(EntityLivingBase caster, int index) {
|
||||
@@ -296,6 +306,7 @@ public abstract class AbilityEnergyProjectile<E extends EntityEnergyProjectile>
|
||||
String id = chargeVisualIds[index];
|
||||
if (id != null && !id.isEmpty()) {
|
||||
EnergyChargeRemovePacket.sendToTracking(id, caster);
|
||||
EnergyChargeTracker.Instance.remove(id, caster.getEntityId());
|
||||
chargeVisualIds[index] = null;
|
||||
}
|
||||
}
|
||||
@@ -305,6 +316,10 @@ public abstract class AbilityEnergyProjectile<E extends EntityEnergyProjectile>
|
||||
for (int i = 0; i < chargeVisualIds.length; i++) {
|
||||
removeChargeVisual(caster, i);
|
||||
}
|
||||
// Safety net: ensure tracker is fully cleaned for this caster
|
||||
if (!isPreview() && caster.worldObj != null && !caster.worldObj.isRemote) {
|
||||
EnergyChargeTracker.Instance.removeAllForCaster(caster.getEntityId());
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== LIFECYCLE ====================
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
package kamkeel.npcs.controllers.data.energycharge;
|
||||
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.packets.data.energycharge.EnergyChargeSpawnPacket;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Server-side tracker for active charging preview visuals.
|
||||
* Stores enough data to resend {@link EnergyChargeSpawnPacket} to late-joining players
|
||||
* who enter tracking range after the initial broadcast.
|
||||
* <p>
|
||||
* Keyed by caster entity ID so {@code PlayerEvent.StartTracking} can look up
|
||||
* active charges for a newly tracked entity.
|
||||
*/
|
||||
public class EnergyChargeTracker {
|
||||
public static final EnergyChargeTracker Instance = new EnergyChargeTracker();
|
||||
|
||||
public static class ChargeEntry {
|
||||
public final String instanceId;
|
||||
public final String entityClassName;
|
||||
public final NBTTagCompound spawnNbt;
|
||||
public final int casterEntityId;
|
||||
public final int startTick;
|
||||
|
||||
public ChargeEntry(String instanceId, String entityClassName,
|
||||
NBTTagCompound spawnNbt, int casterEntityId, int startTick) {
|
||||
this.instanceId = instanceId;
|
||||
this.entityClassName = entityClassName;
|
||||
this.spawnNbt = spawnNbt;
|
||||
this.casterEntityId = casterEntityId;
|
||||
this.startTick = startTick;
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<Integer, List<ChargeEntry>> activeCharges = new HashMap<>();
|
||||
|
||||
public void add(ChargeEntry entry) {
|
||||
List<ChargeEntry> list = activeCharges.get(entry.casterEntityId);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
activeCharges.put(entry.casterEntityId, list);
|
||||
}
|
||||
list.add(entry);
|
||||
}
|
||||
|
||||
public void remove(String instanceId, int casterEntityId) {
|
||||
List<ChargeEntry> list = activeCharges.get(casterEntityId);
|
||||
if (list == null) return;
|
||||
Iterator<ChargeEntry> it = list.iterator();
|
||||
while (it.hasNext()) {
|
||||
if (it.next().instanceId.equals(instanceId)) {
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (list.isEmpty()) {
|
||||
activeCharges.remove(casterEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllForCaster(int casterEntityId) {
|
||||
activeCharges.remove(casterEntityId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all active charges for a caster to a specific player.
|
||||
* Adjusts ChargeTick in the NBT to reflect elapsed time so the
|
||||
* late-joining client starts at the correct visual progress.
|
||||
*/
|
||||
public void sendToPlayer(int casterEntityId, EntityPlayerMP player, int currentWorldTick) {
|
||||
List<ChargeEntry> entries = activeCharges.get(casterEntityId);
|
||||
if (entries == null || entries.isEmpty()) return;
|
||||
|
||||
for (ChargeEntry entry : entries) {
|
||||
int elapsed = currentWorldTick - entry.startTick;
|
||||
int chargeDuration = entry.spawnNbt.hasKey("ChargeDuration")
|
||||
? entry.spawnNbt.getInteger("ChargeDuration") : 0;
|
||||
|
||||
// Charge already complete — server remove packet should follow shortly
|
||||
if (chargeDuration > 0 && elapsed >= chargeDuration) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NBTTagCompound adjustedNbt = (NBTTagCompound) entry.spawnNbt.copy();
|
||||
if (elapsed > 0) {
|
||||
adjustedNbt.setInteger("ChargeTick", elapsed);
|
||||
}
|
||||
|
||||
PacketHandler.Instance.sendToPlayer(
|
||||
new EnergyChargeSpawnPacket(entry.instanceId, entry.entityClassName, adjustedNbt),
|
||||
player
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasCharges(int casterEntityId) {
|
||||
List<ChargeEntry> list = activeCharges.get(casterEntityId);
|
||||
return list != null && !list.isEmpty();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
activeCharges.clear();
|
||||
}
|
||||
}
|
||||
@@ -221,6 +221,10 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
|
||||
if (ticksExisted == 1 && !worldObj.isRemote) {
|
||||
trackProjectile(this);
|
||||
}
|
||||
} else {
|
||||
// Preview entities skip super.onUpdate() but still need ticksExisted
|
||||
// for renderer pulsing effects (e.g., sin(ticksExisted + partialTicks)).
|
||||
this.ticksExisted++;
|
||||
}
|
||||
|
||||
if (!previewMode) {
|
||||
@@ -230,8 +234,13 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
|
||||
// Update rotation
|
||||
updateRotation();
|
||||
|
||||
// Lerp render size toward actual size
|
||||
this.renderCurrentSize = this.renderCurrentSize + (this.size - this.renderCurrentSize) * 0.15f;
|
||||
// Update render size: during charging, track directly (size already grows smoothly).
|
||||
// Post-charging, lerp for smooth visual transitions.
|
||||
if (isCharging()) {
|
||||
this.renderCurrentSize = this.size;
|
||||
} else {
|
||||
this.renderCurrentSize = this.renderCurrentSize + (this.size - this.renderCurrentSize) * 0.15f;
|
||||
}
|
||||
|
||||
// Server-synced visual timer used for brief barrier impact lightning.
|
||||
if (!previewMode && !worldObj.isRemote) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import kamkeel.npcs.controllers.AttributeController;
|
||||
import kamkeel.npcs.controllers.ProfileController;
|
||||
import kamkeel.npcs.controllers.SyncController;
|
||||
import kamkeel.npcs.controllers.TelegraphController;
|
||||
import kamkeel.npcs.controllers.data.energycharge.EnergyChargeTracker;
|
||||
import kamkeel.npcs.controllers.data.profile.CNPCData;
|
||||
import kamkeel.npcs.developer.Developer;
|
||||
import kamkeel.npcs.entity.EntityAbilityBarrier;
|
||||
@@ -37,6 +38,7 @@ import kamkeel.npcs.entity.EntityAbilityPanel;
|
||||
import kamkeel.npcs.entity.EntityAbilitySweeper;
|
||||
import kamkeel.npcs.entity.EntityAbilityZone;
|
||||
import kamkeel.npcs.entity.EntityAbilityDome;
|
||||
import kamkeel.npcs.entity.EntityEnergyProjectile;
|
||||
import kamkeel.npcs.entity.EntityEnergySlicer;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.util.BukkitUtil;
|
||||
@@ -430,8 +432,9 @@ public class CustomNpcs {
|
||||
AuctionController.Instance.save();
|
||||
}
|
||||
|
||||
kamkeel.npcs.entity.EntityEnergyProjectile.clearAllProjectiles();
|
||||
EntityEnergyProjectile.clearAllProjectiles();
|
||||
EntityAbilityBarrier.clearAllBarriers();
|
||||
EnergyChargeTracker.Instance.clear();
|
||||
|
||||
if (FMLCommonHandler.instance().getSide().isClient())
|
||||
clientJaninoCompiler = null;
|
||||
|
||||
@@ -4,6 +4,7 @@ import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import kamkeel.npcs.controllers.SyncController;
|
||||
import kamkeel.npcs.controllers.data.energycharge.EnergyChargeTracker;
|
||||
import kamkeel.npcs.entity.EntityAbilityBarrier;
|
||||
import kamkeel.npcs.entity.EntityAbilityDome;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
@@ -300,6 +301,7 @@ public class ServerEventsHandler {
|
||||
public void invoke(LivingDeathEvent event) {
|
||||
if (event.entityLiving.worldObj.isRemote)
|
||||
return;
|
||||
EnergyChargeTracker.Instance.removeAllForCaster(event.entityLiving.getEntityId());
|
||||
if (event.source.getEntity() != null) {
|
||||
if (event.source.getEntity() instanceof EntityPlayer) {
|
||||
doExcalibur((EntityPlayer) event.source.getEntity(), event.entityLiving);
|
||||
@@ -535,7 +537,19 @@ public class ServerEventsHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void playerTracking(PlayerEvent.StartTracking event) {
|
||||
if (!(event.target instanceof EntityPlayerMP || event.target instanceof EntityNPCInterface) || event.target.worldObj.isRemote)
|
||||
if (event.target.worldObj.isRemote) return;
|
||||
|
||||
// Energy charge visuals: send active charges for newly tracked entity
|
||||
if (event.target instanceof EntityLivingBase
|
||||
&& event.entityPlayer instanceof EntityPlayerMP) {
|
||||
EnergyChargeTracker.Instance.sendToPlayer(
|
||||
event.target.getEntityId(),
|
||||
(EntityPlayerMP) event.entityPlayer,
|
||||
(int) event.target.worldObj.getTotalWorldTime()
|
||||
);
|
||||
}
|
||||
|
||||
if (!(event.target instanceof EntityPlayerMP || event.target instanceof EntityNPCInterface))
|
||||
return;
|
||||
|
||||
AnimationData animationData = AnimationData.getData(event.target);
|
||||
|
||||
Reference in new issue
Block a user