diff --git a/README.md b/README.md index 342a4c13f..b2bd01d99 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here! ## Supported Versions -Geyser is currently supporting Minecraft Bedrock 1.21.50 - 1.21.90 and Minecraft Java 1.21.5. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/). +Geyser is currently supporting Minecraft Bedrock 1.21.70 - 1.21.90 and Minecraft Java 1.21.6. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/). ## Setting Up Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser. diff --git a/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java index ede4c1bc4..b7a678aa6 100644 --- a/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java +++ b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java @@ -65,6 +65,12 @@ public interface GeyserConnection extends Connection, CommandSource { */ int ping(); + /** + * @return {@code true} if the client currently has a form open. + * @since 2.8.0 + */ + boolean hasFormOpen(); + /** * Closes the currently open form on the client. */ @@ -75,6 +81,43 @@ public interface GeyserConnection extends Connection, CommandSource { */ int protocolVersion(); + /** + * Attempts to open the {@code minecraft:pause_screen_additions} dialog tag. This method opens this dialog the same way Java does, that is: + * + *
Use {@link GeyserConnection#hasFormOpen()} to check if a dialog was opened.
+ * @since 2.8.0 + */ + void openPauseScreenAdditions(); + + /** + * Attempts to open the {@code minecraft:quick_actions} dialog tag. This method opens this dialog the same way Java does, that is: + * + *Use {@link GeyserConnection#hasFormOpen()} to check if a dialog was opened.
+ * @since 2.8.0 + */ + void openQuickActions(); + + /** + * Sends a command as if the player had executed it. + * + * @param command the command without the leading forward-slash + * @since 2.8.0 + */ + void sendCommand(String command); + /** * @param javaId the Java entity ID to look up. * @return a {@link GeyserEntity} if present in this connection's entity tracker. diff --git a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json index c0056e5cf..69071cea4 100644 --- a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json +++ b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json @@ -25,6 +25,6 @@ "depends": { "fabricloader": ">=0.16.7", "fabric-api": "*", - "minecraft": ">=1.21.5" + "minecraft": ">=1.21.6" } } diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/PermissionUtils.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/PermissionUtils.java index c57dc9a6c..5755e407f 100644 --- a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/PermissionUtils.java +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/PermissionUtils.java @@ -32,6 +32,8 @@ import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.platform.neoforge.mixin.PermissionNodeMixin; +import java.util.Objects; + /** * Common logic for handling the more complicated way we have to register permission on NeoForge */ @@ -69,7 +71,7 @@ public class PermissionUtils { case FALSE -> false; case NOT_SET -> { if (player != null) { - yield player.createCommandSourceStack().hasPermission(player.server.getOperatorUserPermissionLevel()); + yield player.createCommandSourceStack().hasPermission(Objects.requireNonNull(player.getServer()).getOperatorUserPermissionLevel()); } yield false; // NeoForge javadocs say player is null in the case of an offline player. } diff --git a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml index 7958926bc..3f1fe574d 100644 --- a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -16,12 +16,12 @@ config = "geyser_neoforge.mixins.json" [[dependencies.geyser_neoforge]] modId="neoforge" type="required" - versionRange="[21.5.0-beta,)" + versionRange="[21.6.0-beta,)" ordering="NONE" side="BOTH" [[dependencies.geyser_neoforge]] modId="minecraft" type="required" - versionRange="[1.21.5,)" + versionRange="[1.21.6,)" ordering="NONE" side="BOTH" diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java index e1f9c01e2..2b2e3b736 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/ModPingPassthrough.java @@ -25,22 +25,20 @@ package org.geysermc.geyser.platform.mod; +import com.mojang.serialization.JsonOps; +import io.netty.channel.ChannelFutureListener; import lombok.AllArgsConstructor; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import net.minecraft.core.RegistryAccess; import net.minecraft.network.Connection; -import net.minecraft.network.PacketSendListener; +import net.minecraft.network.chat.ComponentSerialization; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; import net.minecraft.network.protocol.status.ServerStatus; import net.minecraft.network.protocol.status.ServerStatusPacketListener; import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; +import net.minecraft.resources.RegistryOps; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerStatusPacketListenerImpl; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.ping.GeyserPingInfo; @@ -52,9 +50,6 @@ import java.util.Objects; @AllArgsConstructor public class ModPingPassthrough implements IGeyserPingPassthrough { - private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.gson(); - private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacySection(); - private final MinecraftServer server; private final GeyserLogger logger; @@ -81,7 +76,7 @@ public class ModPingPassthrough implements IGeyserPingPassthrough { } return new GeyserPingInfo( - net.minecraft.network.chat.Component.Serializer.toJson(status.description(), RegistryAccess.EMPTY), + ComponentSerialization.CODEC.encodeStart(RegistryOps.create(JsonOps.INSTANCE, server.registryAccess()), status.description()).getOrThrow().toString(), status.players().map(ServerStatus.Players::max).orElse(1), status.players().map(ServerStatus.Players::online).orElse(0) ); @@ -99,11 +94,11 @@ public class ModPingPassthrough implements IGeyserPingPassthrough { } @Override - public void send(@NonNull Packet> packet, @Nullable PacketSendListener packetSendListener, boolean bl) { + public void send(Packet> packet, @Nullable ChannelFutureListener channelFutureListener, boolean bl) { if (packet instanceof ClientboundStatusResponsePacket statusResponse) { status = statusResponse.status(); } - super.send(packet, packetSendListener, bl); + super.send(packet, channelFutureListener, bl); } } } diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSource.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSource.java index af1f368b3..f34164b5a 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSource.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSource.java @@ -25,10 +25,13 @@ package org.geysermc.geyser.platform.mod.command; +import com.google.gson.JsonElement; +import com.mojang.serialization.JsonOps; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.resources.RegistryOps; import net.minecraft.server.level.ServerPlayer; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -36,7 +39,6 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.text.ChatColor; -import java.util.Objects; import java.util.UUID; public class ModCommandSource implements GeyserCommandSource { @@ -65,8 +67,8 @@ public class ModCommandSource implements GeyserCommandSource { @Override public void sendMessage(net.kyori.adventure.text.Component message) { if (source.getEntity() instanceof ServerPlayer player) { - String decoded = GsonComponentSerializer.gson().serialize(message); - player.displayClientMessage(Objects.requireNonNull(Component.Serializer.fromJson(decoded, RegistryAccess.EMPTY)), false); + JsonElement jsonComponent = GsonComponentSerializer.gson().serializeToTree(message); + player.displayClientMessage(ComponentSerialization.CODEC.parse(RegistryOps.create(JsonOps.INSTANCE, player.registryAccess()), jsonComponent).getOrThrow(), false); return; } GeyserCommandSource.super.sendMessage(message); diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java index f791aab7a..5ede434c9 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.platform.mod.world; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.SharedConstants; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.BuiltInRegistries; @@ -50,7 +49,6 @@ import java.util.function.Consumer; public class GeyserModWorldManager extends GeyserWorldManager { - private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.gson(); private final MinecraftServer server; public GeyserModWorldManager(MinecraftServer server) { @@ -62,7 +60,7 @@ public class GeyserModWorldManager extends GeyserWorldManager { // If the protocol version of Geyser and the server are not the // same, fallback to the chunk cache. May be able to update this // in the future to use ViaVersion however, like Spigot does. - if (SharedConstants.getCurrentVersion().getProtocolVersion() != GameProtocol.getJavaProtocolVersion()) { + if (SharedConstants.getCurrentVersion().protocolVersion() != GameProtocol.getJavaProtocolVersion()) { return super.getBlockAt(session, x, y, z); } @@ -96,7 +94,7 @@ public class GeyserModWorldManager extends GeyserWorldManager { @Override public boolean hasOwnChunkCache() { - return SharedConstants.getCurrentVersion().getProtocolVersion() == GameProtocol.getJavaProtocolVersion(); + return SharedConstants.getCurrentVersion().protocolVersion() == GameProtocol.getJavaProtocolVersion(); } @Override diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java index 03ae18408..60bd959d2 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java @@ -236,6 +236,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { // Event must be fired after CommandRegistry has subscribed its listener. // Also, the subscription for the Permissions class is created when Geyser is initialized. cloud.fireRegisterPermissionsEvent(); + } else { + // This isn't ideal - but geyserLogger#start won't ever finish, leading to a reloading deadlock + geyser.setReloading(false); } if (gui != null) { diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java index 0db3c662a..a61a65805 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPingPassthrough.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.platform.velocity; import com.velocitypowered.api.event.proxy.ProxyPingEvent; +import com.velocitypowered.api.network.HandshakeIntent; import com.velocitypowered.api.network.ProtocolState; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.InboundConnection; @@ -84,6 +85,11 @@ public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough { return Optional.empty(); } + @Override + public Optional
* This also updates the session's last vehicle move timestamp.
* @param javaPos the new java position of the vehicle
+ * @param lastRotation the previous rotation of the vehicle (pitch, yaw, headYaw)
*/
- protected void moveVehicle(Vector3d javaPos) {
+ protected void moveVehicle(Vector3d javaPos, Vector3f lastRotation) {
Vector3f bedrockPos = javaPos.toFloat();
- Vector2f rotation = getVehicleRotation();
MoveEntityDeltaPacket moveEntityDeltaPacket = new MoveEntityDeltaPacket();
moveEntityDeltaPacket.setRuntimeEntityId(vehicle.getGeyserId());
@@ -740,27 +756,24 @@ public class VehicleComponent