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 8f71e6fa8..444edcab4 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 @@ -40,6 +40,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerAbilitiesPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; @@ -381,18 +382,6 @@ public class GeyserSession implements CommandSender { */ private boolean flying = false; - /** - * If the current player is in noclip - */ - @Setter - private boolean noClip = false; - - /** - * If the current player can not interact with the world - */ - @Setter - private boolean worldImmutable = false; - /** * Caches current rain status. */ @@ -1282,15 +1271,21 @@ public class GeyserSession implements CommandSender { adventureSettingsPacket.setPlayerPermission(opPermissionLevel >= 2 ? PlayerPermission.OPERATOR : PlayerPermission.MEMBER); // Update the noClip and worldImmutable values based on the current gamemode - noClip = gameMode == GameMode.SPECTATOR; - worldImmutable = gameMode == GameMode.ADVENTURE || gameMode == GameMode.SPECTATOR; + boolean spectator = gameMode == GameMode.SPECTATOR; + boolean worldImmutable = gameMode == GameMode.ADVENTURE || spectator; Set<AdventureSetting> flags = adventureSettingsPacket.getSettings(); - if (canFly) { + if (canFly || spectator) { flags.add(AdventureSetting.MAY_FLY); } - if (flying) { + if (flying || spectator) { + if (spectator && !flying) { + // We're "flying locked" in this gamemode + flying = true; + ClientPlayerAbilitiesPacket abilitiesPacket = new ClientPlayerAbilitiesPacket(true); + sendDownstreamPacket(abilitiesPacket); + } flags.add(AdventureSetting.FLYING); } @@ -1298,7 +1293,7 @@ public class GeyserSession implements CommandSender { flags.add(AdventureSetting.WORLD_IMMUTABLE); } - if (noClip) { + if (spectator) { flags.add(AdventureSetting.NO_CLIP); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java index 61cc80910..e868eedeb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.bedrock; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerAbilitiesPacket; import com.nukkitx.protocol.bedrock.data.AdventureSetting; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; @@ -39,6 +40,12 @@ public class BedrockAdventureSettingsTranslator extends PacketTranslator<Adventu @Override public void translate(AdventureSettingsPacket packet, GeyserSession session) { boolean isFlying = packet.getSettings().contains(AdventureSetting.FLYING); + if (!isFlying && session.getGameMode() == GameMode.SPECTATOR) { + // We should always be flying in spectator mode + session.sendAdventureSettings(); + return; + } + session.setFlying(isFlying); ClientPlayerAbilitiesPacket abilitiesPacket = new ClientPlayerAbilitiesPacket(isFlying); session.sendDownstreamPacket(abilitiesPacket); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java index 8a0ddb3b5..f6eb375e6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java @@ -51,8 +51,6 @@ public class JavaNotifyClientTranslator extends PacketTranslator<ServerNotifyCli @Override public void translate(ServerNotifyClientPacket packet, GeyserSession session) { PlayerEntity entity = session.getPlayerEntity(); - if (entity == null) - return; switch (packet.getNotification()) { case START_RAIN: @@ -110,6 +108,18 @@ public class JavaNotifyClientTranslator extends PacketTranslator<ServerNotifyCli session.sendAdventureSettings(); + if (session.getPlayerEntity().isOnGround() && gameMode == GameMode.SPECTATOR) { + // Fix a bug where the player has glitched movement and thinks they are still on the ground + MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); + movePlayerPacket.setRuntimeEntityId(entity.getGeyserId()); + movePlayerPacket.setPosition(entity.getPosition()); + movePlayerPacket.setRotation(entity.getBedrockRotation()); + movePlayerPacket.setOnGround(false); + movePlayerPacket.setMode(MovePlayerPacket.Mode.TELEPORT); + movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.UNKNOWN); + session.sendUpstreamPacket(movePlayerPacket); + } + // Update the crafting grid to add/remove barriers for creative inventory PlayerInventoryTranslator.updateCraftingGrid(session, session.getPlayerInventory()); break;