tcr/java/src/game/entity/EntityTrackerEntry.java
2025-03-27 17:54:03 +01:00

433 lines
16 KiB
Java
Executable file

package game.entity;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import game.collect.Sets;
import game.entity.attributes.AttributeInstance;
import game.entity.attributes.AttributeMap;
import game.entity.npc.EntityNPC;
import game.entity.projectile.EntityArrow;
import game.entity.types.EntityLiving;
import game.item.ItemStack;
import game.log.Log;
import game.nbt.NBTTagCompound;
import game.network.Packet;
import game.packet.S14PacketEntity;
import game.packet.S18PacketEntityTeleport;
import game.packet.S19PacketEntityHeadLook;
import game.packet.S1BPacketEntityAttach;
import game.packet.S1CPacketEntityMetadata;
import game.packet.S1DPacketEntityEffect;
import game.packet.S20PacketEntityProperties;
import game.packet.S43PacketUpdateEntityNBT;
import game.packet.SPacketEntityEquipment;
import game.packet.SPacketEntityVelocity;
import game.packet.SPacketSpawnMob;
import game.packet.SPacketSpawnObject;
import game.packet.SPacketSpawnPlayer;
import game.potion.PotionEffect;
import game.util.ExtMath;
public class EntityTrackerEntry {
public final Entity trackedEntity;
private final int trackingDistanceThreshold;
private final int updateFrequency;
private final boolean sendVelocityUpdates;
private final Set<EntityNPC> trackingPlayers = Sets.<EntityNPC>newHashSet();
private Entity lastRiding;
private int encodedPosX;
private int encodedPosY;
private int encodedPosZ;
private int encodedRotationYaw;
private int encodedRotationPitch;
private int lastHeadMotion;
private double lastTrackedEntityMotionX;
private double lastTrackedEntityMotionY;
private double lastTrackedEntityMotionZ;
private int updateCounter;
private double lastTrackedEntityPosX;
private double lastTrackedEntityPosY;
private double lastTrackedEntityPosZ;
private boolean firstUpdateDone;
private int ticksSinceLastForcedTeleport;
private boolean ridingEntity;
private boolean onGround;
private boolean playerEntitiesUpdated;
public EntityTrackerEntry(Entity trackedEntityIn, int trackingDistanceThresholdIn, int updateFrequencyIn, boolean sendVelocityUpdatesIn) {
this.trackedEntity = trackedEntityIn;
this.trackingDistanceThreshold = trackingDistanceThresholdIn;
this.updateFrequency = updateFrequencyIn;
this.sendVelocityUpdates = sendVelocityUpdatesIn;
this.encodedPosX = ExtMath.floord(trackedEntityIn.posX * 32.0D);
this.encodedPosY = ExtMath.floord(trackedEntityIn.posY * 32.0D);
this.encodedPosZ = ExtMath.floord(trackedEntityIn.posZ * 32.0D);
this.encodedRotationYaw = ExtMath.floorf(trackedEntityIn.rotYaw * 256.0F / 360.0F);
this.encodedRotationPitch = ExtMath.floorf(trackedEntityIn.rotPitch * 256.0F / 360.0F);
this.lastHeadMotion = ExtMath.floorf(trackedEntityIn.getRotationYawHead() * 256.0F / 360.0F);
this.onGround = trackedEntityIn.onGround;
}
public boolean equals(Object obj) {
return obj instanceof EntityTrackerEntry
? ((EntityTrackerEntry)obj).trackedEntity.getId() == this.trackedEntity.getId()
: false;
}
public int hashCode() {
return this.trackedEntity.getId();
}
public void updatePlayerList(List<EntityNPC> players) {
this.playerEntitiesUpdated = false;
if(!this.firstUpdateDone
|| this.trackedEntity.getDistanceSq(this.lastTrackedEntityPosX, this.lastTrackedEntityPosY, this.lastTrackedEntityPosZ) > 16.0D) {
this.lastTrackedEntityPosX = this.trackedEntity.posX;
this.lastTrackedEntityPosY = this.trackedEntity.posY;
this.lastTrackedEntityPosZ = this.trackedEntity.posZ;
this.firstUpdateDone = true;
this.playerEntitiesUpdated = true;
this.updatePlayerEntities(players);
}
if(this.lastRiding != this.trackedEntity.vehicle || this.trackedEntity.vehicle != null && this.updateCounter % 60 == 0) {
this.lastRiding = this.trackedEntity.vehicle;
this.sendPacketToTrackedPlayers(new S1BPacketEntityAttach(0, this.trackedEntity, this.trackedEntity.vehicle));
}
// if(this.trackedEntity instanceof EntityFrame && this.updateCounter % 10 == 0) {
//// EntityItemFrame entityitemframe = (EntityItemFrame)this.trackedEntity;
//// ItemStack itemstack = entityitemframe.getDisplayedItem();
////
//// if(itemstack != null && itemstack.getItem() instanceof ItemMap) {
//// MapData mapdata = Items.filled_map.getMapData(itemstack, this.trackedEntity.worldObj);
////
//// for(EntityNPC entityplayer : players) {
//// EntityNPCMP entityplayermp = (EntityNPCMP)entityplayer;
//// mapdata.updateVisiblePlayers(entityplayermp, itemstack);
//// Packet packet = Items.filled_map.createMapDataPacket(itemstack, this.trackedEntity.worldObj, entityplayermp);
////
//// if(packet != null) {
//// entityplayermp.netHandler.sendPacket(packet);
//// }
//// }
//// }
//
// this.sendMetadataToAllAssociatedPlayers();
// }
if(this.updateCounter % this.updateFrequency == 0 || this.trackedEntity.isAirBorne
|| this.trackedEntity.getDataWatcher().hasObjectChanged()) {
if(this.trackedEntity.vehicle == null) {
++this.ticksSinceLastForcedTeleport;
int k = ExtMath.floord(this.trackedEntity.posX * 32.0D);
int j1 = ExtMath.floord(this.trackedEntity.posY * 32.0D);
int k1 = ExtMath.floord(this.trackedEntity.posZ * 32.0D);
int l1 = ExtMath.floorf(this.trackedEntity.rotYaw * 256.0F / 360.0F);
int i2 = ExtMath.floorf(this.trackedEntity.rotPitch * 256.0F / 360.0F);
int j2 = k - this.encodedPosX;
int k2 = j1 - this.encodedPosY;
int i = k1 - this.encodedPosZ;
Packet packet1 = null;
boolean flag = Math.abs(j2) >= 4 || Math.abs(k2) >= 4 || Math.abs(i) >= 4 || this.updateCounter % 60 == 0;
boolean flag1 = Math.abs(l1 - this.encodedRotationYaw) >= 4 || Math.abs(i2 - this.encodedRotationPitch) >= 4;
if(this.updateCounter > 0 || this.trackedEntity instanceof EntityArrow) {
if(j2 >= -128 && j2 < 128 && k2 >= -128 && k2 < 128 && i >= -128 && i < 128 && this.ticksSinceLastForcedTeleport <= 400
&& !this.ridingEntity && this.onGround == this.trackedEntity.onGround) {
if((!flag || !flag1) && !(this.trackedEntity instanceof EntityArrow)) {
if(flag) {
packet1 = new S14PacketEntity.S15PacketEntityRelMove(this.trackedEntity.getId(), (byte)j2, (byte)k2, (byte)i,
this.trackedEntity.onGround);
}
else if(flag1) {
packet1 = new S14PacketEntity.S16PacketEntityLook(this.trackedEntity.getId(), (byte)l1, (byte)i2,
this.trackedEntity.onGround);
}
}
else {
packet1 = new S14PacketEntity.S17PacketEntityLookMove(this.trackedEntity.getId(), (byte)j2, (byte)k2, (byte)i,
(byte)l1, (byte)i2, this.trackedEntity.onGround);
}
}
else {
this.onGround = this.trackedEntity.onGround;
this.ticksSinceLastForcedTeleport = 0;
packet1 = new S18PacketEntityTeleport(this.trackedEntity.getId(), k, j1, k1, (byte)l1, (byte)i2,
this.trackedEntity.onGround);
}
}
if(this.sendVelocityUpdates) {
double d0 = this.trackedEntity.motionX - this.lastTrackedEntityMotionX;
double d1 = this.trackedEntity.motionY - this.lastTrackedEntityMotionY;
double d2 = this.trackedEntity.motionZ - this.lastTrackedEntityMotionZ;
double d3 = 0.02D;
double d4 = d0 * d0 + d1 * d1 + d2 * d2;
if(d4 > d3 * d3 || d4 > 0.0D && this.trackedEntity.motionX == 0.0D && this.trackedEntity.motionY == 0.0D
&& this.trackedEntity.motionZ == 0.0D) {
this.lastTrackedEntityMotionX = this.trackedEntity.motionX;
this.lastTrackedEntityMotionY = this.trackedEntity.motionY;
this.lastTrackedEntityMotionZ = this.trackedEntity.motionZ;
this.sendPacketToTrackedPlayers(new SPacketEntityVelocity(this.trackedEntity.getId(), this.lastTrackedEntityMotionX,
this.lastTrackedEntityMotionY, this.lastTrackedEntityMotionZ));
}
}
if(packet1 != null) {
this.sendPacketToTrackedPlayers(packet1);
}
this.sendMetadataToAllAssociatedPlayers();
if(flag) {
this.encodedPosX = k;
this.encodedPosY = j1;
this.encodedPosZ = k1;
}
if(flag1) {
this.encodedRotationYaw = l1;
this.encodedRotationPitch = i2;
}
this.ridingEntity = false;
}
else {
int j = ExtMath.floorf(this.trackedEntity.rotYaw * 256.0F / 360.0F);
int i1 = ExtMath.floorf(this.trackedEntity.rotPitch * 256.0F / 360.0F);
boolean flag2 = Math.abs(j - this.encodedRotationYaw) >= 4 || Math.abs(i1 - this.encodedRotationPitch) >= 4;
if(flag2) {
this.sendPacketToTrackedPlayers(new S14PacketEntity.S16PacketEntityLook(this.trackedEntity.getId(), (byte)j, (byte)i1,
this.trackedEntity.onGround));
this.encodedRotationYaw = j;
this.encodedRotationPitch = i1;
}
this.encodedPosX = ExtMath.floord(this.trackedEntity.posX * 32.0D);
this.encodedPosY = ExtMath.floord(this.trackedEntity.posY * 32.0D);
this.encodedPosZ = ExtMath.floord(this.trackedEntity.posZ * 32.0D);
this.sendMetadataToAllAssociatedPlayers();
this.ridingEntity = true;
}
int l = ExtMath.floorf(this.trackedEntity.getRotationYawHead() * 256.0F / 360.0F);
if(Math.abs(l - this.lastHeadMotion) >= 4) {
this.sendPacketToTrackedPlayers(new S19PacketEntityHeadLook(this.trackedEntity, (byte)l));
this.lastHeadMotion = l;
}
this.trackedEntity.isAirBorne = false;
}
++this.updateCounter;
if(this.trackedEntity.veloChanged) {
this.sendPacketToTrackedAndSelf(new SPacketEntityVelocity(this.trackedEntity));
this.trackedEntity.veloChanged = false;
}
}
private void sendMetadataToAllAssociatedPlayers() {
DataWatcher datawatcher = this.trackedEntity.getDataWatcher();
if(datawatcher.hasObjectChanged()) {
this.sendPacketToTrackedAndSelf(new S1CPacketEntityMetadata(this.trackedEntity.getId(), datawatcher, false));
}
if(this.trackedEntity instanceof EntityLiving) {
AttributeMap serversideattributemap = ((EntityLiving)this.trackedEntity).getAttributeMap();
Set<AttributeInstance> set = serversideattributemap.getDirty();
if(!set.isEmpty()) {
this.sendPacketToTrackedAndSelf(new S20PacketEntityProperties(this.trackedEntity.getId(), set));
}
set.clear();
}
}
public void sendPacketToTrackedPlayers(Packet packetIn) {
for(EntityNPC entityplayermp : this.trackingPlayers) {
entityplayermp.connection.sendPacket(packetIn);
}
}
public void sendPacketToTrackedAndSelf(Packet packetIn) {
this.sendPacketToTrackedPlayers(packetIn);
if(this.trackedEntity.isPlayer()) {
((EntityNPC)this.trackedEntity).connection.sendPacket(packetIn);
}
}
public void sendDestroyEntityPacketToTrackedPlayers() {
for(EntityNPC entityplayermp : this.trackingPlayers) {
entityplayermp.connection.removeEntity(this.trackedEntity);
}
}
public void removeFromTrackedPlayers(EntityNPC playerMP) {
if(this.trackingPlayers.contains(playerMP)) {
playerMP.connection.removeEntity(this.trackedEntity);
this.trackingPlayers.remove(playerMP);
}
}
public void updatePlayerEntity(EntityNPC playerMP) {
if(playerMP != this.trackedEntity) {
if(this.canBeSeen(playerMP)) {
if(!this.trackingPlayers.contains(playerMP) && (this.isPlayerWatchingThisChunk(playerMP) || this.trackedEntity.forceSpawn)) {
this.trackingPlayers.add(playerMP);
Packet packet = this.createSpawnPacket();
playerMP.connection.sendPacket(packet);
if(!this.trackedEntity.getDataWatcher().isBlank()) {
playerMP.connection
.sendPacket(new S1CPacketEntityMetadata(this.trackedEntity.getId(), this.trackedEntity.getDataWatcher(), true));
}
NBTTagCompound nbttagcompound = this.trackedEntity.getNBTTagCompound();
if(nbttagcompound != null) {
playerMP.connection.sendPacket(new S43PacketUpdateEntityNBT(this.trackedEntity.getId(), nbttagcompound));
}
if(this.trackedEntity instanceof EntityLiving) {
AttributeMap serversideattributemap = ((EntityLiving)this.trackedEntity).getAttributeMap();
Collection<AttributeInstance> collection = serversideattributemap.getWatchedAttributes();
if(!collection.isEmpty()) {
playerMP.connection.sendPacket(new S20PacketEntityProperties(this.trackedEntity.getId(), collection));
}
}
this.lastTrackedEntityMotionX = this.trackedEntity.motionX;
this.lastTrackedEntityMotionY = this.trackedEntity.motionY;
this.lastTrackedEntityMotionZ = this.trackedEntity.motionZ;
// if(this.trackedEntity.isPlayer() && !((EntityNPCMP)this.trackedEntity).isVisibleTo(playerMP))
// return;
if(this.sendVelocityUpdates && !(packet instanceof SPacketSpawnMob)) {
playerMP.connection.sendPacket(new SPacketEntityVelocity(this.trackedEntity.getId(),
this.trackedEntity.motionX, this.trackedEntity.motionY, this.trackedEntity.motionZ));
}
if(this.trackedEntity.vehicle != null) {
playerMP.connection.sendPacket(new S1BPacketEntityAttach(0, this.trackedEntity, this.trackedEntity.vehicle));
}
if(this.trackedEntity instanceof EntityLiving && ((EntityLiving)this.trackedEntity).getLeashedTo() != null) {
playerMP.connection.sendPacket(
new S1BPacketEntityAttach(1, this.trackedEntity, ((EntityLiving)this.trackedEntity).getLeashedTo()));
}
if(this.trackedEntity instanceof EntityLiving) {
for(int i = 0; i < 5; ++i) {
ItemStack itemstack = ((EntityLiving)this.trackedEntity).getItem(i);
if(itemstack != null) {
playerMP.connection
.sendPacket(new SPacketEntityEquipment(this.trackedEntity.getId(), i, itemstack));
}
}
}
// if(this.trackedEntity.isPlayer()) {
// EntityNPC entityplayer = (EntityNPC)this.trackedEntity;
//
// if(entityplayer.isPlayerSleeping()) {
// playerMP.netHandler.sendPacket(new SPacketUseBed(entityplayer, new BlockPos(this.trackedEntity)));
// }
// }
if(this.trackedEntity instanceof EntityLiving) {
EntityLiving entitylivingbase = (EntityLiving)this.trackedEntity;
for(PotionEffect potioneffect : entitylivingbase.getEffects()) {
playerMP.connection.sendPacket(new S1DPacketEntityEffect(this.trackedEntity.getId(), potioneffect));
}
}
}
}
else if(this.trackingPlayers.contains(playerMP)) {
this.trackingPlayers.remove(playerMP);
playerMP.connection.removeEntity(this.trackedEntity);
}
}
}
public boolean canBeSeen(EntityNPC playerMP) {
double d0 = playerMP.posX - (double)(this.encodedPosX / 32);
double d1 = playerMP.posZ - (double)(this.encodedPosZ / 32);
return d0 >= (double)(-this.trackingDistanceThreshold) && d0 <= (double)this.trackingDistanceThreshold
&& d1 >= (double)(-this.trackingDistanceThreshold) && d1 <= (double)this.trackingDistanceThreshold
&& this.trackedEntity.isVisibleTo(playerMP);
}
private boolean isPlayerWatchingThisChunk(EntityNPC playerMP) {
return playerMP.getServerWorld().isPlayerWatchingChunk(playerMP, this.trackedEntity.chunkCoordX,
this.trackedEntity.chunkCoordZ);
}
public void updatePlayerEntities(List<EntityNPC> players) {
for(int i = 0; i < players.size(); ++i) {
this.updatePlayerEntity(players.get(i));
}
}
private Packet createSpawnPacket() {
if(this.trackedEntity.dead) {
Log.JNI.warn("Erstelle Spawn-Paket für entferntes Objekt");
}
SPacketSpawnObject packet = null;
// int oid = EntityRegistry.getObjectID(this.trackedEntity);
// if(oid != 0) {
// }
if(this.trackedEntity.isPlayer()) {
return new SPacketSpawnPlayer((EntityNPC)this.trackedEntity);
}
else if(this.trackedEntity instanceof EntityLiving) {
this.lastHeadMotion = ExtMath.floorf(this.trackedEntity.getRotationYawHead() * 256.0F / 360.0F);
return new SPacketSpawnMob((EntityLiving)this.trackedEntity);
}
// else if(this.trackedEntity instanceof EntityPainting) {
// return new SPacketSpawnPainting((EntityPainting)this.trackedEntity);
// }
// else if(this.trackedEntity instanceof EntityXPOrb) {
// return new SPacketSpawnExperienceOrb((EntityXPOrb)this.trackedEntity);
// }
// else if(this.trackedEntity instanceof IObjectData) {
// packet = new SPacketSpawnObject(this.trackedEntity, ((IObjectData)this.trackedEntity).getPacketData());
// }
else {
return new SPacketSpawnObject(this.trackedEntity);
}
// else {
// throw new IllegalArgumentException("Kann Spawn-Paket für " + this.trackedEntity.getClass() + " nicht erstellen!");
// }
// return packet;
}
public void removeTrackedPlayerSymmetric(EntityNPC playerMP) {
if(this.trackingPlayers.contains(playerMP)) {
this.trackingPlayers.remove(playerMP);
playerMP.connection.removeEntity(this.trackedEntity);
}
}
public boolean isUpdated() {
return this.playerEntitiesUpdated;
}
}