mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-31 21:48:08 +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 boolean isNettyClient;
|
||||
|
||||
public Entity(@NotNull EntityType entityType, @NotNull UUID uuid) {
|
||||
this.id = generateId();
|
||||
this.entityType = entityType;
|
||||
@ -152,6 +154,8 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
|
||||
|
||||
setAutoViewable(true);
|
||||
|
||||
isNettyClient = PlayerUtils.isNettyClient(this);
|
||||
|
||||
Entity.ENTITY_BY_ID.put(id, 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
sendPositionUpdate();
|
||||
|
||||
// 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.
|
||||
*
|
||||
|
@ -148,9 +148,6 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
// Only used if multi player breaking is disabled, contains only this player
|
||||
private final Set<Player> targetBreakers = Collections.singleton(this);
|
||||
|
||||
// Position synchronization with viewers
|
||||
private final Position lastSyncedPlayerPosition;
|
||||
|
||||
// Experience orb pickup
|
||||
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);
|
||||
|
||||
setRespawnPoint(new Position(0, 0, 0));
|
||||
this.lastSyncedPlayerPosition = new Position();
|
||||
|
||||
this.settings = new PlayerSettings();
|
||||
this.inventory = new PlayerInventory(this);
|
||||
@ -421,50 +417,6 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
|
||||
// Tick event
|
||||
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
|
||||
@ -2007,6 +1959,10 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
playerConnection.sendPacket(updateViewPositionPacket);
|
||||
}
|
||||
|
||||
public int getNextTeleportId() {
|
||||
return teleportId.getAndIncrement();
|
||||
}
|
||||
|
||||
public int getLastSentTeleportId() {
|
||||
return teleportId.get();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user