mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 03:27:56 +01:00
Fixed teleportation & improved first chunk loading
This commit is contained in:
parent
666f433ae7
commit
f43bf11e66
@ -4,6 +4,7 @@ import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.net.PacketWriterUtils;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public interface Viewable {
|
||||
@ -19,60 +20,31 @@ public interface Viewable {
|
||||
}
|
||||
|
||||
default void sendPacketToViewers(ServerPacket packet) {
|
||||
if (getViewers().isEmpty())
|
||||
return;
|
||||
|
||||
PacketWriterUtils.writeCallbackPacket(packet, buffer -> {
|
||||
int size = getViewers().size();
|
||||
if (size == 0)
|
||||
return;
|
||||
buffer.getData().retain(size).markReaderIndex();
|
||||
for (Player viewer : getViewers()) {
|
||||
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
|
||||
buffer.getData().resetReaderIndex();
|
||||
}
|
||||
});
|
||||
PacketWriterUtils.writeAndSend(getViewers(), packet);
|
||||
}
|
||||
|
||||
default void sendPacketsToViewers(ServerPacket... packets) {
|
||||
if (getViewers().isEmpty())
|
||||
return;
|
||||
|
||||
for (ServerPacket packet : packets) {
|
||||
PacketWriterUtils.writeCallbackPacket(packet, buffer -> {
|
||||
int size = getViewers().size();
|
||||
if (size == 0)
|
||||
return;
|
||||
buffer.getData().retain(size).markReaderIndex();
|
||||
for (Player viewer : getViewers()) {
|
||||
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
|
||||
buffer.getData().resetReaderIndex();
|
||||
}
|
||||
});
|
||||
PacketWriterUtils.writeAndSend(getViewers(), packet);
|
||||
}
|
||||
}
|
||||
|
||||
default void sendPacketToViewersAndSelf(ServerPacket packet) {
|
||||
if (this instanceof Player) {
|
||||
UNSAFE_sendPacketToViewersAndSelf(packet);
|
||||
if (getViewers().isEmpty()) {
|
||||
((Player) this).getPlayerConnection().sendPacket(packet);
|
||||
} else {
|
||||
UNSAFE_sendPacketToViewersAndSelf(packet);
|
||||
}
|
||||
} else {
|
||||
sendPacketToViewers(packet);
|
||||
}
|
||||
}
|
||||
|
||||
private void UNSAFE_sendPacketToViewersAndSelf(ServerPacket packet) {
|
||||
PacketWriterUtils.writeCallbackPacket(packet, buffer -> {
|
||||
int size = getViewers().size();
|
||||
buffer.getData().retain(size + 1).markReaderIndex();
|
||||
((Player) this).getPlayerConnection().writeUnencodedPacket(buffer);
|
||||
buffer.getData().resetReaderIndex();
|
||||
if (size != 0) {
|
||||
for (Player viewer : getViewers()) {
|
||||
buffer.getData().resetReaderIndex();
|
||||
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
|
||||
}
|
||||
}
|
||||
});
|
||||
Set<Player> recipients = new HashSet<>(getViewers());
|
||||
recipients.add((Player) this);
|
||||
PacketWriterUtils.writeAndSend(recipients, packet);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
|
||||
protected Entity vehicle;
|
||||
// Velocity
|
||||
// TODO gravity implementation for entity other than players
|
||||
protected Vector velocity = new Vector(); // Movement in block per second
|
||||
protected float gravityDragPerTick;
|
||||
private int gravityTickCounter;
|
||||
@ -247,8 +246,9 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
gravityTickCounter = 0;
|
||||
}
|
||||
|
||||
if (this instanceof EntityCreature) // Objects are automatically updated client side
|
||||
if (this instanceof EntityCreature) {
|
||||
teleport(getPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,7 +444,7 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
position.setZ(z);
|
||||
|
||||
for (Entity passenger : getPassengers()) {
|
||||
passenger.position = getPosition().clone();
|
||||
passenger.refreshPosition(x, y, z);
|
||||
}
|
||||
|
||||
Instance instance = getInstance();
|
||||
@ -455,17 +455,8 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
synchronized (instance) {
|
||||
instance.removeEntityFromChunk(this, lastChunk);
|
||||
instance.addEntityToChunk(this, newChunk);
|
||||
|
||||
for (Entity passenger : getPassengers()) {
|
||||
instance.removeEntityFromChunk(passenger, lastChunk);
|
||||
instance.addEntityToChunk(passenger, newChunk);
|
||||
}
|
||||
}
|
||||
updateView(this, lastChunk, newChunk);
|
||||
for (Entity passenger : getPassengers()) {
|
||||
updateView(passenger, lastChunk, newChunk);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -647,7 +638,9 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
entityTeleportPacket.position = getPosition();
|
||||
entityTeleportPacket.onGround = isOnGround();
|
||||
sendPacketToViewers(entityTeleportPacket);
|
||||
sendPacketToViewers(getPassengersPacket());
|
||||
|
||||
if (!passengers.isEmpty())
|
||||
sendPacketToViewers(getPassengersPacket());
|
||||
}
|
||||
|
||||
private void fillAirTickMetaData(Buffer buffer) {
|
||||
|
@ -13,6 +13,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EntityManager {
|
||||
@ -43,18 +44,28 @@ public class EntityManager {
|
||||
Position position = playerCache.getPosition();
|
||||
|
||||
long[] visibleChunks = ChunkUtils.getChunksInRange(position, Main.CHUNK_VIEW_DISTANCE);
|
||||
for (int i = 0; i < visibleChunks.length; i++) {
|
||||
int length = visibleChunks.length;
|
||||
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
int[] chunkPos = ChunkUtils.getChunkCoord(visibleChunks[i]);
|
||||
int chunkX = chunkPos[0];
|
||||
int chunkZ = chunkPos[1];
|
||||
boolean isLast = i == visibleChunks.length - 1;
|
||||
Consumer<Chunk> callback = isLast ? chunk -> {
|
||||
playerCache.spawned = true;
|
||||
playerCache.setInstance(spawningInstance);
|
||||
PlayerSpawnEvent spawnEvent = new PlayerSpawnEvent();
|
||||
playerCache.callEvent(PlayerSpawnEvent.class, spawnEvent);
|
||||
playerCache.updateViewPosition(chunk);
|
||||
} : null;
|
||||
Consumer<Chunk> callback = (chunk) -> {
|
||||
boolean isLast = counter.get() == length - 1;
|
||||
if (isLast) {
|
||||
// This is the last chunk to be loaded, spawn player
|
||||
playerCache.spawned = true;
|
||||
playerCache.setInstance(spawningInstance);
|
||||
PlayerSpawnEvent spawnEvent = new PlayerSpawnEvent();
|
||||
playerCache.callEvent(PlayerSpawnEvent.class, spawnEvent);
|
||||
playerCache.updateViewPosition(chunk);
|
||||
} else {
|
||||
// Increment the counter of current loaded chunks
|
||||
counter.incrementAndGet();
|
||||
}
|
||||
};
|
||||
|
||||
// WARNING: if auto load is disabled and no chunks are loaded beforehand, player will be stuck.
|
||||
spawningInstance.loadChunk(chunkX, chunkZ, callback);
|
||||
|
@ -115,7 +115,7 @@ public class Player extends LivingEntity {
|
||||
sendMessage("You attacked an entity!");
|
||||
} else if (entity instanceof Player) {
|
||||
Player player = (Player) entity;
|
||||
Vector velocity = getPosition().clone().getDirection().multiply(6);
|
||||
Vector velocity = getPosition().clone().getDirection().multiply(4);
|
||||
velocity.setY(3.5f);
|
||||
player.setVelocity(velocity, 150);
|
||||
player.damage(2);
|
||||
@ -155,7 +155,7 @@ public class Player extends LivingEntity {
|
||||
|
||||
setEventCallback(PlayerSpawnEvent.class, event -> {
|
||||
System.out.println("SPAWN");
|
||||
setGameMode(GameMode.SURVIVAL);
|
||||
setGameMode(GameMode.CREATIVE);
|
||||
teleport(new Position(0, 66, 0));
|
||||
|
||||
/*ChickenCreature chickenCreature = new ChickenCreature();
|
||||
@ -330,6 +330,8 @@ public class Player extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public void addViewer(Player player) {
|
||||
if (player == this)
|
||||
return;
|
||||
super.addViewer(player);
|
||||
PlayerConnection connection = player.getPlayerConnection();
|
||||
String property = "eyJ0aW1lc3RhbXAiOjE1NjU0ODMwODQwOTYsInByb2ZpbGVJZCI6ImFiNzBlY2I0MjM0NjRjMTRhNTJkN2EwOTE1MDdjMjRlIiwicHJvZmlsZU5hbWUiOiJUaGVNb2RlOTExIiwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RkOTE2NzJiNTE0MmJhN2Y3MjA2ZTRjN2IwOTBkNzhlM2Y1ZDc2NDdiNWFmZDIyNjFhZDk4OGM0MWI2ZjcwYTEifX19";
|
||||
@ -355,6 +357,8 @@ public class Player extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public void removeViewer(Player player) {
|
||||
if (player == this)
|
||||
return;
|
||||
super.removeViewer(player);
|
||||
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER);
|
||||
playerInfoPacket.playerInfos.add(new PlayerInfoPacket.RemovePlayer(getUuid()));
|
||||
@ -523,7 +527,7 @@ public class Player extends LivingEntity {
|
||||
int[] chunkPos = ChunkUtils.getChunkCoord(updatedVisibleChunks[index]);
|
||||
instance.loadOptionalChunk(chunkPos[0], chunkPos[1], chunk -> {
|
||||
if (chunk == null) {
|
||||
return; // Cannot load chunk (auto load not enabled)
|
||||
return; // Cannot load chunk (auto load is not enabled)
|
||||
}
|
||||
instance.sendChunk(this, chunk);
|
||||
if (isFar && isLast) {
|
||||
@ -536,8 +540,6 @@ public class Player extends LivingEntity {
|
||||
@Override
|
||||
public void teleport(Position position, Runnable callback) {
|
||||
super.teleport(position, () -> {
|
||||
if (!instance.hasEnabledAutoChunkLoad() && ChunkUtils.isChunkUnloaded(instance, position.getX(), position.getZ()))
|
||||
return;
|
||||
updatePlayerPosition();
|
||||
if (callback != null)
|
||||
callback.run();
|
||||
|
@ -42,7 +42,6 @@ public class PlayerPositionListener {
|
||||
}
|
||||
|
||||
private static void processMovement(Player player, float x, float y, float z, Runnable runnable) {
|
||||
//System.out.println("MOVEMENT PACKET " + Math.round(x) + ":" + Math.round(y) + ":" + Math.round(z));
|
||||
boolean chunkTest = ChunkUtils.isChunkUnloaded(player.getInstance(), x, z);
|
||||
if (chunkTest) {
|
||||
player.teleport(player.getPosition());
|
||||
|
@ -3,9 +3,11 @@ package fr.themode.minestom.net;
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.adamaq01.ozao.net.packet.Packet;
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.PacketUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
@ -21,4 +23,21 @@ public class PacketWriterUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static void writeAndSend(Collection<Player> players, ServerPacket serverPacket) {
|
||||
batchesPool.execute(() -> {
|
||||
Packet p = PacketUtils.writePacket(serverPacket);
|
||||
Buffer encoded = PacketUtils.encode(p);
|
||||
|
||||
|
||||
int size = players.size();
|
||||
if (size == 0)
|
||||
return;
|
||||
encoded.getData().retain(size).markReaderIndex();
|
||||
for (Player player : players) {
|
||||
player.getPlayerConnection().writeUnencodedPacket(encoded);
|
||||
encoded.getData().resetReaderIndex();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ public class PacketUtils {
|
||||
public static Buffer encode(Packet packet) {
|
||||
Buffer buffer = Buffer.create();
|
||||
Buffer idAndPayload = Buffer.create();
|
||||
|
||||
writeVarInt(idAndPayload, packet.get(PACKET_ID_IDENTIFIER));
|
||||
idAndPayload.putBuffer(packet.getPayload());
|
||||
writeVarInt(buffer, idAndPayload.length());
|
||||
|
@ -5,7 +5,6 @@ import fr.themode.minestom.chat.Chat;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Utils {
|
||||
|
||||
@ -132,11 +131,6 @@ public class Utils {
|
||||
return SerializerUtils.longToBlockPosition(buffer.getLong());
|
||||
}
|
||||
|
||||
public static void writeUuid(Buffer buffer, UUID uuid) {
|
||||
buffer.putLong(uuid.getMostSignificantBits());
|
||||
buffer.putLong(uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public static void writeItemStack(Buffer buffer, ItemStack itemStack) {
|
||||
if (itemStack == null) {
|
||||
buffer.putBoolean(false);
|
||||
|
Loading…
Reference in New Issue
Block a user