mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-19 06:32:03 +01:00
Extracted position sending from Entity#tick and improved checks, also removed duplicate code from Player#update
This commit is contained in:
parent
c027d649cf
commit
66f1c8847d
@ -138,6 +138,8 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
|
|||||||
*/
|
*/
|
||||||
private final Object entityTypeLock = new Object();
|
private final Object entityTypeLock = new Object();
|
||||||
|
|
||||||
|
private final boolean isNettyClient;
|
||||||
|
|
||||||
public Entity(@NotNull EntityType entityType, @NotNull UUID uuid) {
|
public Entity(@NotNull EntityType entityType, @NotNull UUID uuid) {
|
||||||
this.id = generateId();
|
this.id = generateId();
|
||||||
this.entityType = entityType;
|
this.entityType = entityType;
|
||||||
@ -152,6 +154,8 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
|
|||||||
|
|
||||||
setAutoViewable(true);
|
setAutoViewable(true);
|
||||||
|
|
||||||
|
isNettyClient = PlayerUtils.isNettyClient(this);
|
||||||
|
|
||||||
Entity.ENTITY_BY_ID.put(id, this);
|
Entity.ENTITY_BY_ID.put(id, this);
|
||||||
Entity.ENTITY_BY_UUID.put(uuid, this);
|
Entity.ENTITY_BY_UUID.put(uuid, this);
|
||||||
}
|
}
|
||||||
@ -493,47 +497,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean isNettyClient = PlayerUtils.isNettyClient(this);
|
sendPositionUpdate();
|
||||||
|
|
||||||
// Synchronization with updated fields in #getPosition()
|
|
||||||
{
|
|
||||||
final boolean positionChange = !position.isSimilar(lastSyncedPosition);
|
|
||||||
final boolean viewChange = !position.hasSimilarView(lastSyncedPosition);
|
|
||||||
final double distance = positionChange ? position.getDistance(lastSyncedPosition) : 0;
|
|
||||||
|
|
||||||
if (distance >= 8 || (positionChange && isNettyClient)) {
|
|
||||||
// Teleport has the priority over everything else
|
|
||||||
teleport(position);
|
|
||||||
} else if (positionChange && viewChange) {
|
|
||||||
EntityPositionAndRotationPacket positionAndRotationPacket =
|
|
||||||
EntityPositionAndRotationPacket.getPacket(getEntityId(),
|
|
||||||
position, lastSyncedPosition, isOnGround());
|
|
||||||
|
|
||||||
sendPacketToViewersAndSelf(positionAndRotationPacket);
|
|
||||||
|
|
||||||
refreshPosition(position.clone());
|
|
||||||
|
|
||||||
// Fix head rotation
|
|
||||||
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
|
|
||||||
entityHeadLookPacket.entityId = getEntityId();
|
|
||||||
entityHeadLookPacket.yaw = position.getYaw();
|
|
||||||
|
|
||||||
sendPacketToViewersAndSelf(entityHeadLookPacket);
|
|
||||||
|
|
||||||
} else if (positionChange) {
|
|
||||||
EntityPositionPacket entityPositionPacket = EntityPositionPacket.getPacket(getEntityId(),
|
|
||||||
position, lastSyncedPosition, isOnGround());
|
|
||||||
|
|
||||||
sendPacketToViewersAndSelf(entityPositionPacket);
|
|
||||||
|
|
||||||
refreshPosition(position.clone());
|
|
||||||
|
|
||||||
} else if (viewChange) {
|
|
||||||
// Yaw/Pitch
|
|
||||||
setView(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entity tick
|
// Entity tick
|
||||||
{
|
{
|
||||||
@ -713,6 +677,70 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the correct packets to update the entity's position, should be called
|
||||||
|
* every tick. The movement is checked inside the method!
|
||||||
|
* <p>
|
||||||
|
* The following packets are sent to viewers (check are performed in this order):
|
||||||
|
* <ol>
|
||||||
|
* <li>{@link EntityTeleportPacket} if <pre>distanceX > 8 || distanceY > 8 || distanceZ > 8</pre>
|
||||||
|
* <i>(performed using {@link #synchronizePosition()})</i></li>
|
||||||
|
* <li>{@link EntityPositionAndRotationPacket} if <pre>positionChange && viewChange</pre></li>
|
||||||
|
* <li>{@link EntityPositionPacket} if <pre>positionChange</pre></li>
|
||||||
|
* <li>{@link EntityRotationPacket} if <pre>viewChange</pre>
|
||||||
|
* <i>(performed using {@link #setView(float, float)})</i></li>
|
||||||
|
* </ol>
|
||||||
|
* In case of a player's position and/or view change an additional {@link PlayerPositionAndLookPacket}
|
||||||
|
* is sent to self.
|
||||||
|
*/
|
||||||
|
protected void sendPositionUpdate() {
|
||||||
|
final boolean viewChange = !position.hasSimilarView(lastSyncedPosition);
|
||||||
|
final double distanceX = Math.abs(position.getX()-lastSyncedPosition.getX());
|
||||||
|
final double distanceY = Math.abs(position.getY()-lastSyncedPosition.getY());
|
||||||
|
final double distanceZ = Math.abs(position.getZ()-lastSyncedPosition.getZ());
|
||||||
|
final boolean positionChange = (distanceX+distanceY+distanceZ) > 0;
|
||||||
|
|
||||||
|
if (distanceX > 8 || distanceY > 8 || distanceZ > 8) {
|
||||||
|
synchronizePosition();
|
||||||
|
// #synchronizePosition sets sync fields, it's safe to return
|
||||||
|
return;
|
||||||
|
} else if (positionChange && viewChange) {
|
||||||
|
EntityPositionAndRotationPacket positionAndRotationPacket = EntityPositionAndRotationPacket
|
||||||
|
.getPacket(getEntityId(), position, lastSyncedPosition, isOnGround());
|
||||||
|
sendPacketToViewers(positionAndRotationPacket);
|
||||||
|
|
||||||
|
// Fix head rotation
|
||||||
|
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
|
||||||
|
entityHeadLookPacket.entityId = getEntityId();
|
||||||
|
entityHeadLookPacket.yaw = position.getYaw();
|
||||||
|
sendPacketToViewersAndSelf(entityHeadLookPacket);
|
||||||
|
} else if (positionChange) {
|
||||||
|
final EntityPositionPacket entityPositionPacket = EntityPositionPacket
|
||||||
|
.getPacket(getEntityId(), position, lastSyncedPosition, onGround);
|
||||||
|
sendPacketToViewers(entityPositionPacket);
|
||||||
|
} else if (viewChange) {
|
||||||
|
setView(position.getYaw(), position.getPitch());
|
||||||
|
/*
|
||||||
|
#setView indirectly sets last sync field and it appears that EntityRotation packet
|
||||||
|
can be used for players as well, so it's safe to return
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Nothing changed, return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNettyClient) {
|
||||||
|
final PlayerPositionAndLookPacket playerPositionAndLookPacket = new PlayerPositionAndLookPacket();
|
||||||
|
playerPositionAndLookPacket.flags = 0b111;
|
||||||
|
playerPositionAndLookPacket.position = position.clone().subtract(lastSyncedPosition.getX(), lastSyncedPosition.getY(), lastSyncedPosition.getZ());
|
||||||
|
playerPositionAndLookPacket.teleportId = ((Player)this).getNextTeleportId();
|
||||||
|
((Player) this).getPlayerConnection().sendPacket(playerPositionAndLookPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastSyncedPosition.set(position);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of ticks this entity has been active for.
|
* Gets the number of ticks this entity has been active for.
|
||||||
*
|
*
|
||||||
|
@ -148,9 +148,6 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
// Only used if multi player breaking is disabled, contains only this player
|
// Only used if multi player breaking is disabled, contains only this player
|
||||||
private final Set<Player> targetBreakers = Collections.singleton(this);
|
private final Set<Player> targetBreakers = Collections.singleton(this);
|
||||||
|
|
||||||
// Position synchronization with viewers
|
|
||||||
private final Position lastSyncedPlayerPosition;
|
|
||||||
|
|
||||||
// Experience orb pickup
|
// Experience orb pickup
|
||||||
protected Cooldown experiencePickupCooldown = new Cooldown(new UpdateOption(10, TimeUnit.TICK));
|
protected Cooldown experiencePickupCooldown = new Cooldown(new UpdateOption(10, TimeUnit.TICK));
|
||||||
|
|
||||||
@ -187,7 +184,6 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
setBoundingBox(0.6f, 1.8f, 0.6f);
|
setBoundingBox(0.6f, 1.8f, 0.6f);
|
||||||
|
|
||||||
setRespawnPoint(new Position(0, 0, 0));
|
setRespawnPoint(new Position(0, 0, 0));
|
||||||
this.lastSyncedPlayerPosition = new Position();
|
|
||||||
|
|
||||||
this.settings = new PlayerSettings();
|
this.settings = new PlayerSettings();
|
||||||
this.inventory = new PlayerInventory(this);
|
this.inventory = new PlayerInventory(this);
|
||||||
@ -421,50 +417,6 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
|
|
||||||
// Tick event
|
// Tick event
|
||||||
callEvent(PlayerTickEvent.class, playerTickEvent);
|
callEvent(PlayerTickEvent.class, playerTickEvent);
|
||||||
|
|
||||||
// Multiplayer sync
|
|
||||||
if (!viewers.isEmpty()) {
|
|
||||||
final boolean positionChanged = !position.isSimilar(lastSyncedPlayerPosition);
|
|
||||||
final boolean viewChanged = !position.hasSimilarView(lastSyncedPlayerPosition);
|
|
||||||
|
|
||||||
if (positionChanged || viewChanged) {
|
|
||||||
// Player moved since last time
|
|
||||||
|
|
||||||
ServerPacket updatePacket;
|
|
||||||
ServerPacket optionalUpdatePacket = null;
|
|
||||||
if (positionChanged && viewChanged) {
|
|
||||||
updatePacket = EntityPositionAndRotationPacket.getPacket(getEntityId(),
|
|
||||||
position, lastSyncedPlayerPosition, onGround);
|
|
||||||
} else if (positionChanged) {
|
|
||||||
updatePacket = EntityPositionPacket.getPacket(getEntityId(),
|
|
||||||
position, lastSyncedPlayerPosition, onGround);
|
|
||||||
} else {
|
|
||||||
// View changed
|
|
||||||
updatePacket = EntityRotationPacket.getPacket(getEntityId(),
|
|
||||||
position.getYaw(), position.getPitch(), onGround);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (viewChanged) {
|
|
||||||
// Yaw from the rotation packet seems to be ignored, which is why this is required
|
|
||||||
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
|
|
||||||
entityHeadLookPacket.entityId = getEntityId();
|
|
||||||
entityHeadLookPacket.yaw = position.getYaw();
|
|
||||||
optionalUpdatePacket = entityHeadLookPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the update packet
|
|
||||||
if (optionalUpdatePacket != null) {
|
|
||||||
sendPacketsToViewers(updatePacket, optionalUpdatePacket);
|
|
||||||
} else {
|
|
||||||
sendPacketToViewers(updatePacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update sync data
|
|
||||||
lastSyncedPlayerPosition.set(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2007,6 +1959,10 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
playerConnection.sendPacket(updateViewPositionPacket);
|
playerConnection.sendPacket(updateViewPositionPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getNextTeleportId() {
|
||||||
|
return teleportId.getAndIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
public int getLastSentTeleportId() {
|
public int getLastSentTeleportId() {
|
||||||
return teleportId.get();
|
return teleportId.get();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user