2023-07-27 17:19:15 -05:00
|
|
|
package noppes.npcs.controllers.data;
|
2023-01-12 03:13:39 -05:00
|
|
|
|
2023-01-16 13:53:15 -06:00
|
|
|
|
2025-01-30 12:44:39 -05:00
|
|
|
import kamkeel.npcs.network.PacketHandler;
|
2025-01-30 13:54:55 -05:00
|
|
|
import kamkeel.npcs.network.packets.data.UpdateAnimationsPacket;
|
2025-01-22 18:54:00 -06:00
|
|
|
import net.minecraft.entity.Entity;
|
2023-12-13 14:32:09 -06:00
|
|
|
import net.minecraft.entity.EntityLivingBase;
|
2023-01-16 13:53:15 -06:00
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
2023-12-13 14:32:09 -06:00
|
|
|
import net.minecraft.entity.player.EntityPlayerMP;
|
2023-01-12 03:13:39 -05:00
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
2023-12-13 14:32:09 -06:00
|
|
|
import net.minecraft.util.AxisAlignedBB;
|
2025-02-12 12:15:33 -06:00
|
|
|
import noppes.npcs.CustomNpcs;
|
2024-08-22 16:47:45 -04:00
|
|
|
import noppes.npcs.DataDisplay;
|
2025-01-22 18:54:00 -06:00
|
|
|
import noppes.npcs.EventHooks;
|
|
|
|
|
import noppes.npcs.api.entity.IAnimatable;
|
|
|
|
|
import noppes.npcs.api.entity.IEntity;
|
2023-01-16 13:53:15 -06:00
|
|
|
import noppes.npcs.api.handler.data.IAnimation;
|
2024-02-15 17:54:28 -05:00
|
|
|
import noppes.npcs.api.handler.data.IAnimationData;
|
2024-01-30 19:17:55 -06:00
|
|
|
import noppes.npcs.constants.EnumAnimationPart;
|
2023-01-12 03:13:39 -05:00
|
|
|
import noppes.npcs.entity.EntityNPCInterface;
|
2025-01-22 18:54:00 -06:00
|
|
|
import noppes.npcs.scripted.NpcAPI;
|
2023-01-12 03:13:39 -05:00
|
|
|
|
2023-12-22 17:25:40 -06:00
|
|
|
import java.util.Arrays;
|
2023-12-13 14:32:09 -06:00
|
|
|
import java.util.List;
|
2024-01-30 19:17:55 -06:00
|
|
|
import java.util.Map;
|
2023-12-13 14:32:09 -06:00
|
|
|
|
2023-01-16 13:53:15 -06:00
|
|
|
public class AnimationData implements IAnimationData {
|
|
|
|
|
//Server-side: DataDisplay, PlayerData
|
|
|
|
|
//Client-side: DataDisplay, EntityPlayer
|
|
|
|
|
public Object parent;
|
2023-01-12 03:13:39 -05:00
|
|
|
|
2023-01-16 13:53:15 -06:00
|
|
|
public Animation animation;
|
|
|
|
|
public boolean allowAnimation = false;
|
2025-01-22 18:54:00 -06:00
|
|
|
public long animatingTime = 0;
|
|
|
|
|
|
|
|
|
|
public Animation currentClientAnimation;
|
|
|
|
|
private boolean isClientAnimating;
|
2024-03-24 17:03:58 -05:00
|
|
|
|
2023-12-22 17:25:40 -06:00
|
|
|
//Client-side values
|
|
|
|
|
public int finishedTime = -1;
|
|
|
|
|
public int finishedFrame = -1;
|
|
|
|
|
|
2025-03-13 17:14:45 -04:00
|
|
|
public AnimationData(Object parent) {
|
2023-01-16 13:53:15 -06:00
|
|
|
this.parent = parent;
|
2025-01-22 18:54:00 -06:00
|
|
|
}
|
2025-02-12 12:15:33 -06:00
|
|
|
|
2025-01-22 18:54:00 -06:00
|
|
|
public static AnimationData getData(Entity entity) {
|
2025-06-30 21:58:45 -04:00
|
|
|
if (entity == null || entity.worldObj == null) {
|
2025-02-12 13:16:39 -06:00
|
|
|
return null;
|
|
|
|
|
}
|
2025-02-12 12:15:33 -06:00
|
|
|
if (entity.worldObj.isRemote) {
|
|
|
|
|
return CustomNpcs.proxy.getClientAnimationData(entity);
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-22 18:54:00 -06:00
|
|
|
if (entity instanceof EntityPlayerMP) {
|
|
|
|
|
return PlayerData.get((EntityPlayer) entity).animationData;
|
|
|
|
|
} else if (entity instanceof EntityNPCInterface) {
|
2025-03-13 17:14:45 -04:00
|
|
|
return ((EntityNPCInterface) entity).display.animationData;
|
2025-01-22 18:54:00 -06:00
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IAnimatable getEntity() {
|
|
|
|
|
IEntity<?> entity = NpcAPI.Instance().getIEntity(this.getMCEntity());
|
|
|
|
|
if (entity instanceof IAnimatable) {
|
|
|
|
|
return (IAnimatable) entity;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public EntityLivingBase getMCEntity() {
|
|
|
|
|
if (this.parent instanceof DataDisplay) {
|
2025-03-13 17:14:45 -04:00
|
|
|
return ((DataDisplay) this.parent).npc;
|
2025-01-22 18:54:00 -06:00
|
|
|
} else {
|
|
|
|
|
if (this.parent instanceof PlayerData) {
|
|
|
|
|
return ((PlayerData) this.parent).player;
|
|
|
|
|
} else {
|
|
|
|
|
return (EntityPlayer) this.parent;
|
|
|
|
|
}
|
2024-03-24 17:03:58 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-12 03:13:39 -05:00
|
|
|
public void updateClient() {
|
2023-12-22 17:25:40 -06:00
|
|
|
this.updateClient(new EntityPlayer[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void updateClient(EntityPlayer... excludedPlayers) {
|
2023-12-13 14:32:09 -06:00
|
|
|
EntityLivingBase sendingEntity = parent instanceof PlayerData ? ((PlayerData) parent).player : parent instanceof DataDisplay ? ((DataDisplay) parent).npc : null;
|
|
|
|
|
float range = parent instanceof PlayerData ? 160 : 60;
|
2025-06-30 21:58:45 -04:00
|
|
|
if (sendingEntity != null && sendingEntity.worldObj != null) {
|
2025-03-13 17:14:45 -04:00
|
|
|
if (sendingEntity.dimension != sendingEntity.worldObj.provider.dimensionId)
|
2024-03-27 04:28:33 -04:00
|
|
|
sendingEntity.dimension = sendingEntity.worldObj.provider.dimensionId;
|
|
|
|
|
|
2025-01-22 18:54:00 -06:00
|
|
|
this.animatingTime = 0;
|
|
|
|
|
|
|
|
|
|
boolean prevIsClientAnimating = this.isClientAnimating && this.currentClientAnimation.currentFrame() != null;
|
|
|
|
|
this.isClientAnimating = this.allowAnimation && this.animation != null;
|
|
|
|
|
if (prevIsClientAnimating && (!this.isClientAnimating || this.animation != this.currentClientAnimation)) {
|
|
|
|
|
EventHooks.onAnimationEnded(this.currentClientAnimation);
|
|
|
|
|
}
|
|
|
|
|
if (this.isClientAnimating) {
|
|
|
|
|
this.currentClientAnimation = this.animation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.animation != null && this.allowAnimation) {
|
|
|
|
|
if (EventHooks.onAnimationStarted(this.animation))
|
|
|
|
|
return;
|
|
|
|
|
EventHooks.onAnimationFrameEntered(this.animation, this.animation.currentFrame());
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 14:32:09 -06:00
|
|
|
List<EntityPlayer> entities = sendingEntity.worldObj.getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getBoundingBox(
|
2024-02-19 19:23:43 -05:00
|
|
|
sendingEntity.posX - range, sendingEntity.posY - range, sendingEntity.posZ - range,
|
|
|
|
|
sendingEntity.posX + range, sendingEntity.posY + range, sendingEntity.posZ + range));
|
2023-12-13 14:32:09 -06:00
|
|
|
|
2023-12-22 17:25:40 -06:00
|
|
|
entities.removeIf(player -> Arrays.stream(excludedPlayers).anyMatch(exp -> player == exp));
|
|
|
|
|
|
2023-12-13 14:32:09 -06:00
|
|
|
for (EntityPlayer player : entities) {
|
2025-04-08 22:48:32 -04:00
|
|
|
AnimationData animationData = PlayerData.get(player).animationData;
|
2025-01-23 00:35:25 -06:00
|
|
|
NBTTagCompound animationNBT = this.animation != null ? this.animation.writeToNBT() : null;
|
2025-01-22 18:54:00 -06:00
|
|
|
animationData.viewAnimation(this.animation, this, animationNBT);
|
2023-12-13 14:32:09 -06:00
|
|
|
}
|
2023-01-16 13:53:15 -06:00
|
|
|
}
|
2023-01-12 03:13:39 -05:00
|
|
|
}
|
|
|
|
|
|
2025-01-22 18:54:00 -06:00
|
|
|
public boolean isClientAnimating() {
|
|
|
|
|
return this.isClientAnimating;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-12 03:13:39 -05:00
|
|
|
public boolean isActive() {
|
2025-01-22 18:54:00 -06:00
|
|
|
return this.isActive(this.animation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isActive(Animation animation) {
|
|
|
|
|
if (!this.allowAnimation || animation == null || animation.currentFrame == animation.frames.size() || animation.currentFrame() == null)
|
2023-01-12 03:13:39 -05:00
|
|
|
return false;
|
|
|
|
|
|
2023-01-16 13:53:15 -06:00
|
|
|
if (this.parent instanceof DataDisplay) {
|
2025-03-13 17:14:45 -04:00
|
|
|
EntityNPCInterface npc = ((DataDisplay) this.parent).npc;
|
2023-01-16 13:53:15 -06:00
|
|
|
if (!npc.isEntityAlive())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return animation.whileAttacking && npc.isAttacking() || animation.whileMoving && npc.isWalking() || animation.whileStanding && !npc.isWalking();
|
|
|
|
|
} else {
|
|
|
|
|
EntityPlayer player;
|
|
|
|
|
if (this.parent instanceof PlayerData) {
|
|
|
|
|
player = ((PlayerData) this.parent).player;
|
|
|
|
|
} else {
|
|
|
|
|
player = (EntityPlayer) this.parent;
|
|
|
|
|
}
|
|
|
|
|
if (!player.isEntityAlive())
|
|
|
|
|
return false;
|
|
|
|
|
|
2025-03-13 17:14:45 -04:00
|
|
|
boolean moving = Math.sqrt(player.motionX * player.motionX + player.motionY * player.motionY + player.motionZ * player.motionZ) != 0.0D;
|
2023-01-16 13:53:15 -06:00
|
|
|
|
|
|
|
|
return animation.whileAttacking && player.getLastAttackerTime() - player.ticksExisted < 20 || animation.whileMoving && moving || animation.whileStanding && !moving;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-22 18:54:00 -06:00
|
|
|
public void increaseTime() {
|
|
|
|
|
Animation updateAnimation = null;
|
2025-02-12 12:15:33 -06:00
|
|
|
if (this.animation != null && this.isActive(this.animation.parent.currentClientAnimation)) {
|
2025-01-22 18:54:00 -06:00
|
|
|
updateAnimation = this.currentClientAnimation;
|
|
|
|
|
} else {
|
|
|
|
|
this.isClientAnimating = false;
|
|
|
|
|
if (this.isActive()) {
|
|
|
|
|
updateAnimation = this.animation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (updateAnimation != null && updateAnimation.increaseTime()) {
|
|
|
|
|
Frame frame = (Frame) updateAnimation.currentFrame();
|
|
|
|
|
if (frame != null) {
|
2025-02-12 12:15:33 -06:00
|
|
|
this.animatingTime++;
|
2025-01-22 18:54:00 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void viewAnimation(Animation animation, AnimationData animationData, NBTTagCompound animationNBT) {
|
|
|
|
|
this.viewAnimation(animation, animationData, animationNBT, animationData.allowAnimation, -1, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean viewAnimation(Animation animation, AnimationData animationData, NBTTagCompound animationNBT, boolean enabled, int currentFrame, int time) {
|
|
|
|
|
if (animation != null
|
|
|
|
|
&& (currentFrame >= animation.frames.size()
|
|
|
|
|
|| currentFrame >= 0 && animation.frames.get(currentFrame).getDuration() < time)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean prevEnabled = animationData.allowAnimation;
|
|
|
|
|
animationData.allowAnimation = enabled;
|
|
|
|
|
NBTTagCompound data = animationData.viewWriteNBT(new NBTTagCompound());
|
|
|
|
|
animationData.allowAnimation = prevEnabled;
|
|
|
|
|
|
|
|
|
|
if (animation != null && currentFrame >= 0 && currentFrame < animation.frames.size()) {
|
|
|
|
|
data.setInteger("Frame", currentFrame);
|
|
|
|
|
data.setInteger("Time", time);
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-23 00:35:25 -06:00
|
|
|
if (animationNBT != null) {
|
|
|
|
|
data.setTag("Animation", animationNBT);
|
2025-02-11 17:59:35 -06:00
|
|
|
} else if (animation != null) {
|
|
|
|
|
data.setTag("Animation", animation.writeToNBT());
|
2023-12-13 14:32:09 -06:00
|
|
|
}
|
2025-01-22 18:54:00 -06:00
|
|
|
|
|
|
|
|
IAnimatable animatable = animationData.getEntity();
|
|
|
|
|
Entity entity = ((IEntity<?>) animatable).getMCEntity();
|
2023-12-13 14:32:09 -06:00
|
|
|
if (!(entity instanceof EntityPlayer)) {
|
|
|
|
|
data.setInteger("EntityId", entity.getEntityId());
|
|
|
|
|
}
|
2025-01-22 18:54:00 -06:00
|
|
|
|
2025-01-30 12:44:39 -05:00
|
|
|
PacketHandler.Instance.sendToPlayer(new UpdateAnimationsPacket(data, entity.getCommandSenderName()), (EntityPlayerMP) ((PlayerData) parent).player);
|
2025-01-22 18:54:00 -06:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public NBTTagCompound viewWriteNBT(NBTTagCompound compound) {
|
|
|
|
|
compound.setBoolean("AllowAnimation", allowAnimation);
|
|
|
|
|
return compound;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void viewReadFromNBT(NBTTagCompound compound) {
|
|
|
|
|
this.setEnabled(compound.getBoolean("AllowAnimation"));
|
2023-12-13 14:32:09 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-16 13:53:15 -06:00
|
|
|
public NBTTagCompound writeToNBT(NBTTagCompound compound) {
|
2025-01-22 18:54:00 -06:00
|
|
|
if (this.currentClientAnimation != null) {
|
|
|
|
|
compound.setBoolean("IsClientAnimating", isClientAnimating);
|
|
|
|
|
if (this.isClientAnimating) {
|
|
|
|
|
compound.setTag("CurrentAnimation", currentClientAnimation.writeToNBT());
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-02 23:45:38 -05:00
|
|
|
compound.setBoolean("AllowAnimation", allowAnimation);
|
2023-01-16 13:53:15 -06:00
|
|
|
return compound;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void readFromNBT(NBTTagCompound compound) {
|
2025-01-22 18:54:00 -06:00
|
|
|
Entity entity = this.getMCEntity();
|
2025-06-30 21:58:45 -04:00
|
|
|
boolean isServer = entity != null && entity.worldObj != null && !entity.worldObj.isRemote;
|
2025-01-22 18:54:00 -06:00
|
|
|
if (compound.hasKey("IsClientAnimating") && isServer) {
|
|
|
|
|
this.isClientAnimating = compound.getBoolean("IsClientAnimating");
|
|
|
|
|
if (this.isClientAnimating) {
|
|
|
|
|
this.currentClientAnimation = new Animation();
|
|
|
|
|
this.currentClientAnimation.parent = this;
|
|
|
|
|
this.currentClientAnimation.readFromNBT(compound.getCompoundTag("CurrentAnimation"));
|
|
|
|
|
this.animation = this.currentClientAnimation;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-22 17:25:40 -06:00
|
|
|
this.setEnabled(compound.getBoolean("AllowAnimation"));
|
2023-01-16 13:53:15 -06:00
|
|
|
}
|
2023-01-12 03:13:39 -05:00
|
|
|
|
2023-01-16 13:53:15 -06:00
|
|
|
public void setEnabled(boolean enabled) {
|
2023-12-22 17:25:40 -06:00
|
|
|
if (this.allowAnimation != enabled) {
|
|
|
|
|
this.allowAnimation = enabled;
|
|
|
|
|
if (this.parent instanceof EntityPlayer) {
|
|
|
|
|
this.finishedTime = enabled ? -1 : ((EntityPlayer) this.parent).getAge();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-16 13:53:15 -06:00
|
|
|
}
|
2023-01-12 03:13:39 -05:00
|
|
|
|
2023-01-16 13:53:15 -06:00
|
|
|
public boolean enabled() {
|
|
|
|
|
return this.allowAnimation;
|
2023-01-12 03:13:39 -05:00
|
|
|
}
|
|
|
|
|
|
2023-01-16 13:53:15 -06:00
|
|
|
public void setAnimation(IAnimation animation) {
|
2025-01-22 18:54:00 -06:00
|
|
|
Animation newAnim = null;
|
|
|
|
|
if (animation != null) {
|
|
|
|
|
newAnim = new Animation();
|
|
|
|
|
newAnim.readFromNBT(((Animation) animation).writeToNBT());
|
|
|
|
|
newAnim.currentFrame = 0;
|
|
|
|
|
newAnim.currentFrameTime = 0;
|
|
|
|
|
newAnim.parent = this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-06-30 21:58:45 -04:00
|
|
|
if (this.getMCEntity() != null && this.getMCEntity().worldObj != null && this.getMCEntity().worldObj.isRemote && newAnim != null) {
|
2025-01-22 18:54:00 -06:00
|
|
|
this.animatingTime = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Animation prevAnim = this.animation;
|
|
|
|
|
this.animation = newAnim;
|
|
|
|
|
|
2025-06-30 21:58:45 -04:00
|
|
|
if (this.getMCEntity() != null && this.getMCEntity().worldObj != null && this.getMCEntity().worldObj.isRemote &&
|
2025-01-22 18:54:00 -06:00
|
|
|
this.isActive() && prevAnim != null && newAnim != null && !newAnim.frames.isEmpty()) {
|
|
|
|
|
Frame frame = (Frame) prevAnim.currentFrame();
|
|
|
|
|
if (frame != null) {
|
|
|
|
|
Frame firstFrame = newAnim.frames.get(0);
|
|
|
|
|
for (Map.Entry<EnumAnimationPart, FramePart> entry : frame.frameParts.entrySet()) {
|
|
|
|
|
if (firstFrame.frameParts.containsKey(entry.getKey())) {
|
|
|
|
|
FramePart prevFramePart = entry.getValue();
|
|
|
|
|
FramePart newFramePart = firstFrame.frameParts.get(entry.getKey());
|
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
|
newFramePart.prevPivots[i] = prevFramePart.prevPivots[i];
|
|
|
|
|
newFramePart.prevRotations[i] = prevFramePart.prevRotations[i];
|
2024-01-30 19:17:55 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-16 13:53:15 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IAnimation getAnimation() {
|
|
|
|
|
return animation;
|
|
|
|
|
}
|
2025-01-22 18:54:00 -06:00
|
|
|
|
|
|
|
|
public long getAnimatingTime() {
|
|
|
|
|
return this.animatingTime;
|
|
|
|
|
}
|
2023-01-12 03:13:39 -05:00
|
|
|
}
|