mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 19:47:44 +01:00
Player#setInstance can now take an optional Position parameter
This commit is contained in:
parent
edf22fcb66
commit
ab73b0fa3e
@ -1122,34 +1122,6 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
||||
this.eyeHeight = eyeHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if this entity is in the same chunk as the specified position.
|
||||
*
|
||||
* @param position the checked position chunk
|
||||
* @return true if the entity is in the same chunk as {@code position}
|
||||
*/
|
||||
public boolean sameChunk(@NotNull Position position) {
|
||||
Check.notNull(position, "Position cannot be null");
|
||||
final Position pos = getPosition();
|
||||
final int chunkX1 = ChunkUtils.getChunkCoordinate((int) Math.floor(pos.getX()));
|
||||
final int chunkZ1 = ChunkUtils.getChunkCoordinate((int) Math.floor(pos.getZ()));
|
||||
|
||||
final int chunkX2 = ChunkUtils.getChunkCoordinate((int) Math.floor(position.getX()));
|
||||
final int chunkZ2 = ChunkUtils.getChunkCoordinate((int) Math.floor(position.getZ()));
|
||||
|
||||
return chunkX1 == chunkX2 && chunkZ1 == chunkZ2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the entity is in the same chunk as another.
|
||||
*
|
||||
* @param entity the entity to check
|
||||
* @return true if both entities are in the same chunk, false otherwise
|
||||
*/
|
||||
public boolean sameChunk(@NotNull Entity entity) {
|
||||
return sameChunk(entity.getPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the entity from the server immediately.
|
||||
* <p>
|
||||
|
@ -66,6 +66,7 @@ public final class EntityManager {
|
||||
|
||||
waitingPlayer.init();
|
||||
|
||||
// Spawn the player at Player#getRespawnPoint during the next instance tick
|
||||
spawningInstance.scheduleNextTick(waitingPlayer::setInstance);
|
||||
}
|
||||
}
|
||||
|
@ -683,22 +683,19 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
* <p>
|
||||
* Be aware that because chunk operations are expensive,
|
||||
* it is possible for this method to be non-blocking when retrieving chunks is required.
|
||||
* <p>
|
||||
* When this method is called for the first time (during player login), the player will be teleport at {@link #getRespawnPoint()}.
|
||||
*
|
||||
* @param instance the new instance of the player
|
||||
* @param instance the new player instance
|
||||
*/
|
||||
@Override
|
||||
public void setInstance(@NotNull Instance instance) {
|
||||
public void setInstance(@NotNull Instance instance, @NotNull Position spawnPosition) {
|
||||
Check.notNull(instance, "instance cannot be null!");
|
||||
Check.argCondition(this.instance == instance, "Instance should be different than the current one");
|
||||
|
||||
final boolean firstSpawn = this.instance == null; // TODO: Handle player reconnections, must be false in that case too
|
||||
|
||||
// true if the chunks need to be sent to the client, can be false if the instances share the same chunks (eg SharedInstance)
|
||||
final boolean needWorldRefresh = !InstanceUtils.areLinked(this.instance, instance);
|
||||
|
||||
if (needWorldRefresh) {
|
||||
final boolean firstSpawn = this.instance == null; // TODO: Handle player reconnections, must be false in that case too
|
||||
|
||||
// Remove all previous viewable chunks (from the previous instance)
|
||||
for (Chunk viewableChunk : viewableChunks) {
|
||||
viewableChunk.removeViewer(this);
|
||||
@ -712,13 +709,12 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
// Load all the required chunks
|
||||
final Position pos = firstSpawn ? getRespawnPoint() : position;
|
||||
final long[] visibleChunks = ChunkUtils.getChunksInRange(pos, getChunkRange());
|
||||
final long[] visibleChunks = ChunkUtils.getChunksInRange(spawnPosition, getChunkRange());
|
||||
|
||||
final ChunkCallback eachCallback = chunk -> {
|
||||
if (chunk != null) {
|
||||
final int chunkX = ChunkUtils.getChunkCoordinate((int) pos.getX());
|
||||
final int chunkZ = ChunkUtils.getChunkCoordinate((int) pos.getZ());
|
||||
final int chunkX = ChunkUtils.getChunkCoordinate((int) spawnPosition.getX());
|
||||
final int chunkZ = ChunkUtils.getChunkCoordinate((int) spawnPosition.getZ());
|
||||
if (chunk.getChunkX() == chunkX &&
|
||||
chunk.getChunkZ() == chunkZ) {
|
||||
updateViewPosition(chunkX, chunkZ);
|
||||
@ -728,7 +724,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
|
||||
final ChunkCallback endCallback = chunk -> {
|
||||
// This is the last chunk to be loaded , spawn player
|
||||
spawnPlayer(instance, firstSpawn);
|
||||
spawnPlayer(instance, spawnPosition, firstSpawn);
|
||||
};
|
||||
|
||||
// Chunk 0;0 always needs to be loaded
|
||||
@ -739,26 +735,40 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
} else {
|
||||
// The player already has the good version of all the chunks.
|
||||
// We just need to refresh his entity viewing list and add him to the instance
|
||||
spawnPlayer(instance, false);
|
||||
spawnPlayer(instance, spawnPosition, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the player instance without changing its position (defaulted to {@link #getRespawnPoint()}
|
||||
* if the player is not in any instance.
|
||||
*
|
||||
* @param instance the new player instance
|
||||
* @see #setInstance(Instance, Position)
|
||||
*/
|
||||
@Override
|
||||
public void setInstance(@NotNull Instance instance) {
|
||||
setInstance(instance, this.instance != null ? getPosition() : getRespawnPoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to spawn the player once the client has all the required chunks.
|
||||
* <p>
|
||||
* Does add the player to {@code instance}, remove all viewable entities and call {@link PlayerSpawnEvent}.
|
||||
* <p>
|
||||
* UNSAFE: only called with {@link #setInstance(Instance)}.
|
||||
* UNSAFE: only called with {@link #setInstance(Instance, Position)}.
|
||||
*
|
||||
* @param firstSpawn true if this is the player first spawn
|
||||
* @param spawnPosition the position to teleport the player
|
||||
* @param firstSpawn true if this is the player first spawn
|
||||
*/
|
||||
private void spawnPlayer(@NotNull Instance instance, boolean firstSpawn) {
|
||||
private void spawnPlayer(@NotNull Instance instance, @Nullable Position spawnPosition, boolean firstSpawn) {
|
||||
this.viewableEntities.forEach(entity -> entity.removeViewer(this));
|
||||
|
||||
super.setInstance(instance);
|
||||
|
||||
if (firstSpawn) {
|
||||
teleport(getRespawnPoint());
|
||||
if (spawnPosition != null && !position.isSimilar(spawnPosition)) {
|
||||
teleport(spawnPosition,
|
||||
position.inSameChunk(spawnPosition) ? () -> refreshVisibleChunks(getChunk()) : null);
|
||||
} else {
|
||||
refreshVisibleChunks(getChunk());
|
||||
}
|
||||
@ -1519,7 +1529,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
// New chunks indexes
|
||||
final long[] updatedVisibleChunks = ChunkUtils.getChunksInRange(newChunk.toPosition(), getChunkRange());
|
||||
|
||||
// Find the difference between the two arrays¬
|
||||
// Find the difference between the two arrays
|
||||
final int[] oldChunks = ArrayUtils.getDifferencesBetweenArray(lastVisibleChunks, updatedVisibleChunks);
|
||||
final int[] newChunks = ArrayUtils.getDifferencesBetweenArray(updatedVisibleChunks, lastVisibleChunks);
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
package net.minestom.server.utils;
|
||||
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -72,8 +75,8 @@ public class Position {
|
||||
|
||||
/**
|
||||
* Gets the distance between 2 positions.
|
||||
* In cases where performance matters, {@link #getDistanceSquared(Position)} should be used
|
||||
* as it does not perform the expensive Math.sqrt method.
|
||||
* In cases where performance matters, {@link #getDistanceSquared(Position)} should be used
|
||||
* as it does not perform the expensive Math.sqrt method.
|
||||
*
|
||||
* @param position the second position
|
||||
* @return the distance between {@code this} and {@code position}
|
||||
@ -86,15 +89,15 @@ public class Position {
|
||||
|
||||
/**
|
||||
* Gets the square distance to another position.
|
||||
*
|
||||
* @param position the second position
|
||||
* @return the squared distance between {@code this} and {@code position}
|
||||
*/
|
||||
public float getDistanceSquared(Position position) {
|
||||
return MathUtils.square(getX() - position.getX()) +
|
||||
MathUtils.square(getY() - position.getY()) +
|
||||
MathUtils.square(getZ() - position.getZ());
|
||||
}
|
||||
*
|
||||
* @param position the second position
|
||||
* @return the squared distance between {@code this} and {@code position}
|
||||
*/
|
||||
public float getDistanceSquared(Position position) {
|
||||
return MathUtils.square(getX() - position.getX()) +
|
||||
MathUtils.square(getY() - position.getY()) +
|
||||
MathUtils.square(getZ() - position.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a unit-vector pointing in the direction that this Location is
|
||||
@ -209,7 +212,7 @@ public class Position {
|
||||
* @param position the position to compare
|
||||
* @return true if the two positions are similar
|
||||
*/
|
||||
public boolean isSimilar(Position position) {
|
||||
public boolean isSimilar(@NotNull Position position) {
|
||||
return Float.compare(position.x, x) == 0 &&
|
||||
Float.compare(position.y, y) == 0 &&
|
||||
Float.compare(position.z, z) == 0;
|
||||
@ -221,11 +224,27 @@ public class Position {
|
||||
* @param position the position to compare
|
||||
* @return true if the two positions have the same view
|
||||
*/
|
||||
public boolean hasSimilarView(Position position) {
|
||||
public boolean hasSimilarView(@NotNull Position position) {
|
||||
return Float.compare(position.yaw, yaw) == 0 &&
|
||||
Float.compare(position.pitch, pitch) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if two positions are in the same chunk.
|
||||
*
|
||||
* @param position the checked position chunk
|
||||
* @return true if 'this' is in the same chunk as {@code position}
|
||||
*/
|
||||
public boolean inSameChunk(@NotNull Position position) {
|
||||
final int chunkX1 = ChunkUtils.getChunkCoordinate((int) Math.floor(getX()));
|
||||
final int chunkZ1 = ChunkUtils.getChunkCoordinate((int) Math.floor(getZ()));
|
||||
|
||||
final int chunkX2 = ChunkUtils.getChunkCoordinate((int) Math.floor(position.getX()));
|
||||
final int chunkZ2 = ChunkUtils.getChunkCoordinate((int) Math.floor(position.getZ()));
|
||||
|
||||
return chunkX1 == chunkX2 && chunkZ1 == chunkZ2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z, yaw, pitch);
|
||||
|
Loading…
Reference in New Issue
Block a user