From cc0b3293bf887c810a515b46b97f0d3fcdb8e105 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Fri, 27 Dec 2019 02:29:46 -0900 Subject: [PATCH 1/8] Start fixing dimension switching and respawning --- .../network/session/GeyserSession.java | 19 ++++ .../network/translators/TranslatorsInit.java | 1 + .../bedrock/BedrockActionTranslator.java | 10 +- .../bedrock/BedrockMovePlayerTranslator.java | 2 +- .../BedrockPlayerInitializedTranslator.java | 4 + .../bedrock/BedrockRespawnTranslator.java | 43 ++++++++ .../java/JavaJoinGameTranslator.java | 26 ++--- .../java/JavaRespawnTranslator.java | 36 ++----- .../player/JavaPlayerHealthTranslator.java | 14 +-- .../JavaPlayerPositionRotationTranslator.java | 26 ++++- .../connector/utils/DimensionUtils.java | 102 ++++++++++++++++++ 11 files changed, 224 insertions(+), 59 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 52ee38231..b12434c97 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.protocol.MinecraftProtocol; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.event.session.ConnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectedEvent; @@ -57,6 +58,7 @@ import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.cache.*; import org.geysermc.connector.network.translators.Registry; import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.Toolbox; import java.net.InetSocketAddress; @@ -97,6 +99,11 @@ public class GeyserSession implements Player { @Setter private GameMode gameMode = GameMode.SURVIVAL; + @Setter + private volatile boolean switchingDim = false; + private final Object dimensionLock = new Object(); + private ServerRespawnPacket lastDimPacket = null; + public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { this.connector = connector; this.upstream = new UpstreamSession(bedrockServerSession); @@ -198,6 +205,18 @@ public class GeyserSession implements Player { @Override public void packetReceived(PacketReceivedEvent event) { if (!closed) { + //handle consecutive respawn packets + if (event.getPacket().getClass().equals(ServerRespawnPacket.class)) { + if (lastDimPacket != null) { + DimensionUtils.switchDimension(GeyserSession.this, lastDimPacket.getDimension(), true); + } + lastDimPacket = event.getPacket(); + return; + } else if (lastDimPacket != null) { + Registry.JAVA.translate(lastDimPacket.getClass(), lastDimPacket, GeyserSession.this); + lastDimPacket = null; + } + Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), GeyserSession.this); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index a19de3f29..aa7692830 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -156,6 +156,7 @@ public class TranslatorsInit { Registry.registerBedrock(SetLocalPlayerAsInitializedPacket.class, new BedrockPlayerInitializedTranslator()); Registry.registerBedrock(InteractPacket.class, new BedrockInteractTranslator()); Registry.registerBedrock(TextPacket.class, new BedrockTextTranslator()); + Registry.registerBedrock(RespawnPacket.class, new BedrockRespawnTranslator()); itemTranslator = new ItemTranslator(); blockTranslator = new BlockTranslator(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 334679346..8f99b5ccb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -34,7 +34,9 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket; +import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -53,7 +55,7 @@ public class BedrockActionTranslator extends PacketTranslator { + + @Override + public void translate(RespawnPacket packet, GeyserSession session) { + if (packet.getSpawnState() == RespawnPacket.State.CLIENT_READY) { + ClientRequestPacket javaRespawnPacket = new ClientRequestPacket(ClientRequest.RESPAWN); + session.getDownstream().getSession().send(javaRespawnPacket); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java index 87bb62e03..6e4228f26 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java @@ -26,22 +26,29 @@ package org.geysermc.connector.network.translators.java; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket; -import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; -import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket; -import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; -import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket; +import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; -import org.geysermc.connector.world.chunk.ChunkPosition; +import org.geysermc.connector.utils.DimensionUtils; public class JavaJoinGameTranslator extends PacketTranslator { @Override public void translate(ServerJoinGamePacket packet, GeyserSession session) { + PlayerEntity entity = session.getPlayerEntity(); + entity.setEntityId(packet.getEntityId()); + + if (DimensionUtils.javaToBedrock(packet.getDimension()) != entity.getDimension()) { + if (!session.getUpstream().isInitialized()) { + session.setSwitchingDim(true); + DimensionUtils.sendEmptyChunks(session, entity.getPosition().toInt()); + DimensionUtils.waitForAck(session); + } + DimensionUtils.switchDimension(session, packet.getDimension(), false); + } + AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket(); bedrockPacket.setUniqueEntityId(session.getPlayerEntity().getGeyserId()); bedrockPacket.setPlayerPermission(1); @@ -51,9 +58,6 @@ public class JavaJoinGameTranslator extends PacketTranslator { @@ -41,37 +40,16 @@ public class JavaRespawnTranslator extends PacketTranslator if (entity == null) return; - if (entity.getDimension() == getDimension(packet.getDimension())) - return; - - entity.setDimension(getDimension(packet.getDimension())); - - ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); - changeDimensionPacket.setDimension(getDimension(packet.getDimension())); - changeDimensionPacket.setRespawn(false); - changeDimensionPacket.setPosition(entity.getPosition()); - session.getUpstream().sendPacket(changeDimensionPacket); - SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); playerGameTypePacket.setGamemode(packet.getGamemode().ordinal()); session.getUpstream().sendPacket(playerGameTypePacket); session.setGameMode(packet.getGamemode()); - /* - PlayStatusPacket playStatusPacket = new PlayStatusPacket(); - playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); - session.getUpstream().sendPacket(playStatusPacket); - */ - } - - private int getDimension(int javaDimension) { - switch (javaDimension) { - case -1: - return 1; - case 1: - return 2; + if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { + DimensionUtils.switchDimension(session, packet.getDimension(), false); + } else { + // Handled in JavaPlayerPositionRotationTranslator + session.setSpawned(false); } - - return javaDimension; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java index 73376385a..077ca9e82 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java @@ -25,11 +25,7 @@ package org.geysermc.connector.network.translators.java.entity.player; -import com.github.steveice10.mc.protocol.data.game.ClientRequest; -import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerHealthPacket; -import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.packet.RespawnPacket; import com.nukkitx.protocol.bedrock.packet.SetHealthPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.attribute.AttributeType; @@ -60,14 +56,8 @@ public class JavaPlayerHealthTranslator extends PacketTranslator> 4; + int chunkZ = position.getZ() >> 4; + NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); + chunkPublisherUpdatePacket.setPosition(position); + chunkPublisherUpdatePacket.setRadius(session.getRenderDistance() << 4); + session.getUpstream().sendPacket(chunkPublisherUpdatePacket); + session.setLastChunkPosition(null); + for (int x = -5; x < 5; x++) { + for (int z = -5; z < 5; z++) { + LevelChunkPacket data = new LevelChunkPacket(); + data.setChunkX(chunkX + x); + data.setChunkZ(chunkZ + z); + data.setSubChunksLength(0); + data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); + data.setCachingEnabled(false); + session.getUpstream().sendPacket(data); + } + } + } + + public static int javaToBedrock(int javaDimension) { + switch (javaDimension) { + case -1: + return 1; + case 1: + return 2; + default: + return javaDimension; + } + } +} From 8efeb3fe25915ec4d65f1f5b858716dfe01ce5e9 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Fri, 27 Dec 2019 03:03:12 -0900 Subject: [PATCH 2/8] Fix exception when removing all entities --- .../network/session/cache/EntityCache.java | 11 ++++------- .../geysermc/connector/utils/DimensionUtils.java | 13 ++++++------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java index fd0bd7c5a..a248327ae 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java @@ -25,10 +25,7 @@ package org.geysermc.connector.network.session.cache; -import it.unimi.dsi.fastutil.longs.Long2LongMap; -import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.*; import lombok.Getter; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.PlayerEntity; @@ -45,9 +42,9 @@ public class EntityCache { private GeyserSession session; @Getter - private Long2ObjectMap entities = new Long2ObjectOpenHashMap<>(); - private Long2LongMap entityIdTranslations = new Long2LongOpenHashMap(); - private Map playerEntities = new HashMap<>(); + private Long2ObjectMap entities = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>()); + private Long2LongMap entityIdTranslations = Long2LongMaps.synchronize(new Long2LongOpenHashMap()); + private Map playerEntities = Collections.synchronizedMap(new HashMap<>()); private Map bossbars = new HashMap<>(); @Getter diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java index 2f559da36..970532718 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -6,6 +6,9 @@ import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; +import java.util.ArrayList; +import java.util.List; + public class DimensionUtils { public static void switchDimension(GeyserSession session, int javaDimension, boolean fake) { int bedrockDimension = javaToBedrock(javaDimension); @@ -15,13 +18,9 @@ public class DimensionUtils { Vector3i pos = Vector3i.from(0, 32767, 0); - //FIXME: chance of exception while iterating - try { - for (Entity entity : session.getEntityCache().getEntities().values()) { - session.getEntityCache().removeEntity(entity, false); - } - } catch (Exception e) { - e.printStackTrace(); + List entities = new ArrayList<>(session.getEntityCache().getEntities().values()); + for (Entity entity : entities) { + session.getEntityCache().removeEntity(entity, false); } ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); From b2f86ec20b285fd48a29b2215970cc8b905c5c04 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 28 Dec 2019 04:35:21 -0900 Subject: [PATCH 3/8] Rewrite dimension code New code does not rely on pausing the thread --- .../network/session/GeyserSession.java | 30 ++-------- .../network/session/cache/EntityCache.java | 7 +++ .../bedrock/BedrockActionTranslator.java | 7 +-- .../bedrock/BedrockMovePlayerTranslator.java | 2 +- .../BedrockPlayerInitializedTranslator.java | 9 +-- .../java/JavaJoinGameTranslator.java | 13 ++--- .../java/JavaRespawnTranslator.java | 6 +- .../JavaPlayerPositionRotationTranslator.java | 2 +- .../geysermc/connector/utils/ChunkUtils.java | 24 +++++++- .../connector/utils/DimensionUtils.java | 58 ++----------------- 10 files changed, 56 insertions(+), 102 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index b12434c97..b49f0bf78 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -57,8 +57,7 @@ import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.cache.*; import org.geysermc.connector.network.translators.Registry; -import org.geysermc.connector.network.translators.TranslatorsInit; -import org.geysermc.connector.utils.DimensionUtils; +import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.Toolbox; import java.net.InetSocketAddress; @@ -100,8 +99,8 @@ public class GeyserSession implements Player { private GameMode gameMode = GameMode.SURVIVAL; @Setter - private volatile boolean switchingDim = false; - private final Object dimensionLock = new Object(); + private boolean switchingDimension = false; + private boolean manyDimPackets = false; private ServerRespawnPacket lastDimPacket = null; public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { @@ -128,25 +127,8 @@ public class GeyserSession implements Player { public void connect(RemoteServer remoteServer) { startGame(); this.remoteServer = remoteServer; - if (!(connector.getConfig().getRemote().getAuthType().hashCode() == "online".hashCode())) { - connector.getLogger().info("Attempting to login using offline mode... authentication is disabled."); - authenticate(authenticationData.getName()); - } - Vector3f pos = Vector3f.ZERO; - int chunkX = pos.getFloorX() >> 4; - int chunkZ = pos.getFloorZ() >> 4; - NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); - chunkPublisherUpdatePacket.setPosition(pos.toInt()); - chunkPublisherUpdatePacket.setRadius(renderDistance << 4); - upstream.sendPacket(chunkPublisherUpdatePacket); - - LevelChunkPacket data = new LevelChunkPacket(); - data.setChunkX(chunkX); - data.setChunkZ(chunkZ); - data.setSubChunksLength(0); - data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); - upstream.sendPacket(data); + ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 5); BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); biomePacket.setTag(CompoundTag.EMPTY); @@ -207,9 +189,7 @@ public class GeyserSession implements Player { if (!closed) { //handle consecutive respawn packets if (event.getPacket().getClass().equals(ServerRespawnPacket.class)) { - if (lastDimPacket != null) { - DimensionUtils.switchDimension(GeyserSession.this, lastDimPacket.getDimension(), true); - } + manyDimPackets = lastDimPacket != null; lastDimPacket = event.getPacket(); return; } else if (lastDimPacket != null) { diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java index a248327ae..5e9ae0f06 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java @@ -73,6 +73,13 @@ public class EntityCache { return false; } + public void removeAllEntities() { + List entities = new ArrayList<>(session.getEntityCache().getEntities().values()); + for (Entity entity : entities) { + session.getEntityCache().removeEntity(entity, false); + } + } + public Entity getEntityByGeyserId(long geyserId) { return entities.get(geyserId); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 8f99b5ccb..51c476f97 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -34,9 +34,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket; -import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -108,10 +106,7 @@ public class BedrockActionTranslator extends PacketTranslator session.setGameMode(packet.getGamemode()); if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { - DimensionUtils.switchDimension(session, packet.getDimension(), false); + DimensionUtils.switchDimension(session, packet.getDimension()); } else { + if (session.isManyDimPackets()) { //reloading world + session.getEntityCache().removeAllEntities(); + //TODO: fix lighting bug + } // Handled in JavaPlayerPositionRotationTranslator session.setSpawned(false); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java index 83b2e1662..d703c8cbd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java @@ -52,7 +52,7 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator> 4; + int chunkZ = position.getZ() >> 4; + NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); + chunkPublisherUpdatePacket.setPosition(position); + chunkPublisherUpdatePacket.setRadius(radius << 4); + session.getUpstream().sendPacket(chunkPublisherUpdatePacket); + session.setLastChunkPosition(null); + for (int x = -radius; x < radius; x++) { + for (int z = -radius; z < radius; z++) { + LevelChunkPacket data = new LevelChunkPacket(); + data.setChunkX(chunkX + x); + data.setChunkZ(chunkZ + z); + data.setSubChunksLength(0); + data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); + data.setCachingEnabled(false); + session.getUpstream().sendPacket(data); + } + } + } + public static final class ChunkData { public ChunkSection[] sections; diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java index 970532718..19696105b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -4,24 +4,16 @@ import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; - -import java.util.ArrayList; -import java.util.List; public class DimensionUtils { - public static void switchDimension(GeyserSession session, int javaDimension, boolean fake) { + public static void switchDimension(GeyserSession session, int javaDimension) { int bedrockDimension = javaToBedrock(javaDimension); Entity player = session.getPlayerEntity(); if (bedrockDimension == player.getDimension()) return; + Vector3i pos = Vector3i.from(0, Short.MAX_VALUE, 0); - Vector3i pos = Vector3i.from(0, 32767, 0); - - List entities = new ArrayList<>(session.getEntityCache().getEntities().values()); - for (Entity entity : entities) { - session.getEntityCache().removeEntity(entity, false); - } + session.getEntityCache().removeAllEntities(); ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); changeDimensionPacket.setDimension(bedrockDimension); @@ -43,49 +35,7 @@ public class DimensionUtils { session.getUpstream().sendPacket(eventPacket); session.setSpawned(false); - session.setSwitchingDim(true); - - if (fake) { - try { - Thread.sleep(250); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - sendEmptyChunks(session, pos.toInt()); - waitForAck(session); - } - } - - public static void waitForAck(GeyserSession session) { - synchronized (session.getDimensionLock()) { - try { - while (session.isSwitchingDim()) - session.getDimensionLock().wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - - public static void sendEmptyChunks(GeyserSession session, Vector3i position) { - int chunkX = position.getX() >> 4; - int chunkZ = position.getZ() >> 4; - NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); - chunkPublisherUpdatePacket.setPosition(position); - chunkPublisherUpdatePacket.setRadius(session.getRenderDistance() << 4); - session.getUpstream().sendPacket(chunkPublisherUpdatePacket); - session.setLastChunkPosition(null); - for (int x = -5; x < 5; x++) { - for (int z = -5; z < 5; z++) { - LevelChunkPacket data = new LevelChunkPacket(); - data.setChunkX(chunkX + x); - data.setChunkZ(chunkZ + z); - data.setSubChunksLength(0); - data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); - data.setCachingEnabled(false); - session.getUpstream().sendPacket(data); - } - } + session.setSwitchingDimension(true); } public static int javaToBedrock(int javaDimension) { From 782feed64149a292ad299c2cee3f6a3973e3fe8c Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 28 Dec 2019 18:17:00 -0900 Subject: [PATCH 4/8] Fix lighting when reloading world --- .../network/session/GeyserSession.java | 2 +- .../java/JavaRespawnTranslator.java | 20 +++++++++++++++---- .../geysermc/connector/utils/ChunkUtils.java | 17 ++++++++++++---- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index b49f0bf78..db13eff95 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -128,7 +128,7 @@ public class GeyserSession implements Player { startGame(); this.remoteServer = remoteServer; - ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 5); + ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 0, false); BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); biomePacket.setTag(CompoundTag.EMPTY); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaRespawnTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaRespawnTranslator.java index b3d850ad5..07ae551d4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaRespawnTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaRespawnTranslator.java @@ -26,10 +26,12 @@ package org.geysermc.connector.network.translators.java; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket; +import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.DimensionUtils; public class JavaRespawnTranslator extends PacketTranslator { @@ -48,12 +50,22 @@ public class JavaRespawnTranslator extends PacketTranslator if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { DimensionUtils.switchDimension(session, packet.getDimension()); } else { - if (session.isManyDimPackets()) { //reloading world - session.getEntityCache().removeAllEntities(); - //TODO: fix lighting bug - } // Handled in JavaPlayerPositionRotationTranslator session.setSpawned(false); + if (session.isManyDimPackets()) { //reloading world + session.getEntityCache().removeAllEntities(); + //lighting fix + ChunkUtils.sendEmptyChunks(session, entity.getPosition().toInt(), session.getRenderDistance(), false); + Vector3f tempPos = Vector3f.from(entity.getPosition().getX() > 0 ? -5000 : 5000, 0, 0); + MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); + movePlayerPacket.setRuntimeEntityId(entity.getGeyserId()); + movePlayerPacket.setPosition(tempPos); + movePlayerPacket.setRotation(Vector3f.ZERO); + movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL); + movePlayerPacket.setOnGround(true); + session.getUpstream().sendPacket(movePlayerPacket); + ChunkUtils.sendEmptyChunks(session, tempPos.toInt(), 5, true); + } } } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index a140cb588..93681a7d2 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -73,16 +73,16 @@ public class ChunkUtils { session.getUpstream().sendPacket(waterPacket); } - public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius) { + public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius, boolean forceUpdate) { int chunkX = position.getX() >> 4; int chunkZ = position.getZ() >> 4; NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); chunkPublisherUpdatePacket.setPosition(position); - chunkPublisherUpdatePacket.setRadius(radius << 4); + chunkPublisherUpdatePacket.setRadius(radius + 1 << 4); session.getUpstream().sendPacket(chunkPublisherUpdatePacket); session.setLastChunkPosition(null); - for (int x = -radius; x < radius; x++) { - for (int z = -radius; z < radius; z++) { + for (int x = -radius; x <= radius; x++) { + for (int z = -radius; z <= radius; z++) { LevelChunkPacket data = new LevelChunkPacket(); data.setChunkX(chunkX + x); data.setChunkZ(chunkZ + z); @@ -90,6 +90,15 @@ public class ChunkUtils { data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); data.setCachingEnabled(false); session.getUpstream().sendPacket(data); + + if (forceUpdate) { + Vector3i pos = Vector3i.from(chunkX + x << 4, 80, chunkZ + z << 4); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setBlockPosition(pos); + blockPacket.setDataLayer(1); + blockPacket.setRuntimeId(1); + session.getUpstream().sendPacket(blockPacket); + } } } } From 66352415261be89a87f06d43a9cbb4f06b724d68 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 28 Dec 2019 21:15:12 -0900 Subject: [PATCH 5/8] Fix rare slow dimension switching --- .../translators/bedrock/BedrockActionTranslator.java | 6 ++++++ .../network/translators/java/JavaRespawnTranslator.java | 4 ++++ .../java/entity/player/JavaPlayerHealthTranslator.java | 5 ----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 51c476f97..595ca8626 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -34,6 +34,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket; import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; @@ -107,6 +108,11 @@ public class BedrockActionTranslator extends PacketTranslator if (entity == null) return; + float maxHealth = entity.getAttributes().containsKey(AttributeType.MAX_HEALTH) ? entity.getAttributes().get(AttributeType.MAX_HEALTH).getValue() : 20f; + entity.getAttributes().put(AttributeType.HEALTH, AttributeType.HEALTH.getAttribute(maxHealth)); + SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); playerGameTypePacket.setGamemode(packet.getGamemode().ordinal()); session.getUpstream().sendPacket(playerGameTypePacket); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java index 077ca9e82..7a1eb0e10 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java @@ -54,10 +54,5 @@ public class JavaPlayerHealthTranslator extends PacketTranslator Date: Sat, 28 Dec 2019 21:45:41 -0900 Subject: [PATCH 6/8] Small changes --- .../translators/bedrock/BedrockRespawnTranslator.java | 7 +++++++ .../player/JavaPlayerPositionRotationTranslator.java | 6 ------ .../java/org/geysermc/connector/utils/DimensionUtils.java | 6 ------ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java index 1a19fca15..40e97f3a3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java @@ -27,6 +27,7 @@ package org.geysermc.connector.network.translators.bedrock; import com.github.steveice10.mc.protocol.data.game.ClientRequest; import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket; +import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.packet.RespawnPacket; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -36,6 +37,12 @@ public class BedrockRespawnTranslator extends PacketTranslator { @Override public void translate(RespawnPacket packet, GeyserSession session) { if (packet.getSpawnState() == RespawnPacket.State.CLIENT_READY) { + RespawnPacket respawnPacket = new RespawnPacket(); + respawnPacket.setRuntimeEntityId(0); + respawnPacket.setPosition(Vector3f.ZERO); + respawnPacket.setSpawnState(RespawnPacket.State.SERVER_SEARCHING); + session.getUpstream().sendPacket(respawnPacket); + ClientRequestPacket javaRespawnPacket = new ClientRequestPacket(ClientRequest.RESPAWN); session.getDownstream().getSession().send(javaRespawnPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java index d703c8cbd..516d14618 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java @@ -52,12 +52,6 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator Date: Sat, 28 Dec 2019 23:20:48 -0900 Subject: [PATCH 7/8] Change lighting fix method --- .../java/JavaJoinGameTranslator.java | 2 +- .../java/JavaRespawnTranslator.java | 22 +++++-------------- .../connector/utils/DimensionUtils.java | 6 ++++- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java index 4167fb348..3cdc149d0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java @@ -67,7 +67,7 @@ public class JavaJoinGameTranslator extends PacketTranslator { @@ -44,7 +42,8 @@ public class JavaRespawnTranslator extends PacketTranslator return; float maxHealth = entity.getAttributes().containsKey(AttributeType.MAX_HEALTH) ? entity.getAttributes().get(AttributeType.MAX_HEALTH).getValue() : 20f; - entity.getAttributes().put(AttributeType.HEALTH, AttributeType.HEALTH.getAttribute(maxHealth)); + // Max health must be divisible by two in bedrock + entity.getAttributes().put(AttributeType.HEALTH, AttributeType.HEALTH.getAttribute(maxHealth, (maxHealth % 2 == 1 ? maxHealth + 1 : maxHealth))); SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); playerGameTypePacket.setGamemode(packet.getGamemode().ordinal()); @@ -52,23 +51,14 @@ public class JavaRespawnTranslator extends PacketTranslator session.setGameMode(packet.getGamemode()); if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { - DimensionUtils.switchDimension(session, packet.getDimension()); + DimensionUtils.switchDimension(session, packet.getDimension(), false); } else { // Handled in JavaPlayerPositionRotationTranslator session.setSpawned(false); if (session.isManyDimPackets()) { //reloading world - session.getEntityCache().removeAllEntities(); - //lighting fix - ChunkUtils.sendEmptyChunks(session, entity.getPosition().toInt(), session.getRenderDistance(), false); - Vector3f tempPos = Vector3f.from(entity.getPosition().getX() > 0 ? -5000 : 5000, 0, 0); - MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); - movePlayerPacket.setRuntimeEntityId(entity.getGeyserId()); - movePlayerPacket.setPosition(tempPos); - movePlayerPacket.setRotation(Vector3f.ZERO); - movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL); - movePlayerPacket.setOnGround(true); - session.getUpstream().sendPacket(movePlayerPacket); - ChunkUtils.sendEmptyChunks(session, tempPos.toInt(), 5, true); + int fakeDim = entity.getDimension() == 0 ? -1 : 0; + DimensionUtils.switchDimension(session, fakeDim, true); + DimensionUtils.switchDimension(session, packet.getDimension(), false); } } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java index f0a0ed584..ace1c6829 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -6,7 +6,7 @@ import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; public class DimensionUtils { - public static void switchDimension(GeyserSession session, int javaDimension) { + public static void switchDimension(GeyserSession session, int javaDimension, boolean fake) { int bedrockDimension = javaToBedrock(javaDimension); Entity player = session.getPlayerEntity(); if (bedrockDimension == player.getDimension()) @@ -28,6 +28,10 @@ public class DimensionUtils { stopSoundPacket.setSoundName(""); session.getUpstream().sendPacket(stopSoundPacket); + if (fake) { + ChunkUtils.sendEmptyChunks(session, pos, 2, true); + } + session.setSpawned(false); session.setSwitchingDimension(true); } From 377a87f7e31b321f0d75d3b7967e66b57d1e8974 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 29 Dec 2019 01:45:57 -0900 Subject: [PATCH 8/8] Fix health edge case If the java server sent a health value between 0 and 1, the player would die in the bedrock client --- .../java/entity/player/JavaPlayerHealthTranslator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java index 7a1eb0e10..bebd8f9d7 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java @@ -40,8 +40,9 @@ public class JavaPlayerHealthTranslator extends PacketTranslator