275 lines
13 KiB
Java
275 lines
13 KiB
Java
package net.minecraft.server.level;
|
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
import java.util.Set;
|
|
import net.minecraft.network.syncher.SynchedEntityData;
|
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
|
import java.util.Collection;
|
|
import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
|
|
import net.minecraft.world.entity.Mob;
|
|
import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
|
|
import net.minecraft.world.effect.MobEffectInstance;
|
|
import net.minecraft.network.protocol.game.ClientboundSetEquippedItemPacket;
|
|
import net.minecraft.world.entity.EquipmentSlot;
|
|
import net.minecraft.network.protocol.game.ClientboundAddMobPacket;
|
|
import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket;
|
|
import net.minecraft.world.entity.ai.attributes.ModifiableAttributeMap;
|
|
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
|
|
import java.util.Iterator;
|
|
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket;
|
|
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
|
|
import net.minecraft.world.entity.projectile.AbstractArrow;
|
|
import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.item.MapItem;
|
|
import net.minecraft.world.entity.decoration.ItemFrame;
|
|
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
|
import net.minecraft.util.Mth;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraft.network.protocol.Packet;
|
|
import java.util.function.Consumer;
|
|
import net.minecraft.world.entity.Entity;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
public class ServerEntity {
|
|
private static final Logger LOGGER;
|
|
private final ServerLevel level;
|
|
private final Entity entity;
|
|
private final int updateInterval;
|
|
private final boolean trackDelta;
|
|
private final Consumer<Packet<?>> broadcast;
|
|
private long xp;
|
|
private long yp;
|
|
private long zp;
|
|
private int yRotp;
|
|
private int xRotp;
|
|
private int yHeadRotp;
|
|
private Vec3 ap;
|
|
private int tickCount;
|
|
private int teleportDelay;
|
|
private List<Entity> lastPassengers;
|
|
private boolean wasRiding;
|
|
private boolean wasOnGround;
|
|
|
|
public ServerEntity(final ServerLevel xd, final Entity akn, final int integer, final boolean boolean4, final Consumer<Packet<?>> consumer) {
|
|
this.ap = Vec3.ZERO;
|
|
this.lastPassengers = Collections.<Entity>emptyList();
|
|
this.level = xd;
|
|
this.broadcast = consumer;
|
|
this.entity = akn;
|
|
this.updateInterval = integer;
|
|
this.trackDelta = boolean4;
|
|
this.updateSentPos();
|
|
this.yRotp = Mth.floor(akn.yRot * 256.0f / 360.0f);
|
|
this.xRotp = Mth.floor(akn.xRot * 256.0f / 360.0f);
|
|
this.yHeadRotp = Mth.floor(akn.getYHeadRot() * 256.0f / 360.0f);
|
|
this.wasOnGround = akn.onGround;
|
|
}
|
|
|
|
public void sendChanges() {
|
|
final List<Entity> list2 = this.entity.getPassengers();
|
|
if (!list2.equals(this.lastPassengers)) {
|
|
this.lastPassengers = list2;
|
|
this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity));
|
|
}
|
|
if (this.entity instanceof ItemFrame && this.tickCount % 10 == 0) {
|
|
final ItemFrame avo3 = (ItemFrame)this.entity;
|
|
final ItemStack bek4 = avo3.getItem();
|
|
if (bek4.getItem() instanceof MapItem) {
|
|
final MapItemSavedData crd5 = MapItem.getOrCreateSavedData(bek4, this.level);
|
|
for (final ServerPlayer xe7 : this.level.players()) {
|
|
crd5.tickCarriedBy(xe7, bek4);
|
|
final Packet<?> lt8 = ((MapItem)bek4.getItem()).getUpdatePacket(bek4, this.level, xe7);
|
|
if (lt8 != null) {
|
|
xe7.connection.send(lt8);
|
|
}
|
|
}
|
|
}
|
|
this.sendDirtyEntityData();
|
|
}
|
|
if (this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isDirty()) {
|
|
if (this.entity.isPassenger()) {
|
|
final int integer3 = Mth.floor(this.entity.yRot * 256.0f / 360.0f);
|
|
final int integer4 = Mth.floor(this.entity.xRot * 256.0f / 360.0f);
|
|
final boolean boolean5 = Math.abs(integer3 - this.yRotp) >= 1 || Math.abs(integer4 - this.xRotp) >= 1;
|
|
if (boolean5) {
|
|
this.broadcast.accept(new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte)integer3, (byte)integer4, this.entity.onGround));
|
|
this.yRotp = integer3;
|
|
this.xRotp = integer4;
|
|
}
|
|
this.updateSentPos();
|
|
this.sendDirtyEntityData();
|
|
this.wasRiding = true;
|
|
}
|
|
else {
|
|
++this.teleportDelay;
|
|
final int integer3 = Mth.floor(this.entity.yRot * 256.0f / 360.0f);
|
|
final int integer4 = Mth.floor(this.entity.xRot * 256.0f / 360.0f);
|
|
final Vec3 cvi5 = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp));
|
|
final boolean boolean6 = cvi5.lengthSqr() >= 7.62939453125E-6;
|
|
Packet<?> lt9 = null;
|
|
final boolean boolean7 = boolean6 || this.tickCount % 60 == 0;
|
|
final boolean boolean8 = Math.abs(integer3 - this.yRotp) >= 1 || Math.abs(integer4 - this.xRotp) >= 1;
|
|
if (this.tickCount > 0 || this.entity instanceof AbstractArrow) {
|
|
final long long10 = ClientboundMoveEntityPacket.entityToPacket(cvi5.x);
|
|
final long long11 = ClientboundMoveEntityPacket.entityToPacket(cvi5.y);
|
|
final long long12 = ClientboundMoveEntityPacket.entityToPacket(cvi5.z);
|
|
final boolean boolean9 = long10 < -32768L || long10 > 32767L || long11 < -32768L || long11 > 32767L || long12 < -32768L || long12 > 32767L;
|
|
if (boolean9 || this.teleportDelay > 400 || this.wasRiding || this.wasOnGround != this.entity.onGround) {
|
|
this.wasOnGround = this.entity.onGround;
|
|
this.teleportDelay = 0;
|
|
lt9 = new ClientboundTeleportEntityPacket(this.entity);
|
|
}
|
|
else if ((boolean7 && boolean8) || this.entity instanceof AbstractArrow) {
|
|
lt9 = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short)long10, (short)long11, (short)long12, (byte)integer3, (byte)integer4, this.entity.onGround);
|
|
}
|
|
else if (boolean7) {
|
|
lt9 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short)long10, (short)long11, (short)long12, this.entity.onGround);
|
|
}
|
|
else if (boolean8) {
|
|
lt9 = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte)integer3, (byte)integer4, this.entity.onGround);
|
|
}
|
|
}
|
|
if ((this.trackDelta || this.entity.hasImpulse || (this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isFallFlying())) && this.tickCount > 0) {
|
|
final Vec3 cvi6 = this.entity.getDeltaMovement();
|
|
final double double11 = cvi6.distanceToSqr(this.ap);
|
|
if (double11 > 1.0E-7 || (double11 > 0.0 && cvi6.lengthSqr() == 0.0)) {
|
|
this.ap = cvi6;
|
|
this.broadcast.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.ap));
|
|
}
|
|
}
|
|
if (lt9 != null) {
|
|
this.broadcast.accept(lt9);
|
|
}
|
|
this.sendDirtyEntityData();
|
|
if (boolean7) {
|
|
this.updateSentPos();
|
|
}
|
|
if (boolean8) {
|
|
this.yRotp = integer3;
|
|
this.xRotp = integer4;
|
|
}
|
|
this.wasRiding = false;
|
|
}
|
|
final int integer3 = Mth.floor(this.entity.getYHeadRot() * 256.0f / 360.0f);
|
|
if (Math.abs(integer3 - this.yHeadRotp) >= 1) {
|
|
this.broadcast.accept(new ClientboundRotateHeadPacket(this.entity, (byte)integer3));
|
|
this.yHeadRotp = integer3;
|
|
}
|
|
this.entity.hasImpulse = false;
|
|
}
|
|
++this.tickCount;
|
|
if (this.entity.hurtMarked) {
|
|
this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
|
|
this.entity.hurtMarked = false;
|
|
}
|
|
}
|
|
|
|
public void removePairing(final ServerPlayer xe) {
|
|
this.entity.stopSeenByPlayer(xe);
|
|
xe.sendRemoveEntity(this.entity);
|
|
}
|
|
|
|
public void addPairing(final ServerPlayer xe) {
|
|
this.sendPairingData(xe.connection::send);
|
|
this.entity.startSeenByPlayer(xe);
|
|
xe.cancelRemoveEntity(this.entity);
|
|
}
|
|
|
|
public void sendPairingData(final Consumer<Packet<?>> consumer) {
|
|
if (this.entity.removed) {
|
|
ServerEntity.LOGGER.warn("Fetching packet for removed entity " + this.entity);
|
|
}
|
|
final Packet<?> lt3 = this.entity.getAddEntityPacket();
|
|
this.yHeadRotp = Mth.floor(this.entity.getYHeadRot() * 256.0f / 360.0f);
|
|
consumer.accept(lt3);
|
|
if (!this.entity.getEntityData().isEmpty()) {
|
|
consumer.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.entity.getEntityData(), true));
|
|
}
|
|
boolean boolean4 = this.trackDelta;
|
|
if (this.entity instanceof LivingEntity) {
|
|
final ModifiableAttributeMap alt5 = (ModifiableAttributeMap)((LivingEntity)this.entity).getAttributes();
|
|
final Collection<AttributeInstance> collection6 = alt5.getSyncableAttributes();
|
|
if (!collection6.isEmpty()) {
|
|
consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection6));
|
|
}
|
|
if (((LivingEntity)this.entity).isFallFlying()) {
|
|
boolean4 = true;
|
|
}
|
|
}
|
|
this.ap = this.entity.getDeltaMovement();
|
|
if (boolean4 && !(lt3 instanceof ClientboundAddMobPacket)) {
|
|
consumer.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.ap));
|
|
}
|
|
if (this.entity instanceof LivingEntity) {
|
|
for (final EquipmentSlot aks8 : EquipmentSlot.values()) {
|
|
final ItemStack bek9 = ((LivingEntity)this.entity).getItemBySlot(aks8);
|
|
if (!bek9.isEmpty()) {
|
|
consumer.accept(new ClientboundSetEquippedItemPacket(this.entity.getId(), aks8, bek9));
|
|
}
|
|
}
|
|
}
|
|
if (this.entity instanceof LivingEntity) {
|
|
final LivingEntity akw5 = (LivingEntity)this.entity;
|
|
for (final MobEffectInstance akh7 : akw5.getActiveEffects()) {
|
|
consumer.accept(new ClientboundUpdateMobEffectPacket(this.entity.getId(), akh7));
|
|
}
|
|
}
|
|
if (!this.entity.getPassengers().isEmpty()) {
|
|
consumer.accept(new ClientboundSetPassengersPacket(this.entity));
|
|
}
|
|
if (this.entity.isPassenger()) {
|
|
consumer.accept(new ClientboundSetPassengersPacket(this.entity.getVehicle()));
|
|
}
|
|
if (this.entity instanceof Mob) {
|
|
final Mob akx5 = (Mob)this.entity;
|
|
if (akx5.isLeashed()) {
|
|
consumer.accept(new ClientboundSetEntityLinkPacket(akx5, akx5.getLeashHolder()));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void sendDirtyEntityData() {
|
|
final SynchedEntityData se2 = this.entity.getEntityData();
|
|
if (se2.isDirty()) {
|
|
this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), se2, false));
|
|
}
|
|
if (this.entity instanceof LivingEntity) {
|
|
final ModifiableAttributeMap alt3 = (ModifiableAttributeMap)((LivingEntity)this.entity).getAttributes();
|
|
final Set<AttributeInstance> set4 = alt3.getDirtyAttributes();
|
|
if (!set4.isEmpty()) {
|
|
this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), set4));
|
|
}
|
|
set4.clear();
|
|
}
|
|
}
|
|
|
|
private void updateSentPos() {
|
|
this.xp = ClientboundMoveEntityPacket.entityToPacket(this.entity.getX());
|
|
this.yp = ClientboundMoveEntityPacket.entityToPacket(this.entity.getY());
|
|
this.zp = ClientboundMoveEntityPacket.entityToPacket(this.entity.getZ());
|
|
}
|
|
|
|
public Vec3 sentPos() {
|
|
return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp);
|
|
}
|
|
|
|
private void broadcastAndSend(final Packet<?> lt) {
|
|
this.broadcast.accept(lt);
|
|
if (this.entity instanceof ServerPlayer) {
|
|
((ServerPlayer)this.entity).connection.send(lt);
|
|
}
|
|
}
|
|
|
|
static {
|
|
LOGGER = LogManager.getLogger();
|
|
}
|
|
}
|