diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index 9f7e21579d..3098ef0e0d 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.platform.spigot; +import org.geysermc.mcprotocollib.protocol.MinecraftConstants; import org.geysermc.mcprotocollib.protocol.MinecraftProtocol; import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer; import io.netty.bootstrap.ServerBootstrap; @@ -176,9 +177,9 @@ private ChannelInitializer getChildHandler(GeyserBootstrap bootstrap, C */ private void workAroundWeirdBug(GeyserBootstrap bootstrap) { MinecraftProtocol protocol = new MinecraftProtocol(); - LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().address(), - bootstrap.getGeyserConfig().getRemote().port(), this.serverSocketAddress, - InetAddress.getLoopbackAddress().getHostAddress(), protocol, Runnable::run); + LocalSession session = new LocalSession(this.serverSocketAddress, InetAddress.getLoopbackAddress().getHostAddress(), protocol, Runnable::run); + session.setFlag(MinecraftConstants.CLIENT_HOST, bootstrap.getGeyserConfig().getRemote().address()); + session.setFlag(MinecraftConstants.CLIENT_PORT, bootstrap.getGeyserConfig().getRemote().port()); session.connect(); } diff --git a/core/src/main/java/org/geysermc/geyser/event/type/SessionDisconnectEventImpl.java b/core/src/main/java/org/geysermc/geyser/event/type/SessionDisconnectEventImpl.java index b746979df9..c845b23997 100644 --- a/core/src/main/java/org/geysermc/geyser/event/type/SessionDisconnectEventImpl.java +++ b/core/src/main/java/org/geysermc/geyser/event/type/SessionDisconnectEventImpl.java @@ -42,7 +42,7 @@ public class SessionDisconnectEventImpl extends SessionDisconnectEvent { private final Component reasonComponent; public SessionDisconnectEventImpl(@NonNull GeyserSession session, Component reason) { - super(session, MessageTranslator.convertToPlainText(reason, session.locale())); + super(session, MessageTranslator.convertMessageRaw(reason, session.locale())); this.reasonComponent = reason; } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index 3ea78a942b..aadaeb356b 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java @@ -47,6 +47,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Unbreakable; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import java.util.List; @@ -424,7 +425,7 @@ private int getRepairCost(GeyserItemStack itemStack) { private boolean hasDurability(GeyserItemStack itemStack) { if (itemStack.asItem().defaultMaxDamage() > 0) { - return itemStack.getComponentOrFallback(DataComponentType.UNBREAKABLE, false); + return itemStack.getComponent(DataComponentType.UNBREAKABLE) != null; } return false; } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalChannelWithRemoteAddress.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalChannelWithRemoteAddress.java index ac2b6898a7..dacb4de69d 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalChannelWithRemoteAddress.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalChannelWithRemoteAddress.java @@ -28,18 +28,19 @@ import io.netty.channel.local.LocalChannel; import java.net.InetSocketAddress; +import java.net.SocketAddress; /** * Client -> server storing the spoofed remote address. */ public class LocalChannelWithRemoteAddress extends LocalChannel { - private InetSocketAddress spoofedAddress; + private SocketAddress spoofedAddress; - public InetSocketAddress spoofedRemoteAddress() { + public SocketAddress spoofedRemoteAddress() { return spoofedAddress; } - public void spoofedRemoteAddress(InetSocketAddress socketAddress) { + public void spoofedRemoteAddress(SocketAddress socketAddress) { this.spoofedAddress = socketAddress; } } diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index 3b86a0bf9f..e1847bdee3 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -27,151 +27,66 @@ import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelInitializer; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFactory; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelOption; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.DefaultEventLoopGroup; +import io.netty.channel.ReflectiveChannelFactory; import io.netty.channel.unix.PreferredDirectByteBufAllocator; -import io.netty.handler.codec.haproxy.HAProxyCommand; -import io.netty.handler.codec.haproxy.HAProxyMessage; -import io.netty.handler.codec.haproxy.HAProxyMessageEncoder; -import io.netty.handler.codec.haproxy.HAProxyProtocolVersion; -import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol; -import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.WriteTimeoutHandler; -import io.netty.util.concurrent.DefaultThreadFactory; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.mcprotocollib.network.BuiltinFlags; -import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper; +import org.geysermc.mcprotocollib.network.helper.NettyHelper; +import org.geysermc.mcprotocollib.network.netty.MinecraftChannelInitializer; import org.geysermc.mcprotocollib.network.packet.PacketProtocol; -import org.geysermc.mcprotocollib.network.tcp.FlushHandler; -import org.geysermc.mcprotocollib.network.tcp.TcpFlowControlHandler; -import org.geysermc.mcprotocollib.network.tcp.TcpPacketCodec; -import org.geysermc.mcprotocollib.network.tcp.TcpPacketCompression; -import org.geysermc.mcprotocollib.network.tcp.TcpPacketEncryptor; -import org.geysermc.mcprotocollib.network.tcp.TcpPacketSizer; -import org.geysermc.mcprotocollib.network.tcp.TcpSession; -import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.network.session.ClientNetworkSession; -import java.net.Inet4Address; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; /** * Manages a Minecraft Java session over our LocalChannel implementations. */ -public final class LocalSession extends TcpSession { - private static DefaultEventLoopGroup DEFAULT_EVENT_LOOP_GROUP; +public final class LocalSession extends ClientNetworkSession { private static PreferredDirectByteBufAllocator PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR = null; - private final SocketAddress targetAddress; - private final String clientIp; - private final PacketCodecHelper codecHelper; + private final SocketAddress spoofedRemoteAddress; - public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, Executor packetHandlerExecutor) { - super(host, port, protocol, packetHandlerExecutor); - this.targetAddress = targetAddress; - this.clientIp = clientIp; - this.codecHelper = protocol.createHelper(); + public LocalSession(SocketAddress targetAddress, String clientIp, PacketProtocol protocol, Executor packetHandlerExecutor) { + super(targetAddress, protocol, packetHandlerExecutor, null, null); + this.spoofedRemoteAddress = new InetSocketAddress(clientIp, 0); } @Override - public void connect(boolean wait, boolean transferring) { - if (this.disconnected) { - throw new IllegalStateException("Connection has already been disconnected."); - } - - if (DEFAULT_EVENT_LOOP_GROUP == null) { - DEFAULT_EVENT_LOOP_GROUP = new DefaultEventLoopGroup(new DefaultThreadFactory(this.getClass(), true)); - Runtime.getRuntime().addShutdownHook(new Thread( - () -> DEFAULT_EVENT_LOOP_GROUP.shutdownGracefully(100, 500, TimeUnit.MILLISECONDS))); - } - - final Bootstrap bootstrap = new Bootstrap(); - bootstrap.channel(LocalChannelWithRemoteAddress.class); - bootstrap.handler(new ChannelInitializer() { - @Override - public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) { - channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0)); - PacketProtocol protocol = getPacketProtocol(); - protocol.newClientSession(LocalSession.this, transferring); - - ChannelPipeline pipeline = channel.pipeline(); - - addHAProxySupport(pipeline); - - pipeline.addLast("read-timeout", new ReadTimeoutHandler(getFlag(BuiltinFlags.READ_TIMEOUT, 30))); - pipeline.addLast("write-timeout", new WriteTimeoutHandler(getFlag(BuiltinFlags.WRITE_TIMEOUT, 0))); - - pipeline.addLast("encryption", new TcpPacketEncryptor()); - pipeline.addLast("sizer", new TcpPacketSizer(protocol.getPacketHeader(), getCodecHelper())); - pipeline.addLast("compression", new TcpPacketCompression(getCodecHelper())); - - pipeline.addLast("flow-control", new TcpFlowControlHandler()); - pipeline.addLast("codec", new TcpPacketCodec(LocalSession.this, true)); - pipeline.addLast("flush-handler", new FlushHandler()); - pipeline.addLast("manager", LocalSession.this); - } - }).group(DEFAULT_EVENT_LOOP_GROUP).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getFlag(BuiltinFlags.CLIENT_CONNECT_TIMEOUT, 30) * 1000); + protected ChannelFactory getChannelFactory() { + return new ReflectiveChannelFactory<>(LocalChannelWithRemoteAddress.class); + } + @Override + protected void setOptions(Bootstrap bootstrap) { if (PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR != null) { bootstrap.option(ChannelOption.ALLOCATOR, PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR); } + } - bootstrap.remoteAddress(targetAddress); - - CompletableFuture handleFuture = new CompletableFuture<>(); - bootstrap.connect().addListener((futureListener) -> { - if (!futureListener.isSuccess()) { - exceptionCaught(null, futureListener.cause()); - } + @Override + protected ChannelHandler getChannelHandler() { + return new MinecraftChannelInitializer<>(channel -> { + PacketProtocol protocol = getPacketProtocol(); + protocol.newClientSession(LocalSession.this); - handleFuture.complete(null); - }); + return LocalSession.this; + }, true) { + @Override + public void initChannel(@NonNull Channel channel) throws Exception { + ((LocalChannelWithRemoteAddress) channel).spoofedRemoteAddress(spoofedRemoteAddress); - if (wait) { - handleFuture.join(); - } - } + NettyHelper.initializeHAProxySupport(LocalSession.this, channel); - @Override - public MinecraftCodecHelper getCodecHelper() { - return (MinecraftCodecHelper) this.codecHelper; + super.initChannel(channel); + } + }; } - // TODO duplicate code - private void addHAProxySupport(ChannelPipeline pipeline) { - InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS); - if (clientAddress != null) { - pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() { - @Override - public void channelActive(@NonNull ChannelHandlerContext ctx) throws Exception { - HAProxyProxiedProtocol proxiedProtocol = clientAddress.getAddress() instanceof Inet4Address ? HAProxyProxiedProtocol.TCP4 : HAProxyProxiedProtocol.TCP6; - InetSocketAddress remoteAddress; - if (ctx.channel().remoteAddress() instanceof InetSocketAddress) { - remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); - } else { - remoteAddress = new InetSocketAddress(host, port); - } - ctx.channel().writeAndFlush(new HAProxyMessage( - HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol, - clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(), - clientAddress.getPort(), remoteAddress.getPort() - )); - ctx.pipeline().remove(this); - ctx.pipeline().remove("proxy-protocol-encoder"); - super.channelActive(ctx); - } - }); - pipeline.addFirst("proxy-protocol-encoder", HAProxyMessageEncoder.INSTANCE); - } - } - /** * Should only be called when direct ByteBufs should be preferred. At this moment, this should only be called on BungeeCord. */ diff --git a/core/src/main/java/org/geysermc/geyser/session/DownstreamSession.java b/core/src/main/java/org/geysermc/geyser/session/DownstreamSession.java index c1db894845..22827ccfac 100644 --- a/core/src/main/java/org/geysermc/geyser/session/DownstreamSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/DownstreamSession.java @@ -29,14 +29,14 @@ import lombok.RequiredArgsConstructor; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.mcprotocollib.network.ClientSession; import org.geysermc.mcprotocollib.network.packet.Packet; -import org.geysermc.mcprotocollib.network.tcp.TcpSession; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; @Getter @RequiredArgsConstructor public class DownstreamSession { - private final TcpSession session; + private final ClientSession session; public void sendPacket(@NonNull Packet packet) { this.session.send(packet); diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index f40dcfecc8..1cb5d1fd48 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -181,9 +181,9 @@ import org.geysermc.geyser.util.MinecraftAuthLogger; import org.geysermc.mcprotocollib.auth.GameProfile; import org.geysermc.mcprotocollib.network.BuiltinFlags; +import org.geysermc.mcprotocollib.network.ClientSession; import org.geysermc.mcprotocollib.network.packet.Packet; -import org.geysermc.mcprotocollib.network.tcp.TcpClientSession; -import org.geysermc.mcprotocollib.network.tcp.TcpSession; +import org.geysermc.mcprotocollib.network.session.ClientNetworkSession; import org.geysermc.mcprotocollib.protocol.ClientListener; import org.geysermc.mcprotocollib.protocol.MinecraftConstants; import org.geysermc.mcprotocollib.protocol.MinecraftProtocol; @@ -199,6 +199,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.setting.SkinPart; import org.geysermc.mcprotocollib.protocol.data.game.statistic.CustomStatistic; import org.geysermc.mcprotocollib.protocol.data.game.statistic.Statistic; +import org.geysermc.mcprotocollib.protocol.data.handshake.HandshakeIntent; import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundClientInformationPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatPacket; @@ -770,7 +771,7 @@ public void connect() { // Default move speed // Bedrock clients move very fast by default until they get an attribute packet correcting the speed attributesPacket.setAttributes(Collections.singletonList( - GeyserAttributeType.MOVEMENT_SPEED.getAttribute())); + GeyserAttributeType.MOVEMENT_SPEED.getAttribute())); upstream.sendPacket(attributesPacket); GameRulesChangedPacket gamerulePacket = new GameRulesChangedPacket(); @@ -826,8 +827,8 @@ public void authenticateWithAuthChain(String authChain) { StepMCToken.MCToken mcToken = mcProfile.getMcToken(); protocol = new MinecraftProtocol( - new GameProfile(mcProfile.getId(), mcProfile.getName()), - mcToken.getAccessToken() + new GameProfile(mcProfile.getId(), mcProfile.getName()), + mcToken.getAccessToken() ); geyser.saveAuthChain(bedrockUsername(), GSON.toJson(step.toJson(response))); return Boolean.TRUE; @@ -872,7 +873,7 @@ public void authenticateWithMicrosoftCode(boolean offlineAccess) { sendUpstreamPacket(packet); final PendingMicrosoftAuthentication.AuthenticationTask task = geyser.getPendingMicrosoftAuthentication().getOrCreateTask( - getAuthData().xuid() + getAuthData().xuid() ); if (task.getAuthentication() != null && task.getAuthentication().isDone()) { onMicrosoftLoginComplete(task); @@ -898,8 +899,8 @@ public boolean onMicrosoftLoginComplete(PendingMicrosoftAuthentication.Authentic if (ex != null) { geyser.getLogger().error("Failed to log in with Microsoft code!", ex); if (ex instanceof CompletionException ce - && ce.getCause() instanceof MinecraftRequestException mre - && mre.getResponse().getStatusCode() == 404) { + && ce.getCause() instanceof MinecraftRequestException mre + && mre.getResponse().getStatusCode() == 404) { // Player is trying to join with a Microsoft account that doesn't have Java Edition purchased disconnect(GeyserLocale.getPlayerLocaleString("geyser.network.remote.invalid_account", locale())); } else { @@ -912,8 +913,8 @@ public boolean onMicrosoftLoginComplete(PendingMicrosoftAuthentication.Authentic StepMCToken.MCToken mcToken = mcProfile.getMcToken(); this.protocol = new MinecraftProtocol( - new GameProfile(mcProfile.getId(), mcProfile.getName()), - mcToken.getAccessToken() + new GameProfile(mcProfile.getId(), mcProfile.getName()), + mcToken.getAccessToken() ); try { @@ -937,7 +938,7 @@ private void connectDownstream() { GeyserImpl.getInstance().eventBus().fire(loginEvent); if (loginEvent.isCancelled()) { String disconnectReason = loginEvent.disconnectReason() == null ? - BedrockDisconnectReasons.DISCONNECTED : loginEvent.disconnectReason(); + BedrockDisconnectReasons.DISCONNECTED : loginEvent.disconnectReason(); disconnect(disconnectReason); return; } @@ -948,15 +949,17 @@ private void connectDownstream() { // Start ticking tickThread = tickEventLoop.scheduleAtFixedRate(this::tick, nanosecondsPerTick, nanosecondsPerTick, TimeUnit.NANOSECONDS); - TcpSession downstream; + ClientSession downstream; if (geyser.getBootstrap().getSocketAddress() != null) { // We're going to connect through the JVM and not through TCP - downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(), - geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(), - this.protocol, this.tickEventLoop); + downstream = new LocalSession(geyser.getBootstrap().getSocketAddress(), + upstream.getAddress().getAddress().getHostAddress(), + this.protocol, this.tickEventLoop); + downstream.setFlag(MinecraftConstants.CLIENT_HOST, this.remoteServer.address()); + downstream.setFlag(MinecraftConstants.CLIENT_PORT, this.remoteServer.port()); this.downstream = new DownstreamSession(downstream); } else { - downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), "0.0.0.0", 0, this.protocol, null, tickEventLoop); + downstream = new ClientNetworkSession(new InetSocketAddress(this.remoteServer.address(), this.remoteServer.port()), this.protocol, tickEventLoop, null, null); this.downstream = new DownstreamSession(downstream); boolean resolveSrv = false; @@ -986,11 +989,12 @@ private void connectDownstream() { protocol.setUseDefaultListeners(false); // MCPL listener comes first to handle protocol state switching before Geyser translates packets - downstream.addListener(new ClientListener(ProtocolState.LOGIN, loginEvent.transferring())); + downstream.addListener(new ClientListener(HandshakeIntent.LOGIN)); // Geyser adapter second to ensure translating packets in the correct states downstream.addListener(new GeyserSessionAdapter(this)); - downstream.connect(false, loginEvent.transferring()); + downstream.setFlag(BuiltinFlags.CLIENT_TRANSFERRING, loginEvent.transferring()); + downstream.connect(false); if (!daylightCycle) { setDaylightCycle(true); @@ -1287,7 +1291,7 @@ public void setGameMode(GameMode newGamemode) { public void setClientData(BedrockClientData data) { this.clientData = data; this.inputCache.setInputMode( - org.cloudburstmc.protocol.bedrock.data.InputMode.values()[data.getCurrentInputMode().ordinal()]); + org.cloudburstmc.protocol.bedrock.data.InputMode.values()[data.getCurrentInputMode().ordinal()]); } /** @@ -1295,7 +1299,7 @@ public void setClientData(BedrockClientData data) { */ public void useItem(Hand hand) { sendDownstreamGamePacket(new ServerboundUseItemPacket( - hand, worldCache.nextPredictionSequence(), playerEntity.getYaw(), playerEntity.getPitch())); + hand, worldCache.nextPredictionSequence(), playerEntity.getYaw(), playerEntity.getPitch())); } public void releaseItem() { @@ -1351,7 +1355,7 @@ public void armSwingPending() { private boolean disableBlocking() { if (playerEntity.getFlag(EntityFlag.BLOCKING)) { ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, - Vector3i.ZERO, Direction.DOWN, 0); + Vector3i.ZERO, Direction.DOWN, 0); sendDownstreamGamePacket(releaseItemPacket); playerEntity.setFlag(EntityFlag.BLOCKING, false); return true; @@ -1361,7 +1365,7 @@ private boolean disableBlocking() { public void requestOffhandSwap() { ServerboundPlayerActionPacket swapHandsPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, Vector3i.ZERO, - Direction.DOWN, 0); + Direction.DOWN, 0); sendDownstreamGamePacket(swapHandsPacket); } @@ -1585,7 +1589,7 @@ public void confirmTeleport(Vector3d position) { unconfirmedTeleport.resetUnconfirmedFor(); geyser.getLogger().debug("Resending teleport " + unconfirmedTeleport.getTeleportConfirmId()); getPlayerEntity().moveAbsolute(Vector3f.from(unconfirmedTeleport.getX(), unconfirmedTeleport.getY(), unconfirmedTeleport.getZ()), - unconfirmedTeleport.getYaw(), unconfirmedTeleport.getPitch(), playerEntity.isOnGround(), true); + unconfirmedTeleport.getYaw(), unconfirmedTeleport.getPitch(), playerEntity.isOnGround(), true); } } @@ -1841,8 +1845,8 @@ private int getRenderDistance() { public void sendJavaClientSettings() { // Locale is lowercase on Java - (https://github.com/GeyserMC/Geyser/issues/5235) ServerboundClientInformationPacket clientSettingsPacket = new ServerboundClientInformationPacket(locale().toLowerCase(Locale.ROOT), - getRenderDistance(), ChatVisibility.FULL, true, SKIN_PARTS, - HandPreference.RIGHT_HAND, false, true, ParticleStatus.ALL); // TODO particle status + getRenderDistance(), ChatVisibility.FULL, true, SKIN_PARTS, + HandPreference.RIGHT_HAND, false, true, ParticleStatus.ALL); // TODO particle status sendDownstreamPacket(clientSettingsPacket); } @@ -1895,8 +1899,8 @@ public float getEyeHeight() { return switch (pose) { case SNEAKING -> 1.27f; case SWIMMING, - FALL_FLYING, // Elytra - SPIN_ATTACK -> 0.4f; // Trident spin attack + FALL_FLYING, // Elytra + SPIN_ATTACK -> 0.4f; // Trident spin attack case SLEEPING -> 0.2f; default -> EntityDefinitions.PLAYER.offset(); }; diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java index fdc90c2156..c6318c461b 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/item/CustomItemTranslator.java @@ -119,9 +119,7 @@ private static boolean isDamaged(DataComponents components, int damage) { private static boolean isDamagableItem(DataComponents components) { // mapping.getMaxDamage > 0 should also be checked (return false if not true) but we already check prior to this function - Boolean unbreakable = components.get(DataComponentType.UNBREAKABLE); - // Tag must either not be present or be set to false - return unbreakable == null || !unbreakable; + return components.get(DataComponentType.UNBREAKABLE) == null; } private CustomItemTranslator() { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 65cef50f8f..598fb47791 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-common = "3.0.0.Beta5-20241213.160944-20" protocol-codec = "3.0.0.Beta5-20241213.160944-20" raknet = "1.0.0.CR3-20240416.144209-1" minecraftauth = "4.1.1" -mcprotocollib = "1.21.4-20241222.190029-11" +mcprotocollib = "1.21.4-20250118.113140-16" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2"