diff --git a/README.md b/README.md index a94914db..52dfb653 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Geyser is a bridge between Minecraft: Bedrock Edition and Minecraft: Java Editio ## What is Geyser? Geyser is a proxy, bridging the gap between Minecraft: Bedrock Edition and Minecraft: Java Edition servers. -The ultimate goal of this project is to allow Minecraft: Bedrock Edition users to join Minecraft: Java Edition servers as seamlessly as possible. +The ultimate goal of this project is to allow Minecraft: Bedrock Edition users to join Minecraft: Java Edition servers as seamlessly as possible. **Please note, this project is still a work in progress and should not be used on production. Expect bugs!** -### Please note, this project is still a work in progress and should not be used on production. Expect bugs! +### Currently supporting Minecraft Bedrock v1.14.X and Minecraft Java v1.15.2. ## Setting Up Please note, Geyser is **not** (currently) a plugin. Watch the video below or take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set it up. diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 7c72368f..6907f489 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -196,7 +196,7 @@ public class Entity { metadata.getFlags().setFlag(EntityFlag.GLIDING, (xd & 0x80) == 0x80); // metadata.getFlags().setFlag(EntityFlag.INVISIBLE, (xd & 0x20) == 0x20); if ((xd & 0x20) == 0x20) - metadata.put(EntityData.SCALE, 0.01f); + metadata.put(EntityData.SCALE, 0.0f); else metadata.put(EntityData.SCALE, scale); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java index 3279b298..6dd77d73 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java @@ -43,7 +43,7 @@ public class ArmorStandEntity extends LivingEntity { public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getType() == MetadataType.BYTE) { byte xd = (byte) entityMetadata.getValue(); - if((xd & 0x01) == 0x01) { + if((xd & 0x01) == 0x01 && !(metadata.get(EntityData.SCALE).equals(0.0f))) { metadata.put(EntityData.SCALE, .55f); } } 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 ca4a65ca..9984249c 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 @@ -37,8 +37,9 @@ import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; import com.github.steveice10.packetlib.event.session.SessionAdapter; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.tcp.TcpSessionFactory; +import com.nukkitx.math.GenericMath; +import com.nukkitx.math.TrigMath; import com.nukkitx.math.vector.Vector2f; -import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.tag.CompoundTag; @@ -64,6 +65,7 @@ import org.geysermc.connector.utils.Toolbox; import java.net.InetSocketAddress; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; @Getter public class GeyserSession implements Player { @@ -85,9 +87,6 @@ public class GeyserSession implements Player { private DataCache javaPacketCache; - @Setter - private Vector2i lastChunkPosition = null; - @Setter private int renderDistance; private boolean loggedIn; @@ -100,6 +99,7 @@ public class GeyserSession implements Player { @Setter private GameMode gameMode = GameMode.SURVIVAL; + private final AtomicInteger pendingDimSwitches = new AtomicInteger(0); @Setter private boolean sprinting; @@ -135,6 +135,10 @@ 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()); + } ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 0, false); @@ -273,6 +277,16 @@ public class GeyserSession implements Player { windowCache.showWindow(window, id); } + public void setRenderDistance(int renderDistance) { + renderDistance = GenericMath.ceil(++renderDistance * TrigMath.SQRT_OF_TWO); //square to circle + if (renderDistance > 32) renderDistance = 32; // <3 u ViaVersion but I don't like crashing clients x) + this.renderDistance = renderDistance; + + ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket(); + chunkRadiusUpdatedPacket.setRadius(renderDistance); + upstream.sendPacket(chunkRadiusUpdatedPacket); + } + @Override public InetSocketAddress getSocketAddress() { return this.upstream.getAddress(); 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 0afe5a6f..1268e327 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 @@ -142,6 +142,9 @@ public class TranslatorsInit { Registry.registerJava(ServerMultiBlockChangePacket.class, new JavaMultiBlockChangeTranslator()); Registry.registerJava(ServerUnloadChunkPacket.class, new JavaUnloadChunkTranslator()); + Registry.registerJava(ServerUpdateViewPositionPacket.class, new JavaUpdateViewPositionTranslator()); + Registry.registerJava(ServerUpdateViewDistancePacket.class, new JavaUpdateViewDistanceTranslator()); + Registry.registerJava(ServerOpenWindowPacket.class, new OpenWindowPacketTranslator()); Registry.registerBedrock(AnimatePacket.class, new BedrockAnimateTranslator()); 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 981e569b..98a580ee 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 @@ -58,6 +58,14 @@ public class BedrockActionTranslator extends PacketTranslator 0) return; if (!session.getUpstream().isInitialized()) { MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInitializedTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInitializedTranslator.java index e30ef2d7..201049db 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInitializedTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInitializedTranslator.java @@ -38,11 +38,6 @@ public class BedrockPlayerInitializedTranslator extends PacketTranslator { @@ -60,15 +61,11 @@ public class JavaJoinGameTranslator extends PacketTranslator 32) session.setRenderDistance(32); // <3 u ViaVersion but I don't like crashing clients x) - - ChunkRadiusUpdatedPacket chunkRadiusPacket = new ChunkRadiusUpdatedPacket(); - chunkRadiusPacket.setRadius(session.getRenderDistance()); - session.getUpstream().sendPacket(chunkRadiusPacket); + session.setRenderDistance(packet.getViewDistance()); if (DimensionUtils.javaToBedrock(packet.getDimension()) != entity.getDimension()) { - DimensionUtils.switchDimension(session, packet.getDimension(), false); + ChunkUtils.sendEmptyChunks(session, entity.getPosition().toInt(), 3, true); + DimensionUtils.switchDimension(session, packet.getDimension()); } } } 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 8a6432e5..285f9d85 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 @@ -51,14 +51,15 @@ public class JavaRespawnTranslator 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 { - // Handled in JavaPlayerPositionRotationTranslator - session.setSpawned(false); if (session.isManyDimPackets()) { //reloading world int fakeDim = entity.getDimension() == 0 ? -1 : 0; - DimensionUtils.switchDimension(session, fakeDim, true); - DimensionUtils.switchDimension(session, packet.getDimension(), false); + DimensionUtils.switchDimension(session, fakeDim); + DimensionUtils.switchDimension(session, packet.getDimension()); + } else { + // 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 b7bc2ae7..5db813eb 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 @@ -54,7 +54,7 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator { - Vector2i chunkPos = session.getLastChunkPosition(); - Vector3f position = session.getPlayerEntity().getPosition(); - Vector2i newChunkPos = Vector2i.from(position.getFloorX() >> 4, position.getFloorZ() >> 4); - - if (chunkPos == null || !chunkPos.equals(newChunkPos)) { - NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); - chunkPublisherUpdatePacket.setPosition(position.toInt()); - chunkPublisherUpdatePacket.setRadius(session.getRenderDistance() << 4); - session.getUpstream().sendPacket(chunkPublisherUpdatePacket); - - session.setLastChunkPosition(newChunkPos); - } - try { - ChunkUtils.ChunkData chunkData = ChunkUtils.translateToBedrock(packet.getColumn()); - ByteBuf byteBuf = Unpooled.buffer(32); - ChunkSection[] sections = chunkData.sections; + if (packet.getColumn().getBiomeData() != null) { //Full chunk + ChunkUtils.ChunkData chunkData = ChunkUtils.translateToBedrock(packet.getColumn()); + ByteBuf byteBuf = Unpooled.buffer(32); + ChunkSection[] sections = chunkData.sections; - int sectionCount = sections.length - 1; - while (sectionCount >= 0 && sections[sectionCount].isEmpty()) { - sectionCount--; + int sectionCount = sections.length - 1; + while (sectionCount >= 0 && sections[sectionCount].isEmpty()) { + sectionCount--; + } + sectionCount++; + + for (int i = 0; i < sectionCount; i++) { + ChunkSection section = chunkData.sections[i]; + section.writeToNetwork(byteBuf); + } + + byte[] bedrockBiome = BiomeTranslator.toBedrockBiome(packet.getColumn().getBiomeData()); + + byteBuf.writeBytes(bedrockBiome); // Biomes - 256 bytes + byteBuf.writeByte(0); // Border blocks - Edu edition only + VarInts.writeUnsignedInt(byteBuf, 0); // extra data length, 0 for now + + byte[] payload = new byte[byteBuf.writerIndex()]; + byteBuf.readBytes(payload); + + LevelChunkPacket levelChunkPacket = new LevelChunkPacket(); + levelChunkPacket.setSubChunksLength(sectionCount); + levelChunkPacket.setCachingEnabled(false); + levelChunkPacket.setChunkX(packet.getColumn().getX()); + levelChunkPacket.setChunkZ(packet.getColumn().getZ()); + levelChunkPacket.setData(payload); + session.getUpstream().sendPacket(levelChunkPacket); + } else { + final int xOffset = packet.getColumn().getX() << 4; + final int zOffset = packet.getColumn().getZ() << 4; + Chunk[] chunks = packet.getColumn().getChunks(); + for (int i = 0; i < chunks.length; i++) { + Chunk chunk = chunks[i]; + if (chunk == null) continue; + final int yOffset = i * 16; + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + BlockState blockState = chunk.get(x, y, z); + Vector3i pos = Vector3i.from( + x + xOffset, + y + yOffset, + z + zOffset); + ChunkUtils.updateBlock(session, blockState, pos); + } + } + } + } } - sectionCount++; - - for (int i = 0; i < sectionCount; i++) { - ChunkSection section = chunkData.sections[i]; - section.writeToNetwork(byteBuf); - } - - byte[] bedrockBiome = BiomeTranslator.toBedrockBiome(packet.getColumn().getBiomeData()); - - byteBuf.writeBytes(bedrockBiome); // Biomes - 256 bytes - byteBuf.writeByte(0); // Border blocks - Edu edition only - VarInts.writeUnsignedInt(byteBuf, 0); // extra data length, 0 for now - - byte[] payload = new byte[byteBuf.writerIndex()]; - byteBuf.readBytes(payload); - - LevelChunkPacket levelChunkPacket = new LevelChunkPacket(); - levelChunkPacket.setSubChunksLength(sectionCount); - levelChunkPacket.setCachingEnabled(false); - levelChunkPacket.setChunkX(packet.getColumn().getX()); - levelChunkPacket.setChunkZ(packet.getColumn().getZ()); - levelChunkPacket.setData(payload); - session.getUpstream().sendPacket(levelChunkPacket); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateViewDistanceTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateViewDistanceTranslator.java new file mode 100644 index 00000000..1b339b1c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateViewDistanceTranslator.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.world; + +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateViewDistancePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaUpdateViewDistanceTranslator extends PacketTranslator { + + @Override + public void translate(ServerUpdateViewDistancePacket packet, GeyserSession session) { + session.setRenderDistance(packet.getViewDistance()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateViewPositionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateViewPositionTranslator.java new file mode 100644 index 00000000..ebe9062f --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateViewPositionTranslator.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.world; + +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateViewPositionPacket; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaUpdateViewPositionTranslator extends PacketTranslator { + + @Override + public void translate(ServerUpdateViewPositionPacket packet, GeyserSession session) { + NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); + chunkPublisherUpdatePacket.setPosition(Vector3i.from(packet.getChunkX() << 4, 0, packet.getChunkZ() << 4)); + chunkPublisherUpdatePacket.setRadius(session.getRenderDistance() << 4); + session.getUpstream().sendPacket(chunkPublisherUpdatePacket); + } +} 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 6c55c5ea..1a6296c0 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -31,7 +31,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; -import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; @@ -76,19 +75,23 @@ public class ChunkUtils { } public static void updateBlock(GeyserSession session, BlockState blockState, Position position) { - int blockId = BlockTranslator.getBedrockBlockId(blockState); Vector3i pos = Vector3i.from(position.getX(), position.getY(), position.getZ()); + updateBlock(session, blockState, pos); + } + + public static void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + int blockId = BlockTranslator.getBedrockBlockId(blockState); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(pos); + updateBlockPacket.setBlockPosition(position); updateBlockPacket.setRuntimeId(blockId); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); session.getUpstream().sendPacket(updateBlockPacket); UpdateBlockPacket waterPacket = new UpdateBlockPacket(); waterPacket.setDataLayer(1); - waterPacket.setBlockPosition(pos); + waterPacket.setBlockPosition(position); if (BlockTranslator.isWaterlogged(blockState)) { waterPacket.setRuntimeId(BEDROCK_WATER_ID); } else { @@ -100,11 +103,6 @@ public class ChunkUtils { 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 + 1 << 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(); @@ -119,7 +117,7 @@ public class ChunkUtils { Vector3i pos = Vector3i.from(chunkX + x << 4, 80, chunkZ + z << 4); UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setBlockPosition(pos); - blockPacket.setDataLayer(1); + blockPacket.setDataLayer(0); blockPacket.setRuntimeId(1); session.getUpstream().sendPacket(blockPacket); } 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 81f52823..c7ecaafb 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -31,14 +31,18 @@ import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; 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); session.getEntityCache().removeAllEntities(); + if (session.getPendingDimSwitches().getAndIncrement() > 0) { + ChunkUtils.sendEmptyChunks(session, player.getPosition().toInt(), 3, true); + } + + Vector3i pos = Vector3i.from(0, Short.MAX_VALUE, 0); ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); changeDimensionPacket.setDimension(bedrockDimension); @@ -46,19 +50,14 @@ public class DimensionUtils { changeDimensionPacket.setPosition(pos.toFloat()); session.getUpstream().sendPacket(changeDimensionPacket); player.setDimension(bedrockDimension); + player.setPosition(pos.toFloat()); + session.setSpawned(false); //let java server handle portal travel sound StopSoundPacket stopSoundPacket = new StopSoundPacket(); stopSoundPacket.setStoppingAllSound(true); stopSoundPacket.setSoundName(""); session.getUpstream().sendPacket(stopSoundPacket); - - if (fake) { - ChunkUtils.sendEmptyChunks(session, pos, 2, true); - } - - session.setSpawned(false); - session.setSwitchingDimension(true); } public static int javaToBedrock(int javaDimension) { diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java index 840e2f5d..cafb7ab0 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java +++ b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java @@ -27,12 +27,14 @@ package org.geysermc.connector.world.chunk; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @Getter @Setter @AllArgsConstructor +@EqualsAndHashCode public class ChunkPosition { private int x; @@ -43,16 +45,9 @@ public class ChunkPosition { } public Position getChunkBlock(int x, int y, int z) { - int chunkX = x % 16; - int chunkY = y % 16; - int chunkZ = z % 16; - - if (chunkX < 0) - chunkX = -chunkX; - if (chunkY < 0) - chunkY = -chunkY; - if (chunkZ < 0) - chunkZ = -chunkZ; + int chunkX = x & 15; + int chunkY = y & 15; + int chunkZ = z & 15; return new Position(chunkX, chunkY, chunkZ); }