ServerEntity.java
net.minecraft.server.level.ServerEntity
信息
- 全限定名:net.minecraft.server.level.ServerEntity
- 类型:public class
- 包:net.minecraft.server.level
- 源码路径:src/main/java/net/minecraft/server/level/ServerEntity.java
- 起始行号:L50
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L51 - 说明:
TODO
- 类型:
-
TOLERANCE_LEVEL_ROTATION- 类型:
int - 修饰符:
private static final - 源码定位:
L52 - 说明:
TODO
- 类型:
-
TOLERANCE_LEVEL_POSITION- 类型:
double - 修饰符:
private static final - 源码定位:
L53 - 说明:
TODO
- 类型:
-
FORCED_POS_UPDATE_PERIOD- 类型:
int - 修饰符:
public static final - 源码定位:
L54 - 说明:
TODO
- 类型:
-
FORCED_TELEPORT_PERIOD- 类型:
int - 修饰符:
private static final - 源码定位:
L55 - 说明:
TODO
- 类型:
-
level- 类型:
ServerLevel - 修饰符:
private final - 源码定位:
L56 - 说明:
TODO
- 类型:
-
entity- 类型:
Entity - 修饰符:
private final - 源码定位:
L57 - 说明:
TODO
- 类型:
-
updateInterval- 类型:
int - 修饰符:
private final - 源码定位:
L58 - 说明:
TODO
- 类型:
-
trackDelta- 类型:
boolean - 修饰符:
private final - 源码定位:
L59 - 说明:
TODO
- 类型:
-
synchronizer- 类型:
ServerEntity.Synchronizer - 修饰符:
private final - 源码定位:
L60 - 说明:
TODO
- 类型:
-
positionCodec- 类型:
VecDeltaCodec - 修饰符:
private final - 源码定位:
L61 - 说明:
TODO
- 类型:
-
lastSentYRot- 类型:
byte - 修饰符:
private - 源码定位:
L62 - 说明:
TODO
- 类型:
-
lastSentXRot- 类型:
byte - 修饰符:
private - 源码定位:
L63 - 说明:
TODO
- 类型:
-
lastSentYHeadRot- 类型:
byte - 修饰符:
private - 源码定位:
L64 - 说明:
TODO
- 类型:
-
lastSentMovement- 类型:
Vec3 - 修饰符:
private - 源码定位:
L65 - 说明:
TODO
- 类型:
-
tickCount- 类型:
int - 修饰符:
private - 源码定位:
L66 - 说明:
TODO
- 类型:
-
teleportDelay- 类型:
int - 修饰符:
private - 源码定位:
L67 - 说明:
TODO
- 类型:
-
lastPassengers- 类型:
List<Entity> - 修饰符:
private - 源码定位:
L68 - 说明:
TODO
- 类型:
-
wasRiding- 类型:
boolean - 修饰符:
private - 源码定位:
L69 - 说明:
TODO
- 类型:
-
wasOnGround- 类型:
boolean - 修饰符:
private - 源码定位:
L70 - 说明:
TODO
- 类型:
-
trackedDataValues- 类型:
List<SynchedEntityData.DataValue<?>> - 修饰符:
private - 源码定位:
L71 - 说明:
TODO
- 类型:
内部类/嵌套类型
net.minecraft.server.level.ServerEntity.Synchronizer- 类型:
interface - 修饰符:
public - 源码定位:
L352 - 说明:
TODO
- 类型:
构造器
public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, ServerEntity.Synchronizer synchronizer) @ L73
- 构造器名:ServerEntity
- 源码定位:L73
- 修饰符:public
参数:
- level: ServerLevel
- entity: Entity
- updateInterval: int
- trackDelta: boolean
- synchronizer: ServerEntity.Synchronizer
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void sendChanges() @ L88
- 方法名:sendChanges
- 源码定位:L88
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
private void handleMinecartPosRot(NewMinecartBehavior newMinecartBehavior, byte yRotn, byte xRotn, boolean shouldSendRotation) @ L224
- 方法名:handleMinecartPosRot
- 源码定位:L224
- 返回类型:void
- 修饰符:private
参数:
- newMinecartBehavior: NewMinecartBehavior
- yRotn: byte
- xRotn: byte
- shouldSendRotation: boolean
说明:
TODO
public void removePairing(ServerPlayer player) @ L255
- 方法名:removePairing
- 源码定位:L255
- 返回类型:void
- 修饰符:public
参数:
- player: ServerPlayer
说明:
TODO
public void addPairing(ServerPlayer player) @ L260
- 方法名:addPairing
- 源码定位:L260
- 返回类型:void
- 修饰符:public
参数:
- player: ServerPlayer
说明:
TODO
public void sendPairingData(ServerPlayer player, Consumer<Packet<ClientGamePacketListener>> broadcast) @ L267
- 方法名:sendPairingData
- 源码定位:L267
- 返回类型:void
- 修饰符:public
参数:
- player: ServerPlayer
- broadcast: Consumer<Packet
>
说明:
TODO
public Vec3 getPositionBase() @ L314
- 方法名:getPositionBase
- 源码定位:L314
- 返回类型:Vec3
- 修饰符:public
参数:
- 无
说明:
TODO
public Vec3 getLastSentMovement() @ L318
- 方法名:getLastSentMovement
- 源码定位:L318
- 返回类型:Vec3
- 修饰符:public
参数:
- 无
说明:
TODO
public float getLastSentXRot() @ L322
- 方法名:getLastSentXRot
- 源码定位:L322
- 返回类型:float
- 修饰符:public
参数:
- 无
说明:
TODO
public float getLastSentYRot() @ L326
- 方法名:getLastSentYRot
- 源码定位:L326
- 返回类型:float
- 修饰符:public
参数:
- 无
说明:
TODO
public float getLastSentYHeadRot() @ L330
- 方法名:getLastSentYHeadRot
- 源码定位:L330
- 返回类型:float
- 修饰符:public
参数:
- 无
说明:
TODO
private void sendDirtyEntityData() @ L334
- 方法名:sendDirtyEntityData
- 源码定位:L334
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
代码
public class ServerEntity {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int TOLERANCE_LEVEL_ROTATION = 1;
private static final double TOLERANCE_LEVEL_POSITION = 7.6293945E-6F;
public static final int FORCED_POS_UPDATE_PERIOD = 60;
private static final int FORCED_TELEPORT_PERIOD = 400;
private final ServerLevel level;
private final Entity entity;
private final int updateInterval;
private final boolean trackDelta;
private final ServerEntity.Synchronizer synchronizer;
private final VecDeltaCodec positionCodec = new VecDeltaCodec();
private byte lastSentYRot;
private byte lastSentXRot;
private byte lastSentYHeadRot;
private Vec3 lastSentMovement;
private int tickCount;
private int teleportDelay;
private List<Entity> lastPassengers = Collections.emptyList();
private boolean wasRiding;
private boolean wasOnGround;
private @Nullable List<SynchedEntityData.DataValue<?>> trackedDataValues;
public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, ServerEntity.Synchronizer synchronizer) {
this.level = level;
this.synchronizer = synchronizer;
this.entity = entity;
this.updateInterval = updateInterval;
this.trackDelta = trackDelta;
this.positionCodec.setBase(entity.trackingPosition());
this.lastSentMovement = entity.getDeltaMovement();
this.lastSentYRot = Mth.packDegrees(entity.getYRot());
this.lastSentXRot = Mth.packDegrees(entity.getXRot());
this.lastSentYHeadRot = Mth.packDegrees(entity.getYHeadRot());
this.wasOnGround = entity.onGround();
this.trackedDataValues = entity.getEntityData().getNonDefaultValues();
}
public void sendChanges() {
this.entity.updateDataBeforeSync();
List<Entity> passengers = this.entity.getPassengers();
if (!passengers.equals(this.lastPassengers)) {
this.synchronizer
.sendToTrackingPlayersFiltered(
new ClientboundSetPassengersPacket(this.entity), player -> passengers.contains(player) == this.lastPassengers.contains(player)
);
this.lastPassengers = passengers;
}
if (this.entity instanceof ItemFrame frame && this.tickCount % 10 == 0) {
ItemStack itemStack = frame.getItem();
if (itemStack.getItem() instanceof MapItem) {
MapId id = itemStack.get(DataComponents.MAP_ID);
MapItemSavedData data = MapItem.getSavedData(id, this.level);
if (data != null) {
for (ServerPlayer player : this.level.players()) {
data.tickCarriedBy(player, itemStack, frame);
Packet<?> packet = data.getUpdatePacket(id, player);
if (packet != null) {
player.connection.send(packet);
}
}
}
}
this.sendDirtyEntityData();
}
if (this.tickCount % this.updateInterval == 0 || this.entity.needsSync || this.entity.getEntityData().isDirty()) {
byte yRotn = Mth.packDegrees(this.entity.getYRot());
byte xRotn = Mth.packDegrees(this.entity.getXRot());
boolean shouldSendRotation = Math.abs(yRotn - this.lastSentYRot) >= 1 || Math.abs(xRotn - this.lastSentXRot) >= 1;
if (this.entity.isPassenger()) {
if (shouldSendRotation) {
this.synchronizer.sendToTrackingPlayers(new ClientboundMoveEntityPacket.Rot(this.entity.getId(), yRotn, xRotn, this.entity.onGround()));
this.lastSentYRot = yRotn;
this.lastSentXRot = xRotn;
}
this.positionCodec.setBase(this.entity.trackingPosition());
this.sendDirtyEntityData();
this.wasRiding = true;
} else if (this.entity instanceof AbstractMinecart minecart && minecart.getBehavior() instanceof NewMinecartBehavior newMinecartBehavior) {
this.handleMinecartPosRot(newMinecartBehavior, yRotn, xRotn, shouldSendRotation);
} else {
this.teleportDelay++;
Vec3 currentPosition = this.entity.trackingPosition();
boolean positionChanged = this.positionCodec.delta(currentPosition).lengthSqr() >= 7.6293945E-6F;
Packet<ClientGamePacketListener> packet = null;
boolean pos = positionChanged || this.tickCount % 60 == 0;
boolean sentPosition = false;
boolean sentRotation = false;
long xa = this.positionCodec.encodeX(currentPosition);
long ya = this.positionCodec.encodeY(currentPosition);
long za = this.positionCodec.encodeZ(currentPosition);
boolean deltaTooBig = xa < -32768L || xa > 32767L || ya < -32768L || ya > 32767L || za < -32768L || za > 32767L;
if (this.entity.getRequiresPrecisePosition()
|| deltaTooBig
|| this.teleportDelay > 400
|| this.wasRiding
|| this.wasOnGround != this.entity.onGround()) {
this.wasOnGround = this.entity.onGround();
this.teleportDelay = 0;
packet = ClientboundEntityPositionSyncPacket.of(this.entity);
sentPosition = true;
sentRotation = true;
} else if ((!pos || !shouldSendRotation) && !(this.entity instanceof AbstractArrow)) {
if (pos) {
packet = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short)xa, (short)ya, (short)za, this.entity.onGround());
sentPosition = true;
} else if (shouldSendRotation) {
packet = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), yRotn, xRotn, this.entity.onGround());
sentRotation = true;
}
} else {
packet = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short)xa, (short)ya, (short)za, yRotn, xRotn, this.entity.onGround());
sentPosition = true;
sentRotation = true;
}
if (this.entity.needsSync || this.trackDelta || this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isFallFlying()) {
Vec3 movement = this.entity.getDeltaMovement();
double diff = movement.distanceToSqr(this.lastSentMovement);
if (diff > 1.0E-7 || diff > 0.0 && movement.lengthSqr() == 0.0) {
this.lastSentMovement = movement;
if (this.entity instanceof AbstractHurtingProjectile projectile) {
this.synchronizer
.sendToTrackingPlayers(
new ClientboundBundlePacket(
List.of(
new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement),
new ClientboundProjectilePowerPacket(projectile.getId(), projectile.accelerationPower)
)
)
);
} else {
this.synchronizer.sendToTrackingPlayers(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement));
}
}
}
if (packet != null) {
this.synchronizer.sendToTrackingPlayers(packet);
}
this.sendDirtyEntityData();
if (sentPosition) {
this.positionCodec.setBase(currentPosition);
}
if (sentRotation) {
this.lastSentYRot = yRotn;
this.lastSentXRot = xRotn;
}
this.wasRiding = false;
}
byte yHeadRot = Mth.packDegrees(this.entity.getYHeadRot());
if (Math.abs(yHeadRot - this.lastSentYHeadRot) >= 1) {
this.synchronizer.sendToTrackingPlayers(new ClientboundRotateHeadPacket(this.entity, yHeadRot));
this.lastSentYHeadRot = yHeadRot;
}
this.entity.needsSync = false;
}
this.tickCount++;
if (this.entity.hurtMarked) {
this.entity.hurtMarked = false;
this.synchronizer.sendToTrackingPlayersAndSelf(new ClientboundSetEntityMotionPacket(this.entity));
}
}
private void handleMinecartPosRot(NewMinecartBehavior newMinecartBehavior, byte yRotn, byte xRotn, boolean shouldSendRotation) {
this.sendDirtyEntityData();
if (newMinecartBehavior.lerpSteps.isEmpty()) {
Vec3 movement = this.entity.getDeltaMovement();
double diff = movement.distanceToSqr(this.lastSentMovement);
Vec3 currentPosition = this.entity.trackingPosition();
boolean positionChanged = this.positionCodec.delta(currentPosition).lengthSqr() >= 7.6293945E-6F;
boolean shouldSendPosition = positionChanged || this.tickCount % 60 == 0;
if (shouldSendPosition || shouldSendRotation || diff > 1.0E-7) {
this.synchronizer
.sendToTrackingPlayers(
new ClientboundMoveMinecartPacket(
this.entity.getId(),
List.of(
new NewMinecartBehavior.MinecartStep(
this.entity.position(), this.entity.getDeltaMovement(), this.entity.getYRot(), this.entity.getXRot(), 1.0F
)
)
)
);
}
} else {
this.synchronizer.sendToTrackingPlayers(new ClientboundMoveMinecartPacket(this.entity.getId(), List.copyOf(newMinecartBehavior.lerpSteps)));
newMinecartBehavior.lerpSteps.clear();
}
this.lastSentYRot = yRotn;
this.lastSentXRot = xRotn;
this.positionCodec.setBase(this.entity.position());
}
public void removePairing(ServerPlayer player) {
this.entity.stopSeenByPlayer(player);
player.connection.send(new ClientboundRemoveEntitiesPacket(this.entity.getId()));
}
public void addPairing(ServerPlayer player) {
List<Packet<? super ClientGamePacketListener>> packets = new ArrayList<>();
this.sendPairingData(player, packets::add);
player.connection.send(new ClientboundBundlePacket(packets));
this.entity.startSeenByPlayer(player);
}
public void sendPairingData(ServerPlayer player, Consumer<Packet<ClientGamePacketListener>> broadcast) {
this.entity.updateDataBeforeSync();
if (this.entity.isRemoved()) {
LOGGER.warn("Fetching packet for removed entity {}", this.entity);
}
Packet<ClientGamePacketListener> packet = this.entity.getAddEntityPacket(this);
broadcast.accept(packet);
if (this.trackedDataValues != null) {
broadcast.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.trackedDataValues));
}
if (this.entity instanceof LivingEntity livingEntity) {
Collection<AttributeInstance> attributes = livingEntity.getAttributes().getSyncableAttributes();
if (!attributes.isEmpty()) {
broadcast.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributes));
}
}
if (this.entity instanceof LivingEntity livingEntityx) {
List<Pair<EquipmentSlot, ItemStack>> slots = Lists.newArrayList();
for (EquipmentSlot slot : EquipmentSlot.VALUES) {
ItemStack itemStack = livingEntityx.getItemBySlot(slot);
if (!itemStack.isEmpty()) {
slots.add(Pair.of(slot, itemStack.copy()));
}
}
if (!slots.isEmpty()) {
broadcast.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), slots));
}
}
if (!this.entity.getPassengers().isEmpty()) {
broadcast.accept(new ClientboundSetPassengersPacket(this.entity));
}
if (this.entity.isPassenger()) {
broadcast.accept(new ClientboundSetPassengersPacket(this.entity.getVehicle()));
}
if (this.entity instanceof Leashable leashable && leashable.isLeashed()) {
broadcast.accept(new ClientboundSetEntityLinkPacket(this.entity, leashable.getLeashHolder()));
}
}
public Vec3 getPositionBase() {
return this.positionCodec.getBase();
}
public Vec3 getLastSentMovement() {
return this.lastSentMovement;
}
public float getLastSentXRot() {
return Mth.unpackDegrees(this.lastSentXRot);
}
public float getLastSentYRot() {
return Mth.unpackDegrees(this.lastSentYRot);
}
public float getLastSentYHeadRot() {
return Mth.unpackDegrees(this.lastSentYHeadRot);
}
private void sendDirtyEntityData() {
SynchedEntityData entityData = this.entity.getEntityData();
List<SynchedEntityData.DataValue<?>> packedValues = entityData.packDirty();
if (packedValues != null) {
this.trackedDataValues = entityData.getNonDefaultValues();
this.synchronizer.sendToTrackingPlayersAndSelf(new ClientboundSetEntityDataPacket(this.entity.getId(), packedValues));
}
if (this.entity instanceof LivingEntity) {
Set<AttributeInstance> attributes = ((LivingEntity)this.entity).getAttributes().getAttributesToSync();
if (!attributes.isEmpty()) {
this.synchronizer.sendToTrackingPlayersAndSelf(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributes));
}
attributes.clear();
}
}
public interface Synchronizer {
void sendToTrackingPlayers(Packet<? super ClientGamePacketListener> packet);
void sendToTrackingPlayersAndSelf(Packet<? super ClientGamePacketListener> packet);
void sendToTrackingPlayersFiltered(Packet<? super ClientGamePacketListener> packet, Predicate<ServerPlayer> predicate);
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ClientboundBundlePacket()
- 引用位置:
-
ClientboundEntityPositionSyncPacket
- 引用位置:
方法调用 - 关联成员:
ClientboundEntityPositionSyncPacket.of()
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
ClientboundMoveEntityPacket.Pos(), ClientboundMoveEntityPacket.PosRot(), ClientboundMoveEntityPacket.Rot(), Pos(), PosRot(), Rot()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ClientboundMoveMinecartPacket()
- 引用位置:
-
ClientboundProjectilePowerPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundProjectilePowerPacket()
- 引用位置:
-
ClientboundRemoveEntitiesPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundRemoveEntitiesPacket()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ClientboundRotateHeadPacket()
- 引用位置:
-
ClientboundSetEntityDataPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundSetEntityDataPacket()
- 引用位置:
-
ClientboundSetEntityLinkPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundSetEntityLinkPacket()
- 引用位置:
-
ClientboundSetEntityMotionPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundSetEntityMotionPacket()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
ClientboundSetEquipmentPacket()
- 引用位置:
-
ClientboundSetPassengersPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundSetPassengersPacket()
- 引用位置:
-
ClientboundUpdateAttributesPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundUpdateAttributesPacket()
- 引用位置:
-
- 引用位置:
字段/构造调用 - 关联成员:
VecDeltaCodec()
- 引用位置:
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.packDegrees(), Mth.unpackDegrees()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数/方法调用/构造调用 - 关联成员:
MinecartStep(), NewMinecartBehavior.MinecartStep()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
MapItem.getSavedData()
- 引用位置:
-
- 引用位置:
字段/返回值
- 引用位置: