diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 036d838ef8e..ecdb8deed7f 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,11 +1,12 @@
name: Bug report
description: Create a report to help us improve
+type: Bug
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report for Geyser! Fill out the following form to your best ability to help us fix the problem.
- Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/geysermc), [the FAQ](https://github.com/GeyserMC/Geyser/wiki/FAQ) or the [Common Issues](https://github.com/GeyserMC/Geyser/wiki/Common-Issues).
+ Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/geysermc), [the FAQ](https://geysermc.org/wiki/geyser/faq) or the [Common Issues](https://geysermc.org/wiki/geyser/common-issues).
- type: textarea
attributes:
label: Describe the bug
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index d0e42478bc8..872e30b8ec1 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -1,12 +1,13 @@
name: Feature request
description: Suggest an idea for this project
labels: "Feature Request"
+type: Feature
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this feature request for Geyser! Please fill out the following form to your best ability to help us understand your feature request and significantly improve the chance of getting added.
- For anything else than a feature request, use: [our Discord server](https://discord.gg/geysermc), [the FAQ](https://github.com/GeyserMC/Geyser/wiki/FAQ) or [the Common Issues](https://github.com/GeyserMC/Geyser/wiki/Common-Issues).
+ For anything else than a feature request, use: [our Discord server](https://discord.gg/geysermc), [the FAQ](https://geysermc.org/wiki/geyser/faq) or the [Common Issues](https://geysermc.org/wiki/geyser/common-issues).
- type: textarea
attributes:
label: What feature do you want to see added?
@@ -18,4 +19,4 @@ body:
label: Are there any alternatives?
description: List any alternatives you might have tried
validations:
- required: true
\ No newline at end of file
+ required: true
diff --git a/README.md b/README.md
index d0bcb1fdcd9..c6962f65e0b 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.20.80 - 1.21.44 and Minecraft Java 1.21.2/1.21.3. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/).
+Geyser is currently supporting Minecraft Bedrock 1.21.40 - 1.21.61 and Minecraft Java 1.21.4. 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/block/custom/nonvanilla/JavaBlockItem.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockItem.java
deleted file mode 100644
index 5143246d9d4..00000000000
--- a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockItem.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.geysermc.geyser.api.block.custom.nonvanilla;
-
-import org.checkerframework.checker.index.qual.NonNegative;
-import org.checkerframework.checker.nullness.qual.NonNull;
-
-public record JavaBlockItem(@NonNull String identifier, @NonNegative int javaId, @NonNegative int stackSize) {
-}
diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java
index 0dd0d3b330b..61b868cc393 100644
--- a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java
+++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java
@@ -70,7 +70,7 @@ public interface JavaBlockState {
@Nullable String pistonBehavior();
/**
- * Gets whether the block state has block entity
+ * Gets whether the block state has a block entity
*
* @return whether the block state has block entity
* @deprecated Does not have an effect. If you were using this to
diff --git a/api/src/main/java/org/geysermc/geyser/api/entity/type/player/GeyserPlayerEntity.java b/api/src/main/java/org/geysermc/geyser/api/entity/type/player/GeyserPlayerEntity.java
index bba4dbf3ec6..d31def99670 100644
--- a/api/src/main/java/org/geysermc/geyser/api/entity/type/player/GeyserPlayerEntity.java
+++ b/api/src/main/java/org/geysermc/geyser/api/entity/type/player/GeyserPlayerEntity.java
@@ -31,9 +31,9 @@
public interface GeyserPlayerEntity extends GeyserEntity {
/**
- * Gets the position of the player.
+ * Gets the position of the player, as it is known to the Java server.
*
- * @return the position of the player.
+ * @return the player's position
*/
Vector3f position();
}
diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionDisconnectEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionDisconnectEvent.java
index 05e3415a070..f97f32f92d7 100644
--- a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionDisconnectEvent.java
+++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionDisconnectEvent.java
@@ -50,7 +50,7 @@ public SessionDisconnectEvent(@NonNull GeyserConnection connection, @NonNull Str
}
/**
- * Sets the disconnect reason, thereby overriding th original reason.
+ * Sets the disconnect message shown to the Bedrock client.
*
* @param disconnectReason the reason for the disconnect
*/
diff --git a/api/src/main/java/org/geysermc/geyser/api/event/connection/GeyserBedrockPingEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/connection/GeyserBedrockPingEvent.java
index 10ccb93d52c..64d3cb44f84 100644
--- a/api/src/main/java/org/geysermc/geyser/api/event/connection/GeyserBedrockPingEvent.java
+++ b/api/src/main/java/org/geysermc/geyser/api/event/connection/GeyserBedrockPingEvent.java
@@ -33,10 +33,10 @@
import java.net.InetSocketAddress;
/**
- * Called whenever Geyser gets pinged
+ * Called whenever Geyser gets pinged by a Bedrock client.
*
- * This event allows you to modify/obtain the MOTD, maximum player count, and current number of players online,
- * Geyser will reply to the client with what was given.
+ * This event allows you to modify/obtain the MOTD, maximum player count, and current number of players online.
+ * Geyser will reply to the client with the information provided in this event.
*/
public interface GeyserBedrockPingEvent extends Event {
diff --git a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerDefineCommandsEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerDefineCommandsEvent.java
index 299c9d6dd6a..40268d5b2c3 100644
--- a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerDefineCommandsEvent.java
+++ b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerDefineCommandsEvent.java
@@ -37,7 +37,7 @@
*
* This event is mapped to the existence of Brigadier on the server.
*/
-public class ServerDefineCommandsEvent extends ConnectionEvent implements Cancellable {
+public final class ServerDefineCommandsEvent extends ConnectionEvent implements Cancellable {
private final Set extends CommandInfo> commands;
private boolean cancelled;
diff --git a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java
index 594e28ef056..f32d84f6a51 100644
--- a/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java
+++ b/api/src/main/java/org/geysermc/geyser/api/event/java/ServerTransferEvent.java
@@ -37,7 +37,7 @@
* Fired when the Java server sends a transfer request to a different Java server.
* Geyser Extensions can listen to this event and set a target server ip/port for Bedrock players to be transferred to.
*/
-public class ServerTransferEvent extends ConnectionEvent {
+public final class ServerTransferEvent extends ConnectionEvent {
private final String host;
private final int port;
diff --git a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java
index 2c283780cc1..2fff247a78c 100644
--- a/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java
+++ b/api/src/main/java/org/geysermc/geyser/api/item/custom/NonVanillaCustomItemData.java
@@ -80,10 +80,9 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Nullable String toolType();
/**
- * Gets the tool tier of the item.
- *
- * @return the tool tier of the item
+ * @deprecated no longer used
*/
+ @Deprecated(forRemoval = true)
@Nullable String toolTier();
/**
@@ -108,10 +107,9 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Nullable String translationString();
/**
- * Gets the repair materials of the item.
- *
- * @return the repair materials of the item
+ * @deprecated No longer used.
*/
+ @Deprecated(forRemoval = true)
@Nullable Set repairMaterials();
/**
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeCompressionDisabler.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeCompressionDisabler.java
index 485079a0579..23ab3636327 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeCompressionDisabler.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeCompressionDisabler.java
@@ -28,6 +28,7 @@
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
+import net.md_5.bungee.netty.LengthPrependerAndCompressor;
import net.md_5.bungee.protocol.packet.LoginSuccess;
import net.md_5.bungee.protocol.packet.SetCompression;
@@ -40,8 +41,9 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
// Fixes https://github.com/GeyserMC/Geyser/issues/4281
// The server may send a LoginDisconnect packet after compression is set.
if (!compressionDisabled) {
- if (ctx.pipeline().get("compress") != null) {
- ctx.pipeline().remove("compress");
+ LengthPrependerAndCompressor compressor = ctx.pipeline().get(LengthPrependerAndCompressor.class);
+ if (compressor.isCompress()) {
+ compressor.setCompress(false);
compressionDisabled = true;
}
if (ctx.pipeline().get("decompress") != null) {
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java
index f84702ead27..8d8c8c9ef36 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeInjector.java
@@ -73,6 +73,14 @@ protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Excepti
throw new UnsupportedOperationException("Geyser does not currently support multiple listeners with injection! " +
"Please reach out to us on our Discord at https://discord.gg/GeyserMC so we can hear feedback on your setup.");
}
+
+ // TODO remove
+ try {
+ ProxyServer.class.getMethod("unsafe");
+ } catch (NoSuchMethodException e) {
+ throw new UnsupportedOperationException("You're using an outdated version of BungeeCord - please update. Thank you!");
+ }
+
ListenerInfo listenerInfo = proxy.getConfig().getListeners().stream().findFirst().orElseThrow(IllegalStateException::new);
Class extends ProxyServer> proxyClass = proxy.getClass();
@@ -138,7 +146,7 @@ protected void initChannel(@NonNull Channel ch) throws Exception {
if (channelInitializer == null) {
// Proxy has finished initializing; we can safely grab this variable without fear of plugins modifying it
// (Older versions of ViaVersion replace this to inject)
- channelInitializer = PipelineUtils.SERVER_CHILD;
+ channelInitializer = proxy.unsafe().getFrontendChannelInitializer().getChannelInitializer();
}
initChannel.invoke(channelInitializer, ch);
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java
index 263cf5fbd96..fb56d92c273 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePingPassthrough.java
@@ -26,6 +26,8 @@
package org.geysermc.geyser.platform.bungeecord;
import lombok.AllArgsConstructor;
+import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.chat.BaseComponent;
@@ -74,7 +76,7 @@ public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
ServerPing response = event.getResponse();
return new GeyserPingInfo(
- response.getDescriptionComponent().toLegacyText(),
+ GsonComponentSerializer.gson().serialize(BungeeComponentSerializer.get().deserialize(new BaseComponent[]{ response.getDescriptionComponent() })),
response.getPlayers().getMax(),
response.getPlayers().getOnline()
);
@@ -186,6 +188,21 @@ public boolean isConnected() {
return false;
}
+ @Override
+ public boolean isTransferred() {
+ return false;
+ }
+
+ @Override
+ public CompletableFuture retrieveCookie(String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public CompletableFuture sendData(String s, byte[] bytes) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public Unsafe unsafe() {
throw new UnsupportedOperationException();
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
index 70a4d082af8..1a9f4b83fc6 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
@@ -43,6 +43,7 @@
import org.geysermc.geyser.configuration.ConfigLoader;
import org.geysermc.geyser.configuration.GeyserPluginConfig;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
+import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSource;
@@ -59,6 +60,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
+import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -80,18 +82,19 @@ public void onLoad() {
public void onGeyserInitialize() {
GeyserLocale.init(this);
- // Copied from ViaVersion.
- // https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43
try {
- ProtocolConstants.class.getField("MINECRAFT_1_21");
- } catch (NoSuchFieldException e) {
- geyserLogger.error(" / \\");
- geyserLogger.error(" / \\");
- geyserLogger.error(" / | \\");
- geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName()));
- geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
- geyserLogger.error(" / o \\");
- geyserLogger.error("/_____________\\");
+ List supportedProtocols = ProtocolConstants.SUPPORTED_VERSION_IDS;
+ if (!supportedProtocols.contains(GameProtocol.getJavaProtocolVersion())) {
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / | \\");
+ geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName()));
+ geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
+ geyserLogger.error(" / o \\");
+ geyserLogger.error("/_____________\\");
+ }
+ } catch (Throwable e) {
+ geyserLogger.warning("Unable to check the versions supported by this proxy! " + e.getMessage());
}
if (!this.loadConfig()) {
diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts
index fc18d0e7446..711e304d395 100644
--- a/bootstrap/mod/fabric/build.gradle.kts
+++ b/bootstrap/mod/fabric/build.gradle.kts
@@ -38,6 +38,7 @@ dependencies {
modImplementation(libs.cloud.fabric)
include(libs.cloud.fabric)
+ include(libs.fabric.permissions.api)
}
tasks.withType {
diff --git a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json
index a801eb207d3..a1c786c2f5f 100644
--- a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json
+++ b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json
@@ -24,7 +24,7 @@
],
"depends": {
"fabricloader": ">=0.16.7",
- "fabric": "*",
- "minecraft": ">=1.21.2"
+ "fabric-api": "*",
+ "minecraft": ">=1.21.4"
}
}
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 a2bbfa379aa..e1f9c01e255 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
@@ -80,11 +80,8 @@ public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
}
}
- String jsonDescription = net.minecraft.network.chat.Component.Serializer.toJson(status.description(), RegistryAccess.EMPTY);
- String legacyDescription = LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(jsonDescription, Component.empty()));
-
return new GeyserPingInfo(
- legacyDescription,
+ net.minecraft.network.chat.Component.Serializer.toJson(status.description(), RegistryAccess.EMPTY),
status.players().map(ServerStatus.Players::max).orElse(1),
status.players().map(ServerStatus.Players::online).orElse(0)
);
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 f85b6e0796a..f791aab7a38 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
@@ -28,37 +28,24 @@
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
-import net.minecraft.core.RegistryAccess;
-import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
-import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerPlayer;
-import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
-import net.minecraft.world.level.block.entity.BannerBlockEntity;
-import net.minecraft.world.level.block.entity.BannerPatternLayers;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunkSection;
-import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.geyser.level.GeyserWorldManager;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.MinecraftKey;
-import org.geysermc.mcprotocollib.protocol.data.game.Holder;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
-import java.util.HashMap;
import java.util.List;
-import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
public class GeyserModWorldManager extends GeyserWorldManager {
@@ -117,49 +104,6 @@ public GameMode getDefaultGameMode(GeyserSession session) {
return GameMode.byId(server.getDefaultGameType().getId());
}
- @NonNull
- @Override
- public CompletableFuture getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
- CompletableFuture future = new CompletableFuture<>();
- server.execute(() -> {
- ServerPlayer player = getPlayer(session);
- if (player == null) {
- future.complete(null);
- return;
- }
-
- BlockPos pos = new BlockPos(x, y, z);
- // Don't create a new block entity if invalid
- //noinspection resource - level() is just a getter
- BlockEntity blockEntity = player.level().getChunkAt(pos).getBlockEntity(pos);
- if (blockEntity instanceof BannerBlockEntity banner) {
- // Potentially exposes other NBT data? But we need to get the NBT data for the banner patterns *and*
- // the banner might have a custom name, both of which a Java client knows and caches
- ItemStack itemStack = banner.getItem();
-
- org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents components =
- new org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents(new HashMap<>());
-
- components.put(DataComponentType.DAMAGE, itemStack.getDamageValue());
-
- Component customName = itemStack.getComponents().get(DataComponents.CUSTOM_NAME);
- if (customName != null) {
- components.put(DataComponentType.CUSTOM_NAME, toKyoriComponent(customName));
- }
-
- BannerPatternLayers pattern = itemStack.get(DataComponents.BANNER_PATTERNS);
- if (pattern != null) {
- components.put(DataComponentType.BANNER_PATTERNS, toPatternList(pattern));
- }
-
- future.complete(components);
- return;
- }
- future.complete(null);
- });
- return future;
- }
-
@Override
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer> apply) {
server.execute(() -> {
@@ -184,20 +128,4 @@ public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer toPatternList(BannerPatternLayers patternLayers) {
- return patternLayers.layers().stream()
- .map(layer -> {
- BannerPatternLayer.BannerPattern pattern = new BannerPatternLayer.BannerPattern(
- MinecraftKey.key(layer.pattern().value().assetId().toString()), layer.pattern().value().translationKey()
- );
- return new BannerPatternLayer(Holder.ofCustom(pattern), layer.color().getId());
- })
- .toList();
- }
}
diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts
index 29115f7d90e..af133f25487 100644
--- a/bootstrap/spigot/build.gradle.kts
+++ b/bootstrap/spigot/build.gradle.kts
@@ -1,6 +1,7 @@
plugins {
id("geyser.platform-conventions")
id("geyser.modrinth-uploading-conventions")
+ alias(libs.plugins.runpaper)
}
dependencies {
@@ -97,3 +98,9 @@ modrinth {
"1.19.1", "1.19.2", "1.19.3", "1.19.4", "1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6")
loaders.addAll("spigot", "paper")
}
+
+tasks {
+ runServer {
+ minecraftVersion(libs.versions.runpaperversion.get())
+ }
+}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java
index 6a962f4504f..60d5dee5545 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperPingPassthrough.java
@@ -27,6 +27,8 @@
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
import com.destroystokyo.paper.network.StatusClient;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Bukkit;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -81,7 +83,10 @@ public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
players = new GeyserPingInfo.Players(event.getMaxPlayers(), event.getNumPlayers());
}
- return new GeyserPingInfo(event.getMotd(), players);
+ return new GeyserPingInfo(
+ GsonComponentSerializer.gson().serialize(LegacyComponentSerializer.legacySection().deserialize(event.getMotd())),
+ players
+ );
} catch (Exception | LinkageError e) { // LinkageError in the event that method/constructor signatures change
logger.debug("Error while getting Paper ping passthrough: " + e);
return null;
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 c9500031a89..a61833cb0d2 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.MinecraftProtocol;
import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
@@ -40,7 +41,6 @@
import org.geysermc.geyser.network.netty.GeyserInjector;
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
import org.geysermc.geyser.network.netty.LocalSession;
-import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -180,11 +180,10 @@ private ChannelInitializer getChildHandler(GeyserBootstrap bootstrap, C
*/
private void workAroundWeirdBug(GeyserBootstrap bootstrap) {
MinecraftProtocol protocol = new MinecraftProtocol();
- LocalSession session = new LocalSession(bootstrap.config().java().address(),
- bootstrap.config().java().port(), this.serverSocketAddress,
- InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper());
+ LocalSession session = new LocalSession(this.serverSocketAddress, InetAddress.getLoopbackAddress().getHostAddress(), protocol, Runnable::run);
+ session.setFlag(MinecraftConstants.CLIENT_HOST, bootstrap.config().java().address());
+ session.setFlag(MinecraftConstants.CLIENT_PORT, bootstrap.config().java().port());
session.connect();
- session.disconnect("");
}
@Override
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java
index 4b1e428710a..acd19ae1853 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java
@@ -26,6 +26,8 @@
package org.geysermc.geyser.platform.spigot;
import lombok.AllArgsConstructor;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.server.ServerListPingEvent;
@@ -52,7 +54,11 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough {
try {
ServerListPingEvent event = new GeyserPingEvent(inetSocketAddress.getAddress(), Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers());
Bukkit.getPluginManager().callEvent(event);
- return new GeyserPingInfo(event.getMotd(), event.getMaxPlayers(), event.getNumPlayers());
+ return new GeyserPingInfo(
+ GsonComponentSerializer.gson().serialize(LegacyComponentSerializer.legacySection().deserialize(event.getMotd())),
+ event.getMaxPlayers(),
+ event.getNumPlayers()
+ );
} catch (Exception | LinkageError e) { // LinkageError in the event that method/constructor signatures change
logger.debug("Error while getting Bukkit ping passthrough: " + e);
return null;
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandSource.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandSource.java
index c1fb837c246..9f897b09538 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandSource.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandSource.java
@@ -29,6 +29,7 @@
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
+import org.bukkit.command.RemoteConsoleCommandSender;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -76,7 +77,7 @@ public Object handle() {
@Override
public boolean isConsole() {
- return handle instanceof ConsoleCommandSender;
+ return handle instanceof ConsoleCommandSender || handle instanceof RemoteConsoleCommandSender;
}
@Override
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
index c99ca4e783d..96ae4193305 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
@@ -33,7 +33,6 @@
import org.geysermc.geyser.adapters.WorldAdapter;
import org.geysermc.geyser.adapters.paper.PaperAdapters;
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
-import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
index 6588a22a3d6..54b5b917851 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
@@ -25,18 +25,14 @@
package org.geysermc.geyser.platform.spigot.world.manager;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.DecoratedPot;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.erosion.bukkit.BukkitUtils;
-import org.geysermc.erosion.bukkit.PickBlockUtils;
import org.geysermc.erosion.bukkit.SchedulerUtils;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.GameRule;
@@ -44,7 +40,6 @@
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import java.util.List;
import java.util.Objects;
@@ -128,20 +123,6 @@ public GameMode getDefaultGameMode(GeyserSession session) {
return GameMode.byId(Bukkit.getDefaultGameMode().ordinal());
}
- @Override
- public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
- Player bukkitPlayer;
- if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
- return CompletableFuture.completedFuture(null);
- }
- CompletableFuture> future = new CompletableFuture<>();
- Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
- // Paper 1.19.3 complains about async access otherwise.
- // java.lang.IllegalStateException: Tile is null, asynchronous access?
- SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block);
- return future.thenApply(RAW_TRANSFORMER);
- }
-
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer> apply) {
Player bukkitPlayer;
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
diff --git a/bootstrap/standalone/build.gradle.kts b/bootstrap/standalone/build.gradle.kts
index c6ced739ef6..d520d7cb2fe 100644
--- a/bootstrap/standalone/build.gradle.kts
+++ b/bootstrap/standalone/build.gradle.kts
@@ -5,9 +5,6 @@ plugins {
id("geyser.platform-conventions")
}
-val terminalConsoleVersion = "1.2.0"
-val jlineVersion = "3.21.0"
-
dependencies {
api(projects.core)
@@ -45,4 +42,6 @@ tasks.named("run") {
dir.mkdirs()
jvmArgs("-Dio.netty.leakDetection.level=PARANOID")
workingDir = dir
+
+ standardInput = System.`in`
}
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 9a55d5fff2b..aba2b7766a1 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
@@ -27,12 +27,9 @@
import io.netty.util.ResourceLeakDetector;
import lombok.Getter;
-import net.minecrell.terminalconsole.TerminalConsoleAppender;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Logger;
-import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
@@ -82,6 +79,9 @@ public static void main(String[] args) {
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // Can eat performance
}
+ System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
+ GeyserStandaloneLogger.setupStreams();
+
GeyserStandaloneBootstrap bootstrap = new GeyserStandaloneBootstrap();
// Set defaults
boolean useGuiOpts = bootstrap.useGui;
@@ -137,17 +137,10 @@ public static void main(String[] args) {
@Override
public void onGeyserInitialize() {
log4jLogger = (Logger) LogManager.getRootLogger();
- for (Appender appender : log4jLogger.getAppenders().values()) {
- // Remove the appender that is not in use
- // Prevents multiple appenders/double logging and removes harmless errors
- if ((useGui && appender instanceof TerminalConsoleAppender) || (!useGui && appender instanceof ConsoleAppender)) {
- log4jLogger.removeAppender(appender);
- }
- }
if (useGui && gui == null) {
gui = new GeyserStandaloneGUI(geyserLogger);
- gui.redirectSystemStreams();
+ gui.addGuiAppender();
gui.startUpdateThread();
}
@@ -197,9 +190,7 @@ public void onGeyserEnable() {
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
- if (!useGui) {
- geyserLogger.start(); // Throws an error otherwise
- }
+ geyserLogger.start();
}
/**
@@ -212,7 +203,8 @@ private boolean isHeadless() {
Class> graphicsEnv = Class.forName("java.awt.GraphicsEnvironment");
Method isHeadless = graphicsEnv.getDeclaredMethod("isHeadless");
return (boolean) isHeadless.invoke(null);
- } catch (Exception ignore) { }
+ } catch (Exception ignore) {
+ }
return true;
}
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java
index 5636c0ebfc7..13ece30048b 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneLogger.java
@@ -28,7 +28,10 @@
import lombok.extern.slf4j.Slf4j;
import net.minecrell.terminalconsole.SimpleTerminalConsole;
import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.logging.log4j.io.IoBuilder;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
@@ -40,6 +43,15 @@
@Slf4j
public class GeyserStandaloneLogger extends SimpleTerminalConsole implements GeyserLogger, GeyserCommandSource {
+ private static final Logger logger = LogManager.getLogger("GeyserConsole");
+
+ /**
+ * Sets up {@code System.out} and {@code System.err} to redirect to log4j.
+ */
+ public static void setupStreams() {
+ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream());
+ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.ERROR).buildPrintStream());
+ }
@Override
protected LineReader buildReader(LineReaderBuilder builder) {
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java
index 4cbd178af77..b1acb585b04 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java
@@ -25,7 +25,14 @@
package org.geysermc.geyser.platform.standalone.gui;
-import org.checkerframework.checker.nullness.qual.NonNull;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.NullConfiguration;
+import org.apache.logging.log4j.core.config.Property;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.command.CommandRegistry;
@@ -36,11 +43,16 @@
import javax.swing.table.DefaultTableModel;
import javax.swing.text.Document;
import java.awt.*;
-import java.awt.event.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@@ -83,7 +95,8 @@ public GeyserStandaloneGUI(GeyserLogger logger) {
// Remove Java UI look
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- } catch (Exception ignored) { }
+ } catch (Exception ignored) {
+ }
// Show a confirm dialog on close
frame.addWindowListener(new WindowAdapter() {
@@ -181,7 +194,8 @@ private void setupMenuBar(JFrame frame) {
openButton.addActionListener(e -> {
try {
Desktop.getDesktop().open(new File("./"));
- } catch (IOException ignored) { }
+ } catch (IOException ignored) {
+ }
});
fileMenu.add(openButton);
@@ -245,29 +259,8 @@ private void appendConsole(final String text) {
/**
* Redirect the default io streams to the text pane
*/
- public void redirectSystemStreams() {
- // Setup a new output stream to forward it to the text pane
- OutputStream out = new OutputStream() {
- @Override
- public void write(final int b) {
- appendConsole(String.valueOf((char) b));
- }
-
- @Override
- public void write(byte @NonNull [] b, int off, int len) {
- appendConsole(new String(b, off, len));
- }
-
- @Override
- public void write(byte @NonNull[] b) {
- write(b, 0, b.length);
- }
- };
-
- // Override the system output streams
- System.setOut(new PrintStream(out, true));
- System.setErr(new PrintStream(out, true));
-
+ public void addGuiAppender() {
+ new GUIAppender().start();
}
/**
@@ -354,4 +347,30 @@ public void actionPerformed(ActionEvent e) {
commandInput.setText(""); // clear the input
}
}
+
+ private class GUIAppender extends AbstractAppender {
+ private static final List FORMATTERS = PatternLayout.createPatternParser(new NullConfiguration())
+ .parse(
+ "[%d{HH:mm:ss} %style{%highlight{%level}{FATAL=red, ERROR=red, WARN=yellow bright, INFO=cyan bright, DEBUG=green, TRACE=white}}] %minecraftFormatting{%msg}%n",
+ true,
+ false,
+ false
+ );
+
+ protected GUIAppender() {
+ super("GUIAppender", null, null, false, Property.EMPTY_ARRAY);
+
+ ((Logger) LogManager.getRootLogger()).addAppender(this);
+ }
+
+ @Override
+ public void append(LogEvent event) {
+ StringBuilder formatted = new StringBuilder();
+ for (PatternFormatter formatter : FORMATTERS) {
+ formatter.format(event, formatted);
+ }
+
+ appendConsole(formatted.toString());
+ }
+ }
}
diff --git a/bootstrap/standalone/src/main/resources/log4j2.xml b/bootstrap/standalone/src/main/resources/log4j2.xml
index bf361a851de..0304e192454 100644
--- a/bootstrap/standalone/src/main/resources/log4j2.xml
+++ b/bootstrap/standalone/src/main/resources/log4j2.xml
@@ -4,9 +4,6 @@
-
-
-
@@ -18,7 +15,6 @@
-
diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts
index 94c609d7883..b15262cf2a8 100644
--- a/bootstrap/velocity/build.gradle.kts
+++ b/bootstrap/velocity/build.gradle.kts
@@ -1,6 +1,7 @@
plugins {
id("geyser.platform-conventions")
id("geyser.modrinth-uploading-conventions")
+ alias(libs.plugins.runvelocity)
}
dependencies {
@@ -84,3 +85,9 @@ modrinth {
uploadFile.set(tasks.getByPath("shadowJar"))
loaders.addAll("velocity")
}
+
+tasks {
+ runVelocity {
+ version(libs.versions.runvelocityversion.get())
+ }
+}
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 f200765978f..0db3c662ad8 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
@@ -33,7 +33,7 @@
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.proxy.server.ServerPing.Version;
import lombok.AllArgsConstructor;
-import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.ping.GeyserPingInfo;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
@@ -60,7 +60,7 @@ public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
throw new RuntimeException(e);
}
return new GeyserPingInfo(
- LegacyComponentSerializer.legacy('§').serialize(event.getPing().getDescriptionComponent()),
+ GsonComponentSerializer.gson().serialize(event.getPing().getDescriptionComponent()),
event.getPing().getPlayers().map(ServerPing.Players::getMax).orElse(1),
event.getPing().getPlayers().map(ServerPing.Players::getOnline).orElse(0)
);
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/VelocityCommandSource.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/VelocityCommandSource.java
index 2240f998837..f55f145ed63 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/VelocityCommandSource.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/VelocityCommandSource.java
@@ -60,7 +60,7 @@ public String name() {
@Override
public void sendMessage(@NonNull String message) {
- handle.sendMessage(LegacyComponentSerializer.legacy('§').deserialize(message));
+ handle.sendMessage(LegacyComponentSerializer.legacySection().deserialize(message));
}
@Override
diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
index 6030d4f8361..00d4e57ab8c 100644
--- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
+++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
@@ -24,15 +24,19 @@
*/
package org.geysermc.geyser.platform.viaproxy;
+import io.netty.channel.AbstractChannel;
import net.lenni0451.lambdaevents.EventHandler;
+import net.lenni0451.reflect.stream.RStream;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.viaproxy.ViaProxy;
import net.raphimc.viaproxy.plugins.PluginManager;
import net.raphimc.viaproxy.plugins.ViaProxyPlugin;
+import net.raphimc.viaproxy.plugins.events.Client2ProxyChannelInitializeEvent;
import net.raphimc.viaproxy.plugins.events.ConsoleCommandEvent;
import net.raphimc.viaproxy.plugins.events.ProxyStartEvent;
import net.raphimc.viaproxy.plugins.events.ProxyStopEvent;
import net.raphimc.viaproxy.plugins.events.ShouldVerifyOnlineModeEvent;
+import net.raphimc.viaproxy.plugins.events.types.ITyped;
import net.raphimc.viaproxy.protocoltranslator.viaproxy.ViaProxyConfig;
import org.apache.logging.log4j.LogManager;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -57,6 +61,7 @@
import java.io.File;
import java.net.InetSocketAddress;
+import java.net.SocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
@@ -110,6 +115,27 @@ private void onShouldVerifyOnlineModeEvent(final ShouldVerifyOnlineModeEvent eve
}
}
+ @EventHandler
+ private void onClient2ProxyChannelInitialize(Client2ProxyChannelInitializeEvent event) {
+ if (event.getType() != ITyped.Type.POST || event.isLegacyPassthrough()) {
+ return;
+ }
+ if (System.getProperty("geyser.viaproxy.disableIpPassthrough") != null) { // Temporary until Configurate branch is merged
+ return;
+ }
+
+ final GeyserSession session = GeyserImpl.getInstance().onlineConnections().stream()
+ .filter(c -> c.getDownstream() != null)
+ .filter(c -> c.getDownstream().getSession().getLocalAddress().equals(event.getChannel().remoteAddress()))
+ .findAny().orElse(null);
+ if (session != null) {
+ final SocketAddress realAddress = session.getSocketAddress();
+ if (event.getChannel() instanceof AbstractChannel) {
+ RStream.of(AbstractChannel.class, event.getChannel()).fields().by("remoteAddress").set(realAddress);
+ }
+ }
+ }
+
@EventHandler
private void onProxyStart(final ProxyStartEvent event) {
this.onGeyserEnable();
diff --git a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts
index 59f85d182a0..4f445f455cf 100644
--- a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts
+++ b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts
@@ -13,7 +13,7 @@ modrinth {
versionNumber.set(projectVersion(project))
versionType.set("beta")
changelog.set(System.getenv("CHANGELOG") ?: "")
- gameVersions.addAll("1.21.2", libs.minecraft.get().version as String)
+ gameVersions.add(libs.minecraft.get().version as String)
failSilently.set(true)
syncBodyFrom.set(rootProject.file("README.md").readText())
diff --git a/core/src/main/java/org/geysermc/geyser/Constants.java b/core/src/main/java/org/geysermc/geyser/Constants.java
index 6dcccd738f2..2485cf04dba 100644
--- a/core/src/main/java/org/geysermc/geyser/Constants.java
+++ b/core/src/main/java/org/geysermc/geyser/Constants.java
@@ -36,9 +36,6 @@ public final class Constants {
public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://geysermc.org/download#floodgate";
public static final String GEYSER_DOWNLOAD_LOCATION = "https://geysermc.org/download";
-
- @Deprecated
- static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json";
static final String SAVED_AUTH_CHAINS_FILE = "saved-auth-chains.json";
public static final String GEYSER_CUSTOM_NAMESPACE = "geyser_custom";
diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
index caaef479d93..51e188d8369 100644
--- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
+++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
@@ -36,8 +36,6 @@
import lombok.Setter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
-import net.raphimc.minecraftauth.step.java.session.StepFullJavaSession;
-import net.raphimc.minecraftauth.step.msa.StepMsaToken;
import org.bstats.MetricsBase;
import org.bstats.charts.AdvancedPie;
import org.bstats.charts.DrilldownPie;
@@ -77,6 +75,7 @@
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.erosion.UnixSocketClientListener;
import org.geysermc.geyser.event.GeyserEventBus;
+import org.geysermc.geyser.event.type.SessionDisconnectEventImpl;
import org.geysermc.geyser.extension.GeyserExtensionManager;
import org.geysermc.geyser.impl.MinecraftVersionImpl;
import org.geysermc.geyser.level.BedrockDimension;
@@ -89,6 +88,7 @@
import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
+import org.geysermc.geyser.session.SessionDisconnectListener;
import org.geysermc.geyser.session.SessionManager;
import org.geysermc.geyser.session.cache.RegistryCache;
import org.geysermc.geyser.skin.FloodgateSkinUploader;
@@ -99,12 +99,10 @@
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.AssetUtils;
import org.geysermc.geyser.util.JsonUtils;
-import org.geysermc.geyser.util.MinecraftAuthLogger;
import org.geysermc.geyser.util.NewsHandler;
import org.geysermc.geyser.util.VersionCheckUtils;
import org.geysermc.geyser.util.WebUtils;
import org.geysermc.geyser.util.metrics.MetricsPlatform;
-import org.geysermc.mcprotocollib.network.tcp.TcpSession;
import java.io.File;
import java.io.FileReader;
@@ -264,6 +262,8 @@ public void initialize() {
// Register our general permissions when possible
eventBus.subscribe(this, GeyserRegisterPermissionsEvent.class, Permissions::register);
+ // Replace disconnect messages whenever necessary
+ eventBus.subscribe(this, SessionDisconnectEventImpl.class, SessionDisconnectListener::onSessionDisconnect);
startInstance();
@@ -414,9 +414,6 @@ private void startInstance() {
logger.warning("The use-direct-connection config option is deprecated. Please reach out to us on Discord if there's a reason it needs to be disabled.");
}
- // Ensure that PacketLib does not create an event loop for handling packets; we'll do that ourselves
- TcpSession.USE_EVENT_LOOP_FOR_PACKETS = false;
-
pendingMicrosoftAuthentication = new PendingMicrosoftAuthentication(config.pendingAuthenticationTimeout());
this.newsHandler = new NewsHandler(BRANCH, this.buildNumber());
@@ -593,52 +590,6 @@ private void startInstance() {
savedAuthChains = new ConcurrentHashMap<>();
Type type = new TypeToken