mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-29 04:28:21 +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;
|
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.
|
* Removes the entity from the server immediately.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -66,6 +66,7 @@ public final class EntityManager {
|
|||||||
|
|
||||||
waitingPlayer.init();
|
waitingPlayer.init();
|
||||||
|
|
||||||
|
// Spawn the player at Player#getRespawnPoint during the next instance tick
|
||||||
spawningInstance.scheduleNextTick(waitingPlayer::setInstance);
|
spawningInstance.scheduleNextTick(waitingPlayer::setInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -683,22 +683,19 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
* <p>
|
* <p>
|
||||||
* Be aware that because chunk operations are expensive,
|
* Be aware that because chunk operations are expensive,
|
||||||
* it is possible for this method to be non-blocking when retrieving chunks is required.
|
* 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, @NotNull Position spawnPosition) {
|
||||||
public void setInstance(@NotNull Instance instance) {
|
|
||||||
Check.notNull(instance, "instance cannot be null!");
|
Check.notNull(instance, "instance cannot be null!");
|
||||||
Check.argCondition(this.instance == instance, "Instance should be different than the current one");
|
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)
|
// 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);
|
final boolean needWorldRefresh = !InstanceUtils.areLinked(this.instance, instance);
|
||||||
|
|
||||||
if (needWorldRefresh) {
|
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)
|
// Remove all previous viewable chunks (from the previous instance)
|
||||||
for (Chunk viewableChunk : viewableChunks) {
|
for (Chunk viewableChunk : viewableChunks) {
|
||||||
viewableChunk.removeViewer(this);
|
viewableChunk.removeViewer(this);
|
||||||
@ -712,13 +709,12 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load all the required chunks
|
// Load all the required chunks
|
||||||
final Position pos = firstSpawn ? getRespawnPoint() : position;
|
final long[] visibleChunks = ChunkUtils.getChunksInRange(spawnPosition, getChunkRange());
|
||||||
final long[] visibleChunks = ChunkUtils.getChunksInRange(pos, getChunkRange());
|
|
||||||
|
|
||||||
final ChunkCallback eachCallback = chunk -> {
|
final ChunkCallback eachCallback = chunk -> {
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
final int chunkX = ChunkUtils.getChunkCoordinate((int) pos.getX());
|
final int chunkX = ChunkUtils.getChunkCoordinate((int) spawnPosition.getX());
|
||||||
final int chunkZ = ChunkUtils.getChunkCoordinate((int) pos.getZ());
|
final int chunkZ = ChunkUtils.getChunkCoordinate((int) spawnPosition.getZ());
|
||||||
if (chunk.getChunkX() == chunkX &&
|
if (chunk.getChunkX() == chunkX &&
|
||||||
chunk.getChunkZ() == chunkZ) {
|
chunk.getChunkZ() == chunkZ) {
|
||||||
updateViewPosition(chunkX, chunkZ);
|
updateViewPosition(chunkX, chunkZ);
|
||||||
@ -728,7 +724,7 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
|
|
||||||
final ChunkCallback endCallback = chunk -> {
|
final ChunkCallback endCallback = chunk -> {
|
||||||
// This is the last chunk to be loaded , spawn player
|
// 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
|
// Chunk 0;0 always needs to be loaded
|
||||||
@ -739,26 +735,40 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
} else {
|
} else {
|
||||||
// The player already has the good version of all the chunks.
|
// 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
|
// 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.
|
* Used to spawn the player once the client has all the required chunks.
|
||||||
* <p>
|
* <p>
|
||||||
* Does add the player to {@code instance}, remove all viewable entities and call {@link PlayerSpawnEvent}.
|
* Does add the player to {@code instance}, remove all viewable entities and call {@link PlayerSpawnEvent}.
|
||||||
* <p>
|
* <p>
|
||||||
* UNSAFE: only called with {@link #setInstance(Instance)}.
|
* UNSAFE: only called with {@link #setInstance(Instance, Position)}.
|
||||||
*
|
*
|
||||||
|
* @param spawnPosition the position to teleport the player
|
||||||
* @param firstSpawn true if this is the player first spawn
|
* @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));
|
this.viewableEntities.forEach(entity -> entity.removeViewer(this));
|
||||||
|
|
||||||
super.setInstance(instance);
|
super.setInstance(instance);
|
||||||
|
|
||||||
if (firstSpawn) {
|
if (spawnPosition != null && !position.isSimilar(spawnPosition)) {
|
||||||
teleport(getRespawnPoint());
|
teleport(spawnPosition,
|
||||||
|
position.inSameChunk(spawnPosition) ? () -> refreshVisibleChunks(getChunk()) : null);
|
||||||
} else {
|
} else {
|
||||||
refreshVisibleChunks(getChunk());
|
refreshVisibleChunks(getChunk());
|
||||||
}
|
}
|
||||||
@ -1519,7 +1529,7 @@ public class Player extends LivingEntity implements CommandSender {
|
|||||||
// New chunks indexes
|
// New chunks indexes
|
||||||
final long[] updatedVisibleChunks = ChunkUtils.getChunksInRange(newChunk.toPosition(), getChunkRange());
|
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[] oldChunks = ArrayUtils.getDifferencesBetweenArray(lastVisibleChunks, updatedVisibleChunks);
|
||||||
final int[] newChunks = ArrayUtils.getDifferencesBetweenArray(updatedVisibleChunks, lastVisibleChunks);
|
final int[] newChunks = ArrayUtils.getDifferencesBetweenArray(updatedVisibleChunks, lastVisibleChunks);
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package net.minestom.server.utils;
|
package net.minestom.server.utils;
|
||||||
|
|
||||||
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -209,7 +212,7 @@ public class Position {
|
|||||||
* @param position the position to compare
|
* @param position the position to compare
|
||||||
* @return true if the two positions are similar
|
* @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 &&
|
return Float.compare(position.x, x) == 0 &&
|
||||||
Float.compare(position.y, y) == 0 &&
|
Float.compare(position.y, y) == 0 &&
|
||||||
Float.compare(position.z, z) == 0;
|
Float.compare(position.z, z) == 0;
|
||||||
@ -221,11 +224,27 @@ public class Position {
|
|||||||
* @param position the position to compare
|
* @param position the position to compare
|
||||||
* @return true if the two positions have the same view
|
* @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 &&
|
return Float.compare(position.yaw, yaw) == 0 &&
|
||||||
Float.compare(position.pitch, pitch) == 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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(x, y, z, yaw, pitch);
|
return Objects.hash(x, y, z, yaw, pitch);
|
||||||
|
Loading…
Reference in New Issue
Block a user