Fixed teleportation & improved first chunk loading

This commit is contained in:
TheMode 2019-08-31 12:10:46 +02:00
parent 666f433ae7
commit f43bf11e66
8 changed files with 64 additions and 73 deletions

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);

View File

@ -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();

View File

@ -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());

View File

@ -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();
}
});
}
}

View File

@ -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());

View File

@ -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);