From 4a9581c5a62d9b84b6f8b55ddce98333e80f204f Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Mon, 13 Jun 2022 13:47:05 -0400
Subject: [PATCH 01/39] Update Spigot adapters for 1.19
---
bootstrap/spigot/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml
index 72b812234..3b44c628f 100644
--- a/bootstrap/spigot/pom.xml
+++ b/bootstrap/spigot/pom.xml
@@ -54,7 +54,7 @@
org.geysermc.geyser.adapters
spigot-all
- 1.4-SNAPSHOT
+ 1.5-SNAPSHOT
me.lucko
From aa097ecdc49e8d5651003776e24558a4907c4ecb Mon Sep 17 00:00:00 2001
From: rtm516
Date: Wed, 15 Jun 2022 00:51:45 +0100
Subject: [PATCH 02/39] Fix java style queries responding incorrectly (#3051)
---
.../java/org/geysermc/geyser/network/QueryPacketHandler.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/core/src/main/java/org/geysermc/geyser/network/QueryPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/QueryPacketHandler.java
index 8b08098f2..0caa6fac7 100644
--- a/core/src/main/java/org/geysermc/geyser/network/QueryPacketHandler.java
+++ b/core/src/main/java/org/geysermc/geyser/network/QueryPacketHandler.java
@@ -91,8 +91,10 @@ public class QueryPacketHandler {
switch (type) {
case HANDSHAKE:
sendToken();
+ break;
case STATISTICS:
sendQueryData();
+ break;
}
}
From ddd22623803d5d2a06b9804caf168f3e17eea931 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Wed, 15 Jun 2022 18:32:27 -0400
Subject: [PATCH 03/39] Custom chat types at login are valid
Fixes https://github.com/GeyserMC/Geyser-Fabric/issues/55
---
core/pom.xml | 2 +-
.../java/org/geysermc/geyser/session/GeyserSession.java | 6 ++++--
.../translator/protocol/java/JavaLoginTranslator.java | 9 +++++----
3 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/core/pom.xml b/core/pom.xml
index df507e892..a14cf1c29 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -155,7 +155,7 @@
com.github.GeyserMC
MCProtocolLib
- bb2b414
+ 54fc9f0
compile
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 c5fe7f2bf..46f5eb1ca 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -80,6 +80,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import lombok.AccessLevel;
@@ -499,7 +501,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
* Stores a map of all statistics sent from the server.
* The server only sends new statistics back to us, so in order to show all statistics we need to cache existing ones.
*/
- private final Map statistics = new HashMap<>();
+ private final Object2IntMap statistics = new Object2IntOpenHashMap<>(0);
/**
* Whether we're expecting statistics to be sent back to us.
@@ -1688,7 +1690,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
*
* @param statistics Updated statistics values
*/
- public void updateStatistics(@NonNull Map statistics) {
+ public void updateStatistics(@Nonnull Object2IntMap statistics) {
if (this.statistics.isEmpty()) {
// Initialize custom statistics to 0, so that they appear in the form
for (CustomStatistic customStatistic : CustomStatistic.values()) {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java
index cd26e53e5..5d259e243 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java
@@ -25,7 +25,7 @@
package org.geysermc.geyser.translator.protocol.java;
-import com.github.steveice10.mc.protocol.data.game.MessageType;
+import com.github.steveice10.mc.protocol.data.game.BuiltinChatType;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLoginPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
@@ -82,14 +82,15 @@ public class JavaLoginTranslator extends PacketTranslator TextPacket.Type.CHAT;
case SYSTEM -> TextPacket.Type.SYSTEM;
case GAME_INFO -> TextPacket.Type.TIP;
default -> TextPacket.Type.RAW;
- };
+ } : TextPacket.Type.RAW;
chatTypes.put(id, new ChatTypeEntry(bedrockType, textDecoration));
}
From 4405989b8131b35c047f03e2953546268a52d528 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Wed, 15 Jun 2022 18:36:55 -0400
Subject: [PATCH 04/39] Fix compiling
---
.../geysermc/geyser/text/ChatTypeEntry.java | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java b/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java
index 800eb6c0f..ad2514e09 100644
--- a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java
+++ b/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java
@@ -25,7 +25,7 @@
package org.geysermc.geyser.text;
-import com.github.steveice10.mc.protocol.data.game.MessageType;
+import com.github.steveice10.mc.protocol.data.game.BuiltinChatType;
import com.nukkitx.protocol.bedrock.packet.TextPacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -45,13 +45,13 @@ public record ChatTypeEntry(@Nonnull TextPacket.Type bedrockChatType, @Nullable
// So the proper way to do this, probably, would be to dump the NBT data from vanilla and load it.
// But, the only way this happens is if a chat message is sent to us before the login packet, which is rare.
// So we'll just make sure chat ends up in the right place.
- chatTypes.put(MessageType.CHAT.ordinal(), CHAT);
- chatTypes.put(MessageType.SYSTEM.ordinal(), SYSTEM);
- chatTypes.put(MessageType.GAME_INFO.ordinal(), TIP);
- chatTypes.put(MessageType.SAY_COMMAND.ordinal(), RAW);
- chatTypes.put(MessageType.MSG_COMMAND.ordinal(), RAW);
- chatTypes.put(MessageType.TEAM_MSG_COMMAND.ordinal(), RAW);
- chatTypes.put(MessageType.EMOTE_COMMAND.ordinal(), RAW);
- chatTypes.put(MessageType.TELLRAW_COMMAND.ordinal(), RAW);
+ chatTypes.put(BuiltinChatType.CHAT.ordinal(), CHAT);
+ chatTypes.put(BuiltinChatType.SYSTEM.ordinal(), SYSTEM);
+ chatTypes.put(BuiltinChatType.GAME_INFO.ordinal(), TIP);
+ chatTypes.put(BuiltinChatType.SAY_COMMAND.ordinal(), RAW);
+ chatTypes.put(BuiltinChatType.MSG_COMMAND.ordinal(), RAW);
+ chatTypes.put(BuiltinChatType.TEAM_MSG_COMMAND.ordinal(), RAW);
+ chatTypes.put(BuiltinChatType.EMOTE_COMMAND.ordinal(), RAW);
+ chatTypes.put(BuiltinChatType.TELLRAW_COMMAND.ordinal(), RAW);
}
}
From 7739e8097e35e82c8f1f8cc1a4b3488316c192c6 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Wed, 15 Jun 2022 19:59:27 -0400
Subject: [PATCH 05/39] Another locale string to pick up on for outdated
servers
---
.../translator/protocol/java/JavaLoginDisconnectTranslator.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java
index 7fca689b0..0315e1611 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java
@@ -50,6 +50,8 @@ public class JavaLoginDisconnectTranslator extends PacketTranslator
Date: Wed, 15 Jun 2022 21:38:10 -0400
Subject: [PATCH 06/39] Map correct glass sounds
Fixes #3049
---
core/src/main/resources/mappings | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings
index 99a1f8070..01350da5d 160000
--- a/core/src/main/resources/mappings
+++ b/core/src/main/resources/mappings
@@ -1 +1 @@
-Subproject commit 99a1f8070e844d059454dacbb6e8b203521eed23
+Subproject commit 01350da5d184ac535cce343d94ceaff6cff20137
From 5e1769d2bda3c37a8a58c4f00104d50299ee9199 Mon Sep 17 00:00:00 2001
From: David Choo
Date: Wed, 15 Jun 2022 22:55:11 -0400
Subject: [PATCH 07/39] Translate goat horns (#3057)
---
.../geyser/registry/type/ItemMappings.java | 4 +-
.../inventory/item/GoatHornTranslator.java | 98 +++++++++++++++++++
2 files changed, 100 insertions(+), 2 deletions(-)
create mode 100644 core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java
diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java
index 3072568f3..ef1a8bc77 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java
@@ -135,9 +135,9 @@ public class ItemMappings {
}
} else {
if (!(mapping.getBedrockData() == data.getDamage() ||
- // Make exceptions for potions, tipped arrows, and firework stars, whose damage values can vary
+ // Make exceptions for potions, tipped arrows, firework stars, and goat horns, whose damage values can vary
(mapping.getJavaIdentifier().endsWith("potion") || mapping.getJavaIdentifier().equals("minecraft:arrow")
- || mapping.getJavaIdentifier().equals("minecraft:firework_star")))) {
+ || mapping.getJavaIdentifier().equals("minecraft:firework_star") || mapping.getJavaIdentifier().equals("minecraft:goat_horn")))) {
continue;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java
new file mode 100644
index 000000000..08e8534af
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.translator.inventory.item;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
+import com.github.steveice10.opennbt.tag.builtin.StringTag;
+import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
+import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.network.MinecraftProtocol;
+import org.geysermc.geyser.registry.Registries;
+import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.registry.type.ItemMappings;
+
+import java.util.Collections;
+import java.util.List;
+
+@ItemRemapper
+public class GoatHornTranslator extends ItemTranslator {
+
+ private static final List INSTRUMENTS = List.of(
+ "ponder_goat_horn",
+ "sing_goat_horn",
+ "seek_goat_horn",
+ "feel_goat_horn",
+ "admire_goat_horn",
+ "call_goat_horn",
+ "yearn_goat_horn",
+ "dream_goat_horn" // Called "Resist" on Bedrock 1.19.0 due to https://bugs.mojang.com/browse/MCPE-155059
+ );
+
+ @Override
+ protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
+ ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings);
+ if (itemStack.getNbt() != null && itemStack.getNbt().get("instrument") instanceof StringTag instrumentTag) {
+ String instrument = instrumentTag.getValue();
+ // Drop the Minecraft namespace if applicable
+ if (instrument.startsWith("minecraft:")) {
+ instrument = instrument.substring("minecraft:".length());
+ }
+
+ int damage = INSTRUMENTS.indexOf(instrument);
+ if (damage == -1) {
+ damage = 0;
+ GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument: " + instrumentTag.getValue());
+ }
+ builder.damage(damage);
+ }
+ return builder;
+ }
+
+ @Override
+ public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
+ ItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
+
+ int damage = itemData.getDamage();
+ if (damage < 0 || damage >= INSTRUMENTS.size()) {
+ GeyserImpl.getInstance().getLogger().debug("Unknown goat horn instrument for damage: " + damage);
+ damage = 0;
+ }
+
+ String instrument = INSTRUMENTS.get(damage);
+ StringTag instrumentTag = new StringTag("instrument", "minecraft:" + instrument);
+ itemStack.getNbt().put(instrumentTag);
+
+ return itemStack;
+ }
+
+ @Override
+ public List getAppliedItems() {
+ return Collections.singletonList(
+ Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
+ .getMapping("minecraft:goat_horn")
+ );
+ }
+}
From 5b67c78785f934c8ff213656c9b619e35bd9da7e Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Thu, 16 Jun 2022 17:14:47 -0400
Subject: [PATCH 08/39] Allow Minecraft locales to be loaded even if offline
---
.../geysermc/geyser/text/MinecraftLocale.java | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java
index 57749f29e..93150942c 100644
--- a/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java
+++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftLocale.java
@@ -126,14 +126,20 @@ public class MinecraftLocale {
// Check the locale isn't already loaded
if (!ASSET_MAP.containsKey("minecraft/lang/" + locale + ".json") && !locale.equals("en_us")) {
- GeyserImpl.getInstance().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.locale.fail.invalid", locale));
+ if (loadLocale(locale)) {
+ GeyserImpl.getInstance().getLogger().debug("Loaded locale locally while not being in asset map: " + locale);
+ } else {
+ GeyserImpl.getInstance().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.locale.fail.invalid", locale));
+ }
return;
}
GeyserImpl.getInstance().getLogger().debug("Downloading and loading locale: " + locale);
downloadLocale(locale);
- loadLocale(locale);
+ if (!loadLocale(locale)) {
+ GeyserImpl.getInstance().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.locale.fail.missing", locale));
+ }
}
/**
@@ -199,7 +205,7 @@ public class MinecraftLocale {
*
* @param locale Locale to load
*/
- private static void loadLocale(String locale) {
+ private static boolean loadLocale(String locale) {
File localeFile = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("locales/" + locale + ".json").toFile();
// Load the locale
@@ -242,8 +248,9 @@ public class MinecraftLocale {
} catch (IOException e) {
throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.locale.fail.file", locale, e.getMessage()));
}
+ return true;
} else {
- GeyserImpl.getInstance().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.locale.fail.missing", locale));
+ return false;
}
}
@@ -300,9 +307,9 @@ public class MinecraftLocale {
* @return Translated string or the original message if it was not found in the given locale
*/
public static String getLocaleString(String messageText, String locale) {
- Map localeStrings = MinecraftLocale.LOCALE_MAPPINGS.get(locale.toLowerCase());
+ Map localeStrings = LOCALE_MAPPINGS.get(locale.toLowerCase(Locale.ROOT));
if (localeStrings == null) {
- localeStrings = MinecraftLocale.LOCALE_MAPPINGS.get(GeyserLocale.getDefaultLocale());
+ localeStrings = LOCALE_MAPPINGS.get(GeyserLocale.getDefaultLocale());
if (localeStrings == null) {
// Don't cause a NPE if the locale is STILL missing
GeyserImpl.getInstance().getLogger().debug("MISSING DEFAULT LOCALE: " + GeyserLocale.getDefaultLocale());
From 71c489b462cbea5fd324cdccd5df39ed0fde44aa Mon Sep 17 00:00:00 2001
From: AJ Ferguson
Date: Fri, 17 Jun 2022 12:25:49 -0400
Subject: [PATCH 09/39] Add missing villager entity events (#3063)
---
.../java/entity/JavaEntityEventTranslator.java | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java
index d82a20a27..3d44ce2fd 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java
@@ -147,6 +147,7 @@ public class JavaEntityEventTranslator extends PacketTranslator
Date: Sat, 18 Jun 2022 03:15:31 +0100
Subject: [PATCH 10/39] Fixed armorstand passenger yOffset (#2976)
---
.../geyser/entity/type/living/ArmorStandEntity.java | 4 ++++
.../main/java/org/geysermc/geyser/util/EntityUtils.java | 9 +++++++++
2 files changed, 13 insertions(+)
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java
index 04e4727d0..75b2ad991 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/ArmorStandEntity.java
@@ -51,6 +51,7 @@ public class ArmorStandEntity extends LivingEntity {
@Getter
private boolean isMarker = false;
private boolean isInvisible = false;
+ @Getter
private boolean isSmall = false;
/**
@@ -74,6 +75,7 @@ public class ArmorStandEntity extends LivingEntity {
* - No armor, no name: false
* - No armor, yes name: true
*/
+ @Getter
private boolean positionRequiresOffset = false;
/**
* Whether we should update the position of this armor stand after metadata updates.
@@ -411,6 +413,8 @@ public class ArmorStandEntity extends LivingEntity {
this.positionRequiresOffset = newValue;
if (positionRequiresOffset) {
this.position = applyOffsetToPosition(position);
+ // Update the passenger offset as armorstand is moving up by roughly 2 blocks
+ updatePassengerOffsets();
} else {
this.position = removeOffsetFromPosition(position);
}
diff --git a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
index 43ccff5e0..d128989a8 100644
--- a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
@@ -187,6 +187,15 @@ public final class EntityUtils {
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
COMMAND_BLOCK_MINECART, BOAT, CHEST_BOAT -> yOffset -= mount.getDefinition().height() * 0.5f;
}
+ if (passenger.getDefinition().entityType() == EntityType.FALLING_BLOCK) {
+ yOffset += 0.5f;
+ }
+ if (mount.getDefinition().entityType() == EntityType.ARMOR_STAND) {
+ ArmorStandEntity armorStand = (ArmorStandEntity) mount;
+ if (armorStand.isPositionRequiresOffset()) {
+ yOffset -= EntityDefinitions.ARMOR_STAND.height() * (armorStand.isSmall() ? 0.55d : 1d);
+ }
+ }
Vector3f offset = Vector3f.from(xOffset, yOffset, zOffset);
passenger.setRiderSeatPosition(offset);
}
From 18f6836c1500372d435ac53fe1fdb9dcf6684fc3 Mon Sep 17 00:00:00 2001
From: AJ Ferguson
Date: Sat, 18 Jun 2022 15:32:51 -0400
Subject: [PATCH 11/39] Set default Warden heartBeatDelay to 40 (#3071)
---
.../geyser/entity/type/living/monster/WardenEntity.java | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WardenEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WardenEntity.java
index 1ca34037c..ff6eed975 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WardenEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/WardenEntity.java
@@ -41,7 +41,7 @@ import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
public class WardenEntity extends MonsterEntity implements Tickable {
- private int heartBeatDelay;
+ private int heartBeatDelay = 40;
private int tickCount;
private int sonicBoomTickDuration;
@@ -50,6 +50,12 @@ public class WardenEntity extends MonsterEntity implements Tickable {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
+ @Override
+ protected void initializeMetadata() {
+ super.initializeMetadata();
+ dirtyMetadata.put(EntityData.HEARTBEAT_INTERVAL_TICKS, heartBeatDelay);
+ }
+
@Override
public void setPose(Pose pose) {
setFlag(EntityFlag.DIGGING, pose == Pose.DIGGING);
From 08241b8bd8a848a4aa4f9e403f7c4a4b924a9174 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Mon, 20 Jun 2022 22:57:49 -0400
Subject: [PATCH 12/39] Spigot: Ensure surprise method/constructor changes
won't stop ping passthrough from working
Fixes #3079 but will need more work
---
.../geyser/platform/spigot/GeyserPaperPingPassthrough.java | 2 +-
.../geyser/platform/spigot/GeyserSpigotPingPassthrough.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
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 cbe063931..637091673 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
@@ -80,7 +80,7 @@ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough
}
return geyserPingInfo;
- } catch (Exception e) {
+ } 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/GeyserSpigotPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPingPassthrough.java
index ae01190c0..63f335fae 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
@@ -56,7 +56,7 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough {
);
Bukkit.getOnlinePlayers().stream().map(Player::getName).forEach(geyserPingInfo.getPlayerList()::add);
return geyserPingInfo;
- } catch (Exception e) {
+ } catch (Exception | LinkageError e) { // LinkageError in the event that method/constructor signatures change
logger.debug("Error while getting Bukkit ping passthrough: " + e);
return null;
}
From 3a5e5fe9f0a3fb8a542a5634443df2500d999883 Mon Sep 17 00:00:00 2001
From: Julian Vennen
Date: Thu, 23 Jun 2022 04:11:58 +0200
Subject: [PATCH 13/39] Update Paper APIs to 1.19; fix ping passthrough for new
Spigot+ builds (#3078)
---
bootstrap/spigot/pom.xml | 4 ++--
.../geyser/platform/spigot/GeyserPaperPingPassthrough.java | 4 ++--
.../geyser/platform/spigot/GeyserSpigotPingPassthrough.java | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml
index 3b44c628f..0101e11ae 100644
--- a/bootstrap/spigot/pom.xml
+++ b/bootstrap/spigot/pom.xml
@@ -36,13 +36,13 @@
io.papermc.paper
paper-api
- 1.18.1-R0.1-SNAPSHOT
+ 1.19-R0.1-SNAPSHOT
provided
io.papermc.paper
paper-mojangapi
- 1.18.1-R0.1-SNAPSHOT
+ 1.19-R0.1-SNAPSHOT
provided
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 637091673..15bc693fb 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
@@ -55,8 +55,8 @@ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough
// We'd rather *not* use deprecations here, but unfortunately any Adventure class would be relocated at
// runtime because we still have to shade in our own Adventure class. For now.
PaperServerListPingEvent event = new PaperServerListPingEvent(new GeyserStatusClient(inetSocketAddress),
- Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers(), Bukkit.getVersion(),
- MinecraftProtocol.getJavaProtocolVersion(), null);
+ Bukkit.getMotd(), Bukkit.shouldSendChatPreviews(), Bukkit.getOnlinePlayers().size(),
+ Bukkit.getMaxPlayers(), Bukkit.getVersion(), MinecraftProtocol.getJavaProtocolVersion(), null);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
// We have to send a ping, so not really sure what else to do here.
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 63f335fae..db5a0a1e1 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
@@ -66,7 +66,7 @@ public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough {
private static class GeyserPingEvent extends ServerListPingEvent {
public GeyserPingEvent(InetAddress address, String motd, int numPlayers, int maxPlayers) {
- super(address, motd, numPlayers, maxPlayers);
+ super(address, motd, Bukkit.shouldSendChatPreviews(), numPlayers, maxPlayers);
}
@Override
From 23923d734f7bd72591853062d03388eda868d898 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Wed, 22 Jun 2022 22:18:32 -0400
Subject: [PATCH 14/39] Ensure old Paper builds can still use ping passthrough
---
.../spigot/GeyserPaperPingPassthrough.java | 17 +++-
.../platform/spigot/GeyserSpigotPlugin.java | 10 ++-
.../platform/spigot/ReflectedNames.java | 90 +++++++++++++++++++
3 files changed, 110 insertions(+), 7 deletions(-)
create mode 100644 bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java
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 15bc693fb..15bd6bde1 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
@@ -35,6 +35,7 @@ import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.lang.reflect.Constructor;
import java.net.InetSocketAddress;
/**
@@ -42,6 +43,8 @@ import java.net.InetSocketAddress;
* applied.
*/
public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough {
+ private static final Constructor OLD_CONSTRUCTOR = ReflectedNames.getOldPaperPingConstructor();
+
private final GeyserSpigotLogger logger;
public GeyserPaperPingPassthrough(GeyserSpigotLogger logger) {
@@ -54,9 +57,17 @@ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough
try {
// We'd rather *not* use deprecations here, but unfortunately any Adventure class would be relocated at
// runtime because we still have to shade in our own Adventure class. For now.
- PaperServerListPingEvent event = new PaperServerListPingEvent(new GeyserStatusClient(inetSocketAddress),
- Bukkit.getMotd(), Bukkit.shouldSendChatPreviews(), Bukkit.getOnlinePlayers().size(),
- Bukkit.getMaxPlayers(), Bukkit.getVersion(), MinecraftProtocol.getJavaProtocolVersion(), null);
+ PaperServerListPingEvent event;
+ if (OLD_CONSTRUCTOR != null) {
+ // Approximately pre-1.19
+ event = OLD_CONSTRUCTOR.newInstance(new GeyserStatusClient(inetSocketAddress),
+ Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(),
+ Bukkit.getMaxPlayers(), Bukkit.getVersion(), MinecraftProtocol.getJavaProtocolVersion(), null);
+ } else {
+ event = new PaperServerListPingEvent(new GeyserStatusClient(inetSocketAddress),
+ Bukkit.getMotd(), Bukkit.shouldSendChatPreviews(), Bukkit.getOnlinePlayers().size(),
+ Bukkit.getMaxPlayers(), Bukkit.getVersion(), MinecraftProtocol.getJavaProtocolVersion(), null);
+ }
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
// We have to send a ping, so not really sure what else to do here.
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
index cee38228c..2ebce7acd 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
@@ -167,14 +167,16 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
if (geyserConfig.isLegacyPingPassthrough()) {
this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
} else {
- try {
- Class.forName("com.destroystokyo.paper.event.server.PaperServerListPingEvent");
+ if (ReflectedNames.checkPaperPingEvent()) {
this.geyserSpigotPingPassthrough = new GeyserPaperPingPassthrough(geyserLogger);
- } catch (ClassNotFoundException e) {
+ } else if (ReflectedNames.newSpigotPingConstructorExists()) {
this.geyserSpigotPingPassthrough = new GeyserSpigotPingPassthrough(geyserLogger);
+ } else {
+ // Can't enable one of the other options
+ this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
}
}
- geyserLogger.debug("Spigot ping passthrough type: " + (this.geyserSpigotPingPassthrough == null ? null : this.geyserSpigotPingPassthrough.getClass()));
+ geyserLogger.info("Spigot ping passthrough type: " + (this.geyserSpigotPingPassthrough == null ? null : this.geyserSpigotPingPassthrough.getClass()));
this.geyserCommandManager = new GeyserSpigotCommandManager(geyser);
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java
new file mode 100644
index 000000000..3185f2d30
--- /dev/null
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/ReflectedNames.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.platform.spigot;
+
+import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
+import com.destroystokyo.paper.network.StatusClient;
+import org.bukkit.event.server.ServerListPingEvent;
+import org.bukkit.util.CachedServerIcon;
+
+import javax.annotation.Nullable;
+import java.lang.reflect.Constructor;
+import java.net.InetAddress;
+
+/**
+ * A utility class for checking on the existence of classes, constructors, fields, methods
+ */
+public final class ReflectedNames {
+
+ static boolean checkPaperPingEvent() {
+ return classExists("com.destroystokyo.paper.event.server.PaperServerListPingEvent");
+ }
+
+ /**
+ * @return if this class name exists
+ */
+ private static boolean classExists(String clazz) {
+ try {
+ Class.forName(clazz);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ static boolean newSpigotPingConstructorExists() {
+ return getConstructor(ServerListPingEvent.class, InetAddress.class, String.class, boolean.class, int.class, int.class) != null;
+ }
+
+ static Constructor getOldPaperPingConstructor() {
+ if (getConstructor(PaperServerListPingEvent.class, StatusClient.class, String.class, boolean.class, int.class,
+ int.class, String.class, int.class, CachedServerIcon.class) != null) {
+ // @NotNull StatusClient client, @NotNull String motd, boolean shouldSendChatPreviews, int numPlayers, int maxPlayers,
+ // @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon
+ // New constructor is present
+ return null;
+ }
+ // @NotNull StatusClient client, @NotNull String motd, int numPlayers, int maxPlayers,
+ // @NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon
+ return getConstructor(PaperServerListPingEvent.class, StatusClient.class, String.class, int.class, int.class,
+ String.class, int.class, CachedServerIcon.class);
+ }
+
+ /**
+ * @return if this class has a constructor with the specified arguments
+ */
+ @Nullable
+ private static Constructor getConstructor(Class clazz, Class>... args) {
+ try {
+ return clazz.getConstructor(args);
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ private ReflectedNames() {
+ }
+}
From 60327339d653510440e5c24371caf0e74dbc82f9 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Thu, 23 Jun 2022 21:24:26 -0400
Subject: [PATCH 15/39] Indicate support for Bedrock 1.19.2
---
.../java/org/geysermc/geyser/network/MinecraftProtocol.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java b/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java
index ba21eeb44..30f5e80fa 100644
--- a/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java
+++ b/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java
@@ -57,7 +57,7 @@ public final class MinecraftProtocol {
static {
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
- .minecraftVersion("1.19.0")
+ .minecraftVersion("1.19.0/1.19.2")
.build());
}
From 9ea22042eb33f6b34d7160fe4a193790d813cffe Mon Sep 17 00:00:00 2001
From: David Choo
Date: Fri, 24 Jun 2022 16:48:28 -0400
Subject: [PATCH 16/39] Fix some item interactions (#3083)
* Remove Bedrock only banner patterns from the creative inventory
* Add sound for tadpole bucket
* Fix lily pad and frogspawn placing on mobile/single stacks
* Workaround? Fix? for bucket usage on mobile
* Simplify math and update position+rotation whenever ServerboundUseItemPacket is sent
* Rotate the player back after using an item and fix glass bottles
* ITEM_USE actionType 1 does not need the rotation fix
Increase delay for look back
* Add some checks
* Prevent buckets and spawn eggs from being unintentionally placed when interacting with special blocks
As of 1.19 Bedrock no longer sends a PlayerActionPacket with action=BLOCK_INTERACT. Bedrock now sends action=ITEM_USE_ON_START before and action=ITEM_USE_ON_STOP after using an item on a block. However, this is not useful as it is sent for all block interactions.
* Fix inventory transactions being rejected after restoreCorrectBlock
The held item's netId is always 0 in the InventoryTransactionPacket.
* Touch ups
* Fix lookAt for different poses and sneaking + cauldron + bucket interactions
Fix boat items being desynced when placing them very close to collision
Fix bottles being desynced when tapping above water
Resend the held item if we do encounter a desync
* Avoid getting blockstate twice and fix comment
* Use generated interaction data
* Fix glass bottles being double filled and phantom water bottles/water buckets
* Don't update the entire inventory on useItem
* Use Geyser's inventory copy for check
* Use ItemTranslator#getBedrockItemMapping to avoid NBT translation
* mappings
Co-authored-by: Camotoy <20743703+Camotoy@users.noreply.github.com>
---
.../inventory/item/StoredItemMappings.java | 8 +
.../geyser/level/block/BlockStateValues.java | 15 +-
.../geyser/registry/BlockRegistries.java | 10 +
.../populator/BlockRegistryPopulator.java | 19 ++
.../populator/ItemRegistryPopulator.java | 3 +
.../geyser/session/GeyserSession.java | 11 +-
.../block/entity/BedrockOnlyBlockEntity.java | 2 +-
...BedrockInventoryTransactionTranslator.java | 204 ++++++++++++++----
.../player/BedrockActionTranslator.java | 8 -
.../player/BedrockMovePlayerTranslator.java | 7 +
.../JavaLevelChunkWithLightTranslator.java | 4 +-
.../BucketSoundInteractionTranslator.java | 5 +-
core/src/main/resources/mappings | 2 +-
13 files changed, 239 insertions(+), 59 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
index 56b6ee7ac..c4375efba 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
@@ -42,16 +42,20 @@ public class StoredItemMappings {
private final ItemMapping banner;
private final ItemMapping barrier;
private final int bowl;
+ private final int bucket;
private final int chest;
private final ItemMapping compass;
private final ItemMapping crossbow;
private final ItemMapping enchantedBook;
private final ItemMapping fishingRod;
private final int flintAndSteel;
+ private final int frogspawn;
+ private final int glassBottle;
private final int goldenApple;
private final int goldIngot;
private final int ironIngot;
private final int lead;
+ private final int lilyPad;
private final ItemMapping milkBucket;
private final int nameTag;
private final ItemMapping powderSnowBucket;
@@ -70,16 +74,20 @@ public class StoredItemMappings {
this.banner = load(itemMappings, "white_banner"); // As of 1.17.10, all banners have the same Bedrock ID
this.barrier = load(itemMappings, "barrier");
this.bowl = load(itemMappings, "bowl").getJavaId();
+ this.bucket = load(itemMappings, "bucket").getBedrockId();
this.chest = load(itemMappings, "chest").getJavaId();
this.compass = load(itemMappings, "compass");
this.crossbow = load(itemMappings, "crossbow");
this.enchantedBook = load(itemMappings, "enchanted_book");
this.fishingRod = load(itemMappings, "fishing_rod");
this.flintAndSteel = load(itemMappings, "flint_and_steel").getJavaId();
+ this.frogspawn = load(itemMappings, "frogspawn").getBedrockId();
+ this.glassBottle = load(itemMappings, "glass_bottle").getBedrockId();
this.goldenApple = load(itemMappings, "golden_apple").getJavaId();
this.goldIngot = load(itemMappings, "gold_ingot").getJavaId();
this.ironIngot = load(itemMappings, "iron_ingot").getJavaId();
this.lead = load(itemMappings, "lead").getJavaId();
+ this.lilyPad = load(itemMappings, "lily_pad").getBedrockId();
this.milkBucket = load(itemMappings, "milk_bucket");
this.nameTag = load(itemMappings, "name_tag").getJavaId();
this.powderSnowBucket = load(itemMappings, "powder_snow_bucket");
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
index a9b3ffedc..adb81761f 100644
--- a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
@@ -44,6 +44,7 @@ import java.util.Locale;
* Used for block entities if the Java block state contains Bedrock block information.
*/
public final class BlockStateValues {
+ private static final IntSet ALL_CAULDRONS = new IntOpenHashSet();
private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap();
private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap();
private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap();
@@ -193,6 +194,9 @@ public final class BlockStateValues {
return;
}
+ if (javaId.contains("cauldron")) {
+ ALL_CAULDRONS.add(javaBlockState);
+ }
if (javaId.contains("_cauldron") && !javaId.contains("water_")) {
NON_WATER_CAULDRONS.add(javaBlockState);
}
@@ -225,10 +229,19 @@ public final class BlockStateValues {
*
* @return if this Java block state is a non-empty non-water cauldron
*/
- public static boolean isCauldron(int state) {
+ public static boolean isNonWaterCauldron(int state) {
return NON_WATER_CAULDRONS.contains(state);
}
+ /**
+ * When using a bucket on a cauldron sending a ServerboundUseItemPacket can result in the liquid being placed.
+ *
+ * @return if this Java block state is a cauldron
+ */
+ public static boolean isCauldron(int state) {
+ return ALL_CAULDRONS.contains(state);
+ }
+
/**
* The block state in Java and Bedrock both contain the conditional bit, however command block block entity tags
* in Bedrock need the conditional information.
diff --git a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
index 609647b2d..586e7d08b 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
@@ -72,6 +72,16 @@ public class BlockRegistries {
*/
public static final SimpleRegistry WATERLOGGED = SimpleRegistry.create(RegistryLoaders.empty(IntOpenHashSet::new));
+ /**
+ * A registry containing all blockstates which are always interactive.
+ */
+ public static final SimpleRegistry INTERACTIVE = SimpleRegistry.create(RegistryLoaders.empty(IntOpenHashSet::new));
+
+ /**
+ * A registry containing all blockstates which are interactive if the player has the may build permission.
+ */
+ public static final SimpleRegistry INTERACTIVE_MAY_BUILD = SimpleRegistry.create(RegistryLoaders.empty(IntOpenHashSet::new));
+
static {
BlockRegistryPopulator.populate();
}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java
index 25528a919..53c3e2310 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java
@@ -26,6 +26,7 @@
package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableMap;
import com.nukkitx.nbt.*;
import com.nukkitx.protocol.bedrock.v527.Bedrock_v527;
@@ -355,6 +356,24 @@ public class BlockRegistryPopulator {
BlockRegistries.CLEAN_JAVA_IDENTIFIERS.set(cleanIdentifiers.toArray(new String[0]));
BLOCKS_JSON = blocksJson;
+
+ JsonNode blockInteractionsJson;
+ try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/interactions.json")) {
+ blockInteractionsJson = GeyserImpl.JSON_MAPPER.readTree(stream);
+ } catch (Exception e) {
+ throw new AssertionError("Unable to load Java block interaction mappings", e);
+ }
+
+ BlockRegistries.INTERACTIVE.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("always_consumes")));
+ BlockRegistries.INTERACTIVE_MAY_BUILD.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("requires_may_build")));
+ }
+
+ private static IntSet toBlockStateSet(ArrayNode node) {
+ IntSet blockStateSet = new IntOpenHashSet(node.size());
+ for (JsonNode javaIdentifier : node) {
+ blockStateSet.add(BlockRegistries.JAVA_IDENTIFIERS.get().getInt(javaIdentifier.textValue()));
+ }
+ return blockStateSet;
}
private static NbtMap buildBedrockState(JsonNode node, int blockStateVersion, BiFunction statesMapper) {
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
index f3d936b2e..eaeefbe56 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
@@ -164,6 +164,9 @@ public class ItemRegistryPopulator {
} else if (identifier.equals("minecraft:empty_map") && damage == 2) {
// Bedrock-only as its own item
continue;
+ } else if (identifier.equals("minecraft:bordure_indented_banner_pattern") || identifier.equals("minecraft:field_masoned_banner_pattern")) {
+ // Bedrock-only banner patterns
+ continue;
}
StartGamePacket.ItemEntry entry = entries.get(identifier);
int id = -1;
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 46f5eb1ca..705ee6416 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -433,11 +433,10 @@ public class GeyserSession implements GeyserConnection, CommandSender {
private long lastInteractionTime;
/**
- * Stores a future interaction to place a bucket. Will be cancelled if the client instead intended to
- * interact with a block.
+ * Stores whether the player intended to place a bucket.
*/
@Setter
- private ScheduledFuture> bucketScheduledFuture;
+ private boolean placedBucket;
/**
* Used to send a movement packet every three seconds if the player hasn't moved. Prevents timeouts when AFK in certain instances.
@@ -524,6 +523,12 @@ public class GeyserSession implements GeyserConnection, CommandSender {
*/
private ScheduledFuture> tickThread = null;
+ /**
+ * Used to return the player to their original rotation after using an item in BedrockInventoryTransactionTranslator
+ */
+ @Setter
+ private ScheduledFuture> lookBackScheduledFuture = null;
+
private MinecraftProtocol protocol;
public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop eventLoop) {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java
index 94760b66c..9ae3300cd 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java
@@ -62,7 +62,7 @@ public interface BedrockOnlyBlockEntity extends RequiresBlockState {
return FlowerPotBlockEntityTranslator.getTag(session, blockState, position);
} else if (PistonBlockEntityTranslator.isBlock(blockState)) {
return PistonBlockEntityTranslator.getTag(blockState, position);
- } else if (BlockStateValues.isCauldron(blockState)) {
+ } else if (BlockStateValues.isNonWaterCauldron(blockState)) {
// As of 1.18.30: this is required to make rendering not look weird on chunk load (lava and snow cauldrons look dim)
return NbtMap.builder()
.putString("id", "Cauldron")
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
index 243b1cede..d9603ae8e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
@@ -33,6 +33,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*;
+import com.nukkitx.math.vector.Vector3d;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
@@ -44,6 +45,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
+import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
@@ -53,6 +55,8 @@ import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.inventory.InventoryTranslator;
+import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.BlockUtils;
@@ -170,6 +174,11 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator
- playerPosition = playerPosition.sub(0, (EntityDefinitions.PLAYER.offset() - 1.27f), 0);
- case SWIMMING,
- FALL_FLYING, // Elytra
- SPIN_ATTACK -> // Trident spin attack
- playerPosition = playerPosition.sub(0, (EntityDefinitions.PLAYER.offset() - 0.4f), 0);
- case SLEEPING ->
- playerPosition = playerPosition.sub(0, (EntityDefinitions.PLAYER.offset() - 0.2f), 0);
- } // else, we don't have to modify the position
+ playerPosition = playerPosition.down(EntityDefinitions.PLAYER.offset() - getEyeHeight(session));
boolean creative = session.getGameMode() == GameMode.CREATIVE;
@@ -255,9 +253,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator {
- ServerboundUseItemPacket itemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getNextSequence());
- session.sendDownstreamPacket(itemPacket);
- }, 5, TimeUnit.MILLISECONDS));
+ if (itemId != session.getItemMappings().getStoredItems().powderSnowBucket().getBedrockId()) {
+ if (!session.isSneaking() && BlockStateValues.isCauldron(blockState)) {
+ // ServerboundUseItemPacket is not sent for cauldrons and buckets
+ return;
}
+ session.setPlacedBucket(useItem(session, packet, blockState));
+ } else {
+ session.setPlacedBucket(true);
}
}
}
@@ -320,6 +316,11 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator {
+ if (isIncorrectHeldItem(session, packet)) {
+ InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), session.getPlayerInventory().getOffsetForHotbar(packet.getHotbarSlot()));
+ break;
+ }
+
// Handled when sneaking
if (session.getPlayerInventory().getItemInHand().getJavaId() == mappings.getStoredItems().shield().getJavaId()) {
break;
@@ -334,6 +335,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator 1) {
+ if (packet.getItemInHand().getId() == session.getItemMappings().getStoredItems().bucket() ||
+ packet.getItemInHand().getId() == session.getItemMappings().getStoredItems().glassBottle()) {
+ // Using a stack of buckets or glass bottles will result in an item being added to the first empty slot.
+ // We need to revert the item in case the interaction fails. The order goes from left to right in the
+ // hotbar. Then left to right and top to bottom in the inventory.
+ for (int i = 0; i < 36; i++) {
+ int slot = i;
+ if (i < 9) {
+ slot = playerInventory.getOffsetForHotbar(slot);
+ }
+ if (playerInventory.getItem(slot).isEmpty()) {
+ InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, playerInventory, slot);
+ break;
+ }
+ }
+ }
+ }
+ // Check if the player is interacting with a block
+ if (!session.isSneaking()) {
+ if (BlockRegistries.INTERACTIVE.get().contains(blockState)) {
+ return false;
+ }
+
+ boolean mayBuild = session.getGameMode() == GameMode.SURVIVAL || session.getGameMode() == GameMode.CREATIVE;
+ if (mayBuild && BlockRegistries.INTERACTIVE_MAY_BUILD.get().contains(blockState)) {
+ return false;
+ }
+ }
+
+ Vector3f target = packet.getBlockPosition().toFloat().add(packet.getClickPosition());
+ lookAt(session, target);
+
+ ServerboundUseItemPacket itemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getNextSequence());
+ session.sendDownstreamPacket(itemPacket);
+ return true;
+ }
+
+ /**
+ * Determine the rotation necessary to activate this transaction.
+ *
+ * The position between the intended click position and the player can be determined with two triangles.
+ * First, we compute the difference of the X and Z coordinates:
+ *
+ * Player position (0, 0)
+ * |
+ * |
+ * |
+ * |_____________ Intended target (-3, 2)
+ *
+ * We then use the Pythagorean Theorem to find the direct line (hypotenuse) on the XZ plane. Finding the angle of the
+ * triangle from there, closest to the player, gives us our yaw rotation value
+ * Then doing the same using the new XZ distance and Y difference, we can find the direct line of sight from the
+ * player to the intended target, and the pitch rotation value. We can then send the necessary packets to update
+ * the player's rotation.
+ *
+ * @param session the Geyser Session
+ * @param target the position to look at
+ */
+ private void lookAt(GeyserSession session, Vector3f target) {
+ // Use the bounding box's position since we need the player's position seen by the Java server
+ Vector3d playerPosition = session.getCollisionManager().getPlayerBoundingBox().getBottomCenter();
+ float xDiff = (float) (target.getX() - playerPosition.getX());
+ float yDiff = (float) (target.getY() - (playerPosition.getY() + getEyeHeight(session)));
+ float zDiff = (float) (target.getZ() - playerPosition.getZ());
+
+ // First triangle on the XZ plane
+ float yaw = (float) -Math.toDegrees(Math.atan2(xDiff, zDiff));
+ // Second triangle on the Y axis using the hypotenuse of the first triangle as a side
+ double xzHypot = Math.sqrt(xDiff * xDiff + zDiff * zDiff);
+ float pitch = (float) -Math.toDegrees(Math.atan2(yDiff, xzHypot));
+
+ SessionPlayerEntity entity = session.getPlayerEntity();
+ ServerboundMovePlayerPosRotPacket returnPacket = new ServerboundMovePlayerPosRotPacket(entity.isOnGround(), playerPosition.getX(), playerPosition.getY(), playerPosition.getZ(), entity.getYaw(), entity.getPitch());
+ // This matches Java edition behavior
+ ServerboundMovePlayerPosRotPacket movementPacket = new ServerboundMovePlayerPosRotPacket(entity.isOnGround(), playerPosition.getX(), playerPosition.getY(), playerPosition.getZ(), yaw, pitch);
+ session.sendDownstreamPacket(movementPacket);
+
+ if (session.getLookBackScheduledFuture() != null) {
+ session.getLookBackScheduledFuture().cancel(false);
+ }
+ if (Math.abs(entity.getYaw() - yaw) > 1f || Math.abs(entity.getPitch() - pitch) > 1f) {
+ session.setLookBackScheduledFuture(session.scheduleInEventLoop(() -> {
+ Vector3d newPlayerPosition = session.getCollisionManager().getPlayerBoundingBox().getBottomCenter();
+ if (!newPlayerPosition.equals(playerPosition) || entity.getYaw() != returnPacket.getYaw() || entity.getPitch() != returnPacket.getPitch()) {
+ // The player moved/rotated so there is no need to change their rotation back
+ return;
+ }
+ session.sendDownstreamPacket(returnPacket);
+ }, 150, TimeUnit.MILLISECONDS));
+ }
+ }
+
+ private float getEyeHeight(GeyserSession session) {
+ return switch (session.getPose()) {
+ case SNEAKING -> 1.27f;
+ case SWIMMING,
+ 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/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
index fe519c329..dd7a1788c 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
@@ -136,14 +136,6 @@ public class BedrockActionTranslator extends PacketTranslator> 8) & 0xF), (packet.getZ() << 4) + ((yzx >> 4) & 0xF)),
javaId
@@ -183,7 +183,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator
Date: Fri, 24 Jun 2022 23:13:35 -0400
Subject: [PATCH 17/39] Forward cooldowns for shields and goats
These are server-controlled as of 1.19. Ender pearls and chorus fruit still appear to be client-controlled.
---
.../inventory/item/StoredItemMappings.java | 2 +
.../java/level/JavaCooldownTranslator.java | 61 +++++++++++++++++++
2 files changed, 63 insertions(+)
create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
index c4375efba..8f9eb415f 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
@@ -50,6 +50,7 @@ public class StoredItemMappings {
private final ItemMapping fishingRod;
private final int flintAndSteel;
private final int frogspawn;
+ private final int goatHorn;
private final int glassBottle;
private final int goldenApple;
private final int goldIngot;
@@ -82,6 +83,7 @@ public class StoredItemMappings {
this.fishingRod = load(itemMappings, "fishing_rod");
this.flintAndSteel = load(itemMappings, "flint_and_steel").getJavaId();
this.frogspawn = load(itemMappings, "frogspawn").getBedrockId();
+ this.goatHorn = load(itemMappings, "goat_horn").getJavaId();
this.glassBottle = load(itemMappings, "glass_bottle").getBedrockId();
this.goldenApple = load(itemMappings, "golden_apple").getJavaId();
this.goldIngot = load(itemMappings, "gold_ingot").getJavaId();
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java
new file mode 100644
index 000000000..f222682ae
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCooldownTranslator.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.translator.protocol.java.level;
+
+import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCooldownPacket;
+import com.nukkitx.protocol.bedrock.packet.PlayerStartItemCooldownPacket;
+import org.geysermc.geyser.inventory.item.StoredItemMappings;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.protocol.PacketTranslator;
+import org.geysermc.geyser.translator.protocol.Translator;
+
+@Translator(packet = ClientboundCooldownPacket.class)
+public class JavaCooldownTranslator extends PacketTranslator {
+
+ @Override
+ public void translate(GeyserSession session, ClientboundCooldownPacket packet) {
+ StoredItemMappings itemMappings = session.getItemMappings().getStoredItems();
+
+ int itemId = packet.getItemId();
+ // Not every item, as of 1.19, appears to be server-driven. Just these two.
+ // Use a map here if it gets too big.
+ String cooldownCategory;
+ if (itemId == itemMappings.goatHorn()) {
+ cooldownCategory = "goat_horn";
+ } else if (itemId == itemMappings.shield().getJavaId()) {
+ cooldownCategory = "shield";
+ } else {
+ cooldownCategory = null;
+ }
+
+ if (cooldownCategory != null) {
+ PlayerStartItemCooldownPacket bedrockPacket = new PlayerStartItemCooldownPacket();
+ bedrockPacket.setItemCategory(cooldownCategory);
+ bedrockPacket.setCooldownDuration(packet.getCooldownTicks());
+ session.sendUpstreamPacket(bedrockPacket);
+ }
+ }
+}
From 00603c5239e8f50beecd6f4087726ea6429b3843 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Sun, 26 Jun 2022 18:45:47 -0400
Subject: [PATCH 18/39] Fix creeper primed sound
---
core/src/main/resources/mappings | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings
index 244efb7ea..05009c86f 160000
--- a/core/src/main/resources/mappings
+++ b/core/src/main/resources/mappings
@@ -1 +1 @@
-Subproject commit 244efb7ea277a431c4e9c5b586eb401b691ed888
+Subproject commit 05009c86fb06ecab0ea4691ec96fc24fdc6c1ee5
From 5d29bda7eb77976d6c4d4ea3e3a54f46b50d632f Mon Sep 17 00:00:00 2001
From: David Choo
Date: Sun, 26 Jun 2022 19:12:43 -0400
Subject: [PATCH 19/39] Fix incorrect patterns in loom and DecoderException in
beacons (#3090)
* Fix DecoderException when setting beacon effect
* Fix incorrect patterns applied in loom and remove old version stuff
---
.../inventory/BeaconInventoryTranslator.java | 2 +-
.../inventory/LoomInventoryTranslator.java | 19 ++++++-------------
2 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java
index 54dc533c6..4dac5e86f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java
@@ -119,7 +119,7 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator
}
private OptionalInt toJava(int effectChoice) {
- return effectChoice == -1 ? OptionalInt.empty() : OptionalInt.of(effectChoice);
+ return effectChoice == 0 ? OptionalInt.empty() : OptionalInt.of(effectChoice);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
index a7b736d72..5a237b72a 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
@@ -60,7 +60,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
static {
// Added from left-to-right then up-to-down in the order Java presents it
- int index = 1;
+ int index = 0;
PATTERN_TO_INDEX.put("bl", index++);
PATTERN_TO_INDEX.put("br", index++);
PATTERN_TO_INDEX.put("tl", index++);
@@ -119,15 +119,16 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
@Override
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) {
// If the LOOM_MATERIAL slot is not empty, we are crafting a pattern that does not come from an item
- // Remove the CRAFT_NON_IMPLEMENTED_DEPRECATED when 1.17.30 is dropped
- return (action.getType() == StackRequestActionType.CRAFT_NON_IMPLEMENTED_DEPRECATED || action.getType() == StackRequestActionType.CRAFT_LOOM)
- && inventory.getItem(2).isEmpty();
+ return action.getType() == StackRequestActionType.CRAFT_LOOM && inventory.getItem(2).isEmpty();
}
@Override
public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
StackRequestActionData headerData = request.getActions()[0];
StackRequestActionData data = request.getActions()[1];
+ if (!(headerData instanceof CraftLoomStackRequestActionData)) {
+ return rejectRequest(request);
+ }
if (!(data instanceof CraftResultsDeprecatedStackRequestActionData craftData)) {
return rejectRequest(request);
}
@@ -136,15 +137,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
List newBlockEntityTag = craftData.getResultItems()[0].getTag().getList("Patterns", NbtType.COMPOUND);
// Get the pattern that the Bedrock client requests - the last pattern in the Patterns list
NbtMap pattern = newBlockEntityTag.get(newBlockEntityTag.size() - 1);
- String bedrockPattern;
-
- if (headerData instanceof CraftLoomStackRequestActionData loomData) {
- // Prioritize this if on 1.17.40
- // Remove the below if statement when 1.17.30 is dropped
- bedrockPattern = loomData.getPatternId();
- } else {
- bedrockPattern = pattern.getString("Pattern");
- }
+ String bedrockPattern = ((CraftLoomStackRequestActionData) headerData).getPatternId();
// Get the Java index of this pattern
int index = PATTERN_TO_INDEX.getOrDefault(bedrockPattern, -1);
From f62484b93e3ca5af5c6b34573b6ad13c70ba93a0 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Wed, 29 Jun 2022 16:42:30 -0400
Subject: [PATCH 20/39] Update Adventure to fix click event deserialization
Fixes #3054
---
core/pom.xml | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/core/pom.xml b/core/pom.xml
index a14cf1c29..408a2b761 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -11,12 +11,20 @@
core
- 4.9.3
+ 4.12.0-20220629.025215-9
8.5.2
2.13.2
4.1.66.Final
+
+
+
+ sonatype-s01
+ https://s01.oss.sonatype.org/content/repositories/snapshots/
+
+
+
org.geysermc
@@ -166,6 +174,11 @@
com.github.GeyserMC
mcauthlib
+
+
+ net.kyori
+ *
+
@@ -245,6 +258,19 @@
${adventure.version}
compile
+
+
+ net.kyori
+ adventure-text-serializer-gson
+ ${adventure.version}
+ compile
+
+
+ net.kyori
+ adventure-text-serializer-gson-legacy-impl
+ ${adventure.version}
+ compile
+
junit
From b2b544c3a8c1d82d8ee0e257463c735cbd9b72fb Mon Sep 17 00:00:00 2001
From: DJelly4K <68630033+DJelly4K@users.noreply.github.com>
Date: Thu, 30 Jun 2022 10:34:01 +0800
Subject: [PATCH 21/39] Jump to new wiki (#3100)
---
.github/ISSUE_TEMPLATE/config.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 862e9c0be..7bd9a19d0 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,10 +1,10 @@
blank_issues_enabled: false
contact_links:
- name: Common Issues
- url: https://github.com/GeyserMC/Geyser/wiki/Common-Issues
+ url: https://wiki.geysermc.org/geyser/common-issues
about: Check the common issues to see if you are not alone with that issue and see how you can fix them.
- name: Frequently Asked Questions
- url: https://github.com/GeyserMC/Geyser/wiki/FAQ
+ url: https://wiki.geysermc.org/geyser/faq
about: Look at the FAQ page for answers to frequently asked questions.
- name: Get help on the GeyserMC Discord server
url: https://discord.gg/geysermc
From 13e8b59ed086031f70b4913caaeb581e0ec86066 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Thu, 30 Jun 2022 16:53:55 -0400
Subject: [PATCH 22/39] Quick fix for NPE in SystemChatTranslator
This won't matter in 1.19.1 so.
---
.../translator/protocol/java/JavaSystemChatTranslator.java | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java
index 2d69c363d..2bc0d1442 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.java;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket;
import com.nukkitx.protocol.bedrock.packet.TextPacket;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.text.ChatTypeEntry;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.translator.text.MessageTranslator;
@@ -37,11 +38,15 @@ public class JavaSystemChatTranslator extends PacketTranslator
Date: Thu, 30 Jun 2022 17:40:30 -0400
Subject: [PATCH 23/39] Fix IronGolem cracked texture and sound (#3103)
* Update mappings submodule
* Set IronGolem maxHealth to 100 by default
Fixes cracked texture on vanilla servers
* Add detail to comment
---
.../geysermc/geyser/entity/type/living/IronGolemEntity.java | 3 +++
core/src/main/resources/mappings | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
index e5cbb2f89..52e4a6f2f 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/IronGolemEntity.java
@@ -45,6 +45,9 @@ public class IronGolemEntity extends GolemEntity {
setFlag(EntityFlag.BRIBED, true);
// Required, or else the overlay is black
dirtyMetadata.put(EntityData.COLOR_2, (byte) 0);
+ // Default max health. Ensures correct cracked texture is used
+ // Bug reproducible in 1.19.0 JE vanilla/fabric when spawning a new iron golem
+ maxHealth = 100f;
}
@Nonnull
diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings
index 05009c86f..27e9c97df 160000
--- a/core/src/main/resources/mappings
+++ b/core/src/main/resources/mappings
@@ -1 +1 @@
-Subproject commit 05009c86fb06ecab0ea4691ec96fc24fdc6c1ee5
+Subproject commit 27e9c97df1e9a2f9d1f05359a29181e6ee0810d2
From dc810f1d3945591aa7038785b506f8501121d7bb Mon Sep 17 00:00:00 2001
From: David Choo
Date: Sat, 2 Jul 2022 21:17:14 -0400
Subject: [PATCH 24/39] Fix break time while submerged in water (#3110)
* Fix break time while submerged in water
* Review stuff
* LAYERS -> LEVELS
---
.../geyser/entity/type/FishingHookEntity.java | 16 ++--------
.../geyser/level/block/BlockStateValues.java | 27 ++++++++++++++++-
.../level/physics/CollisionManager.java | 13 +++++++++
.../geyser/session/GeyserSession.java | 12 ++++++++
...BedrockInventoryTransactionTranslator.java | 15 ++--------
.../org/geysermc/geyser/util/BlockUtils.java | 29 +++++++------------
6 files changed, 67 insertions(+), 45 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
index 75bdd9021..65662bbe4 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
@@ -99,19 +99,9 @@ public class FishingHookEntity extends ThrowableEntity {
}
}
- int waterLevel = BlockStateValues.getWaterLevel(blockID);
- if (BlockRegistries.WATERLOGGED.get().contains(blockID)) {
- waterLevel = 0;
- }
- if (waterLevel >= 0) {
- double waterMaxY = iter.getY() + 1 - (waterLevel + 1) / 9.0;
- // Falling water is a full block
- if (waterLevel >= 8) {
- waterMaxY = iter.getY() + 1;
- }
- if (position.getY() <= waterMaxY) {
- touchingWater = true;
- }
+ double waterHeight = BlockStateValues.getWaterHeight(blockID);
+ if (waterHeight != -1 && position.getY() <= (iter.getY() + waterHeight)) {
+ touchingWater = true;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
index adb81761f..e4772df80 100644
--- a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
@@ -77,6 +77,8 @@ public final class BlockStateValues {
public static int JAVA_SPAWNER_ID;
public static int JAVA_WATER_ID;
+ public static final int NUM_WATER_LEVELS = 9;
+
/**
* Determines if the block state contains Bedrock block information
*
@@ -449,7 +451,6 @@ public final class BlockStateValues {
/**
* Get the level of water from the block state.
- * This is used in FishingHookEntity to create splash sounds when the hook hits the water.
*
* @param state BlockState of the block
* @return The water level or -1 if the block isn't water
@@ -458,6 +459,30 @@ public final class BlockStateValues {
return WATER_LEVEL.getOrDefault(state, -1);
}
+ /**
+ * Get the height of water from the block state
+ * This is used in FishingHookEntity to create splash sounds when the hook hits the water. In addition,
+ * CollisionManager uses this to determine if the player's eyes are in water.
+ *
+ * @param state BlockState of the block
+ * @return The water height or -1 if the block does not contain water
+ */
+ public static double getWaterHeight(int state) {
+ int waterLevel = BlockStateValues.getWaterLevel(state);
+ if (BlockRegistries.WATERLOGGED.get().contains(state)) {
+ waterLevel = 0;
+ }
+ if (waterLevel >= 0) {
+ double waterHeight = 1 - (waterLevel + 1) / ((double) NUM_WATER_LEVELS);
+ // Falling water is a full block
+ if (waterLevel >= 8) {
+ waterHeight = 1;
+ }
+ return waterHeight;
+ }
+ return -1;
+ }
+
/**
* Get the slipperiness of a block.
* This is used in ItemEntity to calculate the friction on an item as it slides across the ground
diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
index 2617b2750..a91c2b083 100644
--- a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
+++ b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
@@ -25,6 +25,7 @@
package org.geysermc.geyser.level.physics;
+import com.nukkitx.math.GenericMath;
import com.nukkitx.math.vector.Vector3d;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
@@ -405,6 +406,18 @@ public class CollisionManager {
return session.getGeyser().getWorldManager().getBlockAt(session, session.getPlayerEntity().getPosition().toInt()) == BlockStateValues.JAVA_WATER_ID;
}
+ public boolean isWaterInEyes() {
+ double eyeX = playerBoundingBox.getMiddleX();
+ double eyeY = playerBoundingBox.getMiddleY() - playerBoundingBox.getSizeY() / 2d + session.getEyeHeight();
+ double eyeZ = playerBoundingBox.getMiddleZ();
+
+ eyeY -= 1 / ((double) BlockStateValues.NUM_WATER_LEVELS); // Subtract the height of one water layer
+ int blockID = session.getGeyser().getWorldManager().getBlockAt(session, GenericMath.floor(eyeX), GenericMath.floor(eyeY), GenericMath.floor(eyeZ));
+ double waterHeight = BlockStateValues.getWaterHeight(blockID);
+
+ return waterHeight != -1 && eyeY < (Math.floor(eyeY) + waterHeight);
+ }
+
/**
* Updates scaffolding entity flags
* Scaffolding needs to be checked per-move since it's a flag in Bedrock but Java does it client-side
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 705ee6416..93ef62c56 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -100,6 +100,7 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.command.CommandSender;
import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption;
+import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
@@ -1767,6 +1768,17 @@ public class GeyserSession implements GeyserConnection, CommandSender {
sendUpstreamPacket(packet);
}
+ public float getEyeHeight() {
+ return switch (pose) {
+ case SNEAKING -> 1.27f;
+ case SWIMMING,
+ FALL_FLYING, // Elytra
+ SPIN_ATTACK -> 0.4f; // Trident spin attack
+ case SLEEPING -> 0.2f;
+ default -> EntityDefinitions.PLAYER.offset();
+ };
+ }
+
public MinecraftCodecHelper getCodecHelper() {
return (MinecraftCodecHelper) this.downstream.getCodecHelper();
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
index d9603ae8e..1adf123bf 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
@@ -201,7 +201,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator 1.27f;
- case SWIMMING,
- 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/util/BlockUtils.java b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java
index 7059c9a8b..c0d484919 100644
--- a/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/BlockUtils.java
@@ -36,6 +36,8 @@ import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.collision.BlockCollision;
+import javax.annotation.Nullable;
+
public final class BlockUtils {
private static boolean correctTool(GeyserSession session, BlockMapping blockMapping, String itemToolType) {
@@ -101,7 +103,7 @@ public final class BlockUtils {
// https://minecraft.gamepedia.com/Breaking
private static double calculateBreakTime(double blockHardness, String toolTier, boolean canHarvestWithHand, boolean correctTool, boolean canTierMineBlock,
String toolType, boolean isShearsEffective, int toolEfficiencyLevel, int hasteLevel, int miningFatigueLevel,
- boolean insideOfWaterWithoutAquaAffinity, boolean outOfWaterButNotOnGround, boolean insideWaterAndNotOnGround) {
+ boolean insideOfWaterWithoutAquaAffinity, boolean onGround) {
double baseTime = (((correctTool && canTierMineBlock) || canHarvestWithHand) ? 1.5 : 5.0) * blockHardness;
double speed = 1.0 / baseTime;
@@ -129,12 +131,11 @@ public final class BlockUtils {
}
if (insideOfWaterWithoutAquaAffinity) speed *= 0.2;
- if (outOfWaterButNotOnGround) speed *= 0.2;
- if (insideWaterAndNotOnGround) speed *= 0.2;
+ if (!onGround) speed *= 0.2;
return 1.0 / speed;
}
- public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemMapping item, CompoundTag nbtData, boolean isSessionPlayer) {
+ public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemMapping item, @Nullable CompoundTag nbtData, boolean isSessionPlayer) {
boolean isShearsEffective = session.getTagCache().isShearsEffective(blockMapping); //TODO called twice
boolean canHarvestWithHand = blockMapping.isCanBreakWithHand();
String toolType = "";
@@ -154,36 +155,28 @@ public final class BlockUtils {
if (!isSessionPlayer) {
// Another entity is currently mining; we have all the information we know
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
- toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false,
- false, false);
+ toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false, true);
}
hasteLevel = Math.max(session.getEffectCache().getHaste(), session.getEffectCache().getConduitPower());
miningFatigueLevel = session.getEffectCache().getMiningFatigue();
- boolean isInWater = session.getCollisionManager().isPlayerInWater();
-
- boolean insideOfWaterWithoutAquaAffinity = isInWater &&
+ boolean waterInEyes = session.getCollisionManager().isWaterInEyes();
+ boolean insideOfWaterWithoutAquaAffinity = waterInEyes &&
ItemUtils.getEnchantmentLevel(session.getPlayerInventory().getItem(5).getNbt(), "minecraft:aqua_affinity") < 1;
- boolean outOfWaterButNotOnGround = (!isInWater) && (!session.getPlayerEntity().isOnGround());
- boolean insideWaterNotOnGround = isInWater && !session.getPlayerEntity().isOnGround();
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
- toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity,
- outOfWaterButNotOnGround, insideWaterNotOnGround);
+ toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, session.getPlayerEntity().isOnGround());
}
public static double getSessionBreakTime(GeyserSession session, BlockMapping blockMapping) {
PlayerInventory inventory = session.getPlayerInventory();
GeyserItemStack item = inventory.getItemInHand();
- ItemMapping mapping;
- CompoundTag nbtData;
+ ItemMapping mapping = ItemMapping.AIR;
+ CompoundTag nbtData = null;
if (item != null) {
mapping = item.getMapping(session);
nbtData = item.getNbt();
- } else {
- mapping = ItemMapping.AIR;
- nbtData = new CompoundTag("");
}
return getBreakTime(session, blockMapping, mapping, nbtData, true);
}
From ab4800c4f2b814fa13af18cdb3b706d3c1534277 Mon Sep 17 00:00:00 2001
From: Yashar <47281991+Yashar256@users.noreply.github.com>
Date: Fri, 8 Jul 2022 16:01:00 -0700
Subject: [PATCH 25/39] Fix login screen not closing (#3122)
---
.../org/geysermc/geyser/util/LoginEncryptionUtils.java | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java
index ea1ff770a..372d40258 100644
--- a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java
@@ -310,7 +310,14 @@ public class LoginEncryptionUtils {
.label("geyser.auth.login.form.details.desc")
.input("geyser.auth.login.form.details.email", "account@geysermc.org", "")
.input("geyser.auth.login.form.details.pass", "123456", "")
- .closedOrInvalidResultHandler(() -> buildAndShowLoginDetailsWindow(session))
+ .invalidResultHandler(() -> buildAndShowLoginDetailsWindow(session))
+ .closedResultHandler(() -> {
+ if (session.isMicrosoftAccount()) {
+ buildAndShowMicrosoftAuthenticationWindow(session);
+ } else {
+ buildAndShowLoginWindow(session);
+ }
+ })
.validResultHandler((response) -> session.authenticate(response.next(), response.next())));
}
From 2ce7ff850ae96327e7a1fdd23f1457ac5b104789 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Sat, 9 Jul 2022 23:02:19 -0400
Subject: [PATCH 26/39] Support the 1.19.0 Java block prediction/ack system
---
.../command/defaults/OffhandCommand.java | 2 +-
.../geyser/session/GeyserSession.java | 12 ++-
.../geyser/session/cache/TagCache.java | 14 +++-
.../geyser/session/cache/WorldCache.java | 80 +++++++++++++++++++
...BedrockInventoryTransactionTranslator.java | 29 +++++--
.../BedrockLecternUpdateTranslator.java | 2 +-
.../BedrockMobEquipmentTranslator.java | 2 +-
.../player/BedrockActionTranslator.java | 20 +++--
.../entity/player/BedrockEmoteTranslator.java | 2 +-
.../player/JavaBlockChangedAckTranslator.java | 2 +-
.../org/geysermc/geyser/util/ChunkUtils.java | 13 ++-
11 files changed, 145 insertions(+), 33 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/OffhandCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/OffhandCommand.java
index b0d0e1ce6..48afd21fe 100644
--- a/core/src/main/java/org/geysermc/geyser/command/defaults/OffhandCommand.java
+++ b/core/src/main/java/org/geysermc/geyser/command/defaults/OffhandCommand.java
@@ -47,7 +47,7 @@ public class OffhandCommand extends GeyserCommand {
}
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, Vector3i.ZERO,
- Direction.DOWN, session.getNextSequence());
+ Direction.DOWN, session.getWorldCache().nextPredictionSequence());
session.sendDownstreamPacket(releaseItemPacket);
}
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 93ef62c56..0a916fbf5 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -401,6 +401,8 @@ public class GeyserSession implements GeyserConnection, CommandSender {
*/
@Setter
private boolean emulatePost1_16Logic = true;
+ @Setter
+ private boolean emulatePost1_18Logic = true;
/**
* The current attack speed of the player. Used for sending proper cooldown timings.
@@ -1278,9 +1280,9 @@ public class GeyserSession implements GeyserConnection, CommandSender {
ServerboundUseItemPacket useItemPacket;
if (playerInventory.getItemInHand().getJavaId() == shield.getJavaId()) {
- useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, getNextSequence());
+ useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, worldCache.nextPredictionSequence());
} else if (playerInventory.getOffhand().getJavaId() == shield.getJavaId()) {
- useItemPacket = new ServerboundUseItemPacket(Hand.OFF_HAND, getNextSequence());
+ useItemPacket = new ServerboundUseItemPacket(Hand.OFF_HAND, worldCache.nextPredictionSequence());
} else {
// No blocking
return false;
@@ -1309,7 +1311,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
private boolean disableBlocking() {
if (playerEntity.getFlag(EntityFlag.BLOCKING)) {
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM,
- Vector3i.ZERO, Direction.DOWN, getNextSequence());
+ Vector3i.ZERO, Direction.DOWN, worldCache.nextPredictionSequence());
sendDownstreamPacket(releaseItemPacket);
playerEntity.setFlag(EntityFlag.BLOCKING, false);
return true;
@@ -1687,10 +1689,6 @@ public class GeyserSession implements GeyserConnection, CommandSender {
sendDownstreamPacket(clientSettingsPacket);
}
- public int getNextSequence() {
- return 0;
- }
-
/**
* Used for updating statistic values since we only get changes from the server
*
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
index d46a39616..7db01e655 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.session.cache;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateTagsPacket;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntLists;
+import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.registry.type.ItemMapping;
@@ -82,6 +83,15 @@ public class TagCache {
this.requiresIronTool = IntList.of(blockTags.get("minecraft:needs_iron_tool"));
this.requiresDiamondTool = IntList.of(blockTags.get("minecraft:needs_diamond_tool"));
+ // Hack btw
+ GeyserLogger logger = session.getGeyser().getLogger();
+ int[] convertableToMud = blockTags.get("minecraft:convertable_to_mud");
+ boolean emulatePost1_18Logic = convertableToMud != null && convertableToMud.length != 0;
+ session.setEmulatePost1_18Logic(emulatePost1_18Logic);
+ if (logger.isDebug()) {
+ logger.debug("Emulating post 1.18 block predication logic for " + session.name() + "? " + emulatePost1_18Logic);
+ }
+
Map itemTags = packet.getTags().get("minecraft:item");
this.axolotlTemptItems = IntList.of(itemTags.get("minecraft:axolotl_tempt_items"));
this.fishes = IntList.of(itemTags.get("minecraft:fishes"));
@@ -93,8 +103,8 @@ public class TagCache {
// Hack btw
boolean emulatePost1_14Logic = itemTags.get("minecraft:signs").length > 1;
session.setEmulatePost1_14Logic(emulatePost1_14Logic);
- if (session.getGeyser().getLogger().isDebug()) {
- session.getGeyser().getLogger().debug("Emulating post 1.14 villager logic for " + session.name() + "? " + emulatePost1_14Logic);
+ if (logger.isDebug()) {
+ logger.debug("Emulating post 1.14 villager logic for " + session.name() + "? " + emulatePost1_14Logic);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java
index 17679ad3e..239f5c865 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java
@@ -26,12 +26,18 @@
package org.geysermc.geyser.session.cache;
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
+import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.packet.SetTitlePacket;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.geyser.scoreboard.Scoreboard;
import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.util.ChunkUtils;
+
+import java.util.Iterator;
+import java.util.Map;
public final class WorldCache {
private final GeyserSession session;
@@ -51,6 +57,9 @@ public final class WorldCache {
private int trueTitleStayTime;
private int trueTitleFadeOutTime;
+ private int currentSequence;
+ private final Map unverifiedPredictions = new Object2ObjectOpenHashMap<>(1);
+
public WorldCache(GeyserSession session) {
this.session = session;
this.scoreboard = new Scoreboard(session);
@@ -121,4 +130,75 @@ public final class WorldCache {
forceSyncCorrectTitleTimes();
}
}
+
+ /* Code to support the prediction structure introduced in Java Edition 1.19.0
+ Blocks can be rolled back if invalid, but this requires some client-side information storage. */
+
+ public int nextPredictionSequence() {
+ return ++currentSequence;
+ }
+
+ /**
+ * Stores a record of a block at a certain position to rollback in the event it is incorrect.
+ */
+ public void addServerCorrectBlockState(Vector3i position, int blockState) {
+ if (session.isEmulatePost1_18Logic()) {
+ // Cheap hack
+ // On non-Bukkit platforms, ViaVersion will always confirm the sequence before the block is updated,
+ // meaning we'd send two block updates after (ChunkUtils.updateBlockClientSide in endPredictionsUpTo
+ // and the packet updating from the client)
+ this.unverifiedPredictions.compute(position, ($, serverVerifiedState) -> serverVerifiedState == null
+ ? new ServerVerifiedState(currentSequence, blockState) : serverVerifiedState.setData(currentSequence, blockState));
+ }
+ }
+
+ public void updateServerCorrectBlockState(Vector3i position) {
+ if (this.unverifiedPredictions.isEmpty()) {
+ return;
+ }
+
+ this.unverifiedPredictions.remove(position);
+ }
+
+ public void endPredictionsUpTo(int sequence) {
+ if (this.unverifiedPredictions.isEmpty()) {
+ return;
+ }
+
+ Iterator> it = this.unverifiedPredictions.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = it.next();
+ ServerVerifiedState serverVerifiedState = entry.getValue();
+ if (serverVerifiedState.sequence <= sequence) {
+ // This block may be out of sync with the server
+ // In 1.19.0 Java, you can verify this by trying to mine in spawn protection
+ ChunkUtils.updateBlockClientSide(session, serverVerifiedState.blockState, entry.getKey());
+ it.remove();
+ }
+ }
+ }
+
+ private static class ServerVerifiedState {
+ private int sequence;
+ private int blockState;
+
+ ServerVerifiedState(int sequence, int blockState) {
+ this.sequence = sequence;
+ this.blockState = blockState;
+ }
+
+ ServerVerifiedState setData(int sequence, int blockState) {
+ this.sequence = sequence;
+ this.blockState = blockState;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "ServerVerifiedState{" +
+ "sequence=" + sequence +
+ ", blockState=" + blockState +
+ '}';
+ }
+ }
}
\ No newline at end of file
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
index 1adf123bf..24c046ef2 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
@@ -38,7 +38,10 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.data.inventory.*;
-import com.nukkitx.protocol.bedrock.packet.*;
+import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
+import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
+import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
+import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -126,7 +129,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator legacySlots = packet.getLegacySlots();
@@ -406,12 +409,22 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator session.sendDownstreamPacket(new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getNextSequence())),
+ session.scheduleInEventLoop(() -> session.sendDownstreamPacket(new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getWorldCache().nextPredictionSequence())),
50, TimeUnit.MILLISECONDS);
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
index dd7a1788c..5001fc2d2 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
@@ -41,7 +41,6 @@ import com.nukkitx.protocol.bedrock.packet.*;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
-import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
@@ -129,7 +128,7 @@ public class BedrockActionTranslator extends PacketTranslator {
if (session.getGeyser().getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.DISABLED) {
// Activate the workaround - we should trigger the offhand now
ServerboundPlayerActionPacket swapHandsPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, Vector3i.ZERO,
- Direction.DOWN, session.getNextSequence());
+ Direction.DOWN, session.getWorldCache().nextPredictionSequence());
session.sendDownstreamPacket(swapHandsPacket);
if (session.getGeyser().getConfig().getEmoteOffhandWorkaround() == EmoteOffhandWorkaroundOption.NO_EMOTES) {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaBlockChangedAckTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaBlockChangedAckTranslator.java
index 6afb0b3ef..523d0fdc4 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaBlockChangedAckTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaBlockChangedAckTranslator.java
@@ -35,6 +35,6 @@ public class JavaBlockChangedAckTranslator extends PacketTranslator
Date: Sun, 10 Jul 2022 13:33:39 -0400
Subject: [PATCH 27/39] Initial support for 1.19.10 Bedrock
---
core/pom.xml | 6 +-
.../entity/type/player/PlayerEntity.java | 16 ++++-
.../type/player/SessionPlayerEntity.java | 5 +-
.../entity/type/player/SkullPlayerEntity.java | 1 +
.../geyser/network/MinecraftProtocol.java | 13 +++-
.../geyser/session/GeyserSession.java | 71 +++++++++++++++++--
.../player/JavaPlayerAbilitiesTranslator.java | 2 +
.../JavaPlayerCombatKillTranslator.java | 50 +++++++++++++
8 files changed, 151 insertions(+), 13 deletions(-)
create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java
diff --git a/core/pom.xml b/core/pom.xml
index 408a2b761..e264531a9 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -128,8 +128,8 @@
com.github.CloudburstMC.Protocol
- bedrock-v527
- 977a9a1
+ bedrock-v534
+ a78a64b
compile
@@ -145,7 +145,7 @@
com.nukkitx.network
raknet
- 1.6.28-20211202.034102-5
+ 1.6.28-20220125.214016-6
compile
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java
index 6f2958ffd..8e600b1a8 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java
@@ -35,9 +35,7 @@ import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
-import com.nukkitx.protocol.bedrock.data.AttributeData;
-import com.nukkitx.protocol.bedrock.data.GameType;
-import com.nukkitx.protocol.bedrock.data.PlayerPermission;
+import com.nukkitx.protocol.bedrock.data.*;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
@@ -59,6 +57,7 @@ import org.geysermc.geyser.translator.text.MessageTranslator;
import javax.annotation.Nullable;
import java.util.Collections;
+import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@@ -66,6 +65,16 @@ import java.util.concurrent.TimeUnit;
@Getter @Setter
public class PlayerEntity extends LivingEntity {
public static final float SNEAKING_POSE_HEIGHT = 1.5f;
+ protected static final List BASE_ABILITY_LAYER;
+
+ static {
+ AbilityLayer abilityLayer = new AbilityLayer();
+ abilityLayer.setLayerType(AbilityLayer.Type.BASE);
+ Ability[] abilities = Ability.values();
+ Collections.addAll(abilityLayer.getAbilitiesSet(), abilities); // Apparently all the abilities you're working with
+ Collections.addAll(abilityLayer.getAbilityValues(), abilities); // Apparently all the abilities the player can work with
+ BASE_ABILITY_LAYER = Collections.singletonList(abilityLayer);
+ }
private String username;
private boolean playerList = true; // Player is in the player list
@@ -127,6 +136,7 @@ public class PlayerEntity extends LivingEntity {
addPlayerPacket.setDeviceId("");
addPlayerPacket.setPlatformChatId("");
addPlayerPacket.setGameType(GameType.SURVIVAL); //TODO
+ addPlayerPacket.setAbilityLayers(BASE_ABILITY_LAYER); // Recommended to be added since 1.19.10, but only needed here for permissions viewing
addPlayerPacket.getMetadata().putFlags(flags);
dirtyMetadata.apply(addPlayerPacket.getMetadata());
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
index d4b703c40..f16f46e2e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
@@ -44,7 +44,10 @@ import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils;
import javax.annotation.Nullable;
-import java.util.*;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
/**
* The entity class specifically for a {@link GeyserSession}'s player.
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
index 6c15a4d3e..176d171de 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
@@ -81,6 +81,7 @@ public class SkullPlayerEntity extends PlayerEntity {
addPlayerPacket.setDeviceId("");
addPlayerPacket.setPlatformChatId("");
addPlayerPacket.setGameType(GameType.SURVIVAL);
+ addPlayerPacket.setAbilityLayers(BASE_ABILITY_LAYER);
addPlayerPacket.getMetadata().putFlags(flags);
dirtyMetadata.apply(addPlayerPacket.getMetadata());
diff --git a/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java b/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java
index 30f5e80fa..4d8ef680c 100644
--- a/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java
+++ b/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java
@@ -29,6 +29,8 @@ import com.github.steveice10.mc.protocol.codec.MinecraftCodec;
import com.github.steveice10.mc.protocol.codec.PacketCodec;
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import com.nukkitx.protocol.bedrock.v527.Bedrock_v527;
+import com.nukkitx.protocol.bedrock.v534.Bedrock_v534;
+import org.geysermc.geyser.session.GeyserSession;
import java.util.ArrayList;
import java.util.Collections;
@@ -43,7 +45,7 @@ public final class MinecraftProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports.
*/
- public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v527.V527_CODEC;
+ public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v534.V534_CODEC;
/**
* A list of all supported Bedrock versions that can join Geyser
*/
@@ -56,9 +58,10 @@ public final class MinecraftProtocol {
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
static {
- SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
+ SUPPORTED_BEDROCK_CODECS.add(Bedrock_v527.V527_CODEC.toBuilder()
.minecraftVersion("1.19.0/1.19.2")
.build());
+ SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
}
/**
@@ -75,6 +78,12 @@ public final class MinecraftProtocol {
return null;
}
+ /* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */
+
+ public static boolean supports1_19_10(GeyserSession session) {
+ return session.getUpstream().getProtocolVersion() >= Bedrock_v534.V534_CODEC.getProtocolVersion();
+ }
+
/**
* Gets the {@link PacketCodec} for Minecraft: Java Edition.
*
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 0a916fbf5..087cd0d8c 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -487,6 +487,11 @@ public class GeyserSession implements GeyserConnection, CommandSender {
@Setter
private boolean instabuild = false;
+ @Setter
+ private float flySpeed;
+ @Setter
+ private float walkSpeed;
+
/**
* Caches current rain status.
*/
@@ -1623,23 +1628,81 @@ public class GeyserSession implements GeyserConnection, CommandSender {
return geyser.getWorldManager().hasPermission(this, permission);
}
+ private static final Ability[] USED_ABILITIES = Ability.values();
+
/**
* Send an AdventureSettingsPacket to the client with the latest flags
*/
public void sendAdventureSettings() {
- AdventureSettingsPacket adventureSettingsPacket = new AdventureSettingsPacket();
- adventureSettingsPacket.setUniqueEntityId(playerEntity.getGeyserId());
+ long bedrockId = playerEntity.getGeyserId();
// Set command permission if OP permission level is high enough
// This allows mobile players access to a GUI for doing commands. The commands there do not change above OPERATOR
// and all commands there are accessible with OP permission level 2
- adventureSettingsPacket.setCommandPermission(opPermissionLevel >= 2 ? CommandPermission.OPERATOR : CommandPermission.NORMAL);
+ CommandPermission commandPermission = opPermissionLevel >= 2 ? CommandPermission.OPERATOR : CommandPermission.NORMAL;
// Required to make command blocks destroyable
- adventureSettingsPacket.setPlayerPermission(opPermissionLevel >= 2 ? PlayerPermission.OPERATOR : PlayerPermission.MEMBER);
+ PlayerPermission playerPermission = opPermissionLevel >= 2 ? PlayerPermission.OPERATOR : PlayerPermission.MEMBER;
// Update the noClip and worldImmutable values based on the current gamemode
boolean spectator = gameMode == GameMode.SPECTATOR;
boolean worldImmutable = gameMode == GameMode.ADVENTURE || spectator;
+ if (org.geysermc.geyser.network.MinecraftProtocol.supports1_19_10(this)) {
+ UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket();
+ adventureSettingsPacket.setNoMvP(false);
+ adventureSettingsPacket.setNoMvP(false);
+ adventureSettingsPacket.setImmutableWorld(worldImmutable);
+ adventureSettingsPacket.setShowNameTags(false);
+ adventureSettingsPacket.setAutoJump(true);
+ sendUpstreamPacket(adventureSettingsPacket);
+
+ UpdateAbilitiesPacket updateAbilitiesPacket = new UpdateAbilitiesPacket();
+ updateAbilitiesPacket.setUniqueEntityId(bedrockId);
+ updateAbilitiesPacket.setCommandPermission(commandPermission);
+ updateAbilitiesPacket.setPlayerPermission(playerPermission);
+
+ AbilityLayer abilityLayer = new AbilityLayer();
+ Set abilities = abilityLayer.getAbilityValues();
+ if (canFly || spectator) {
+ abilities.add(Ability.MAY_FLY);
+ }
+
+ // Default stuff we have to fill in
+ abilities.add(Ability.BUILD);
+ abilities.add(Ability.MINE);
+ if (gameMode == GameMode.CREATIVE) {
+ // Needed so the client doesn't attempt to take away items
+ abilities.add(Ability.INSTABUILD);
+ }
+
+ if (flying || spectator) {
+ if (spectator && !flying) {
+ // We're "flying locked" in this gamemode
+ flying = true;
+ ServerboundPlayerAbilitiesPacket abilitiesPacket = new ServerboundPlayerAbilitiesPacket(true);
+ sendDownstreamPacket(abilitiesPacket);
+ }
+ abilities.add(Ability.FLYING);
+ }
+
+ if (spectator) {
+ abilities.add(Ability.NO_CLIP);
+ }
+
+ abilityLayer.setLayerType(AbilityLayer.Type.BASE);
+ abilityLayer.setFlySpeed(flySpeed);
+ abilityLayer.setWalkSpeed(walkSpeed);
+ Collections.addAll(abilityLayer.getAbilitiesSet(), USED_ABILITIES);
+
+ updateAbilitiesPacket.getAbilityLayers().add(abilityLayer);
+ sendUpstreamPacket(updateAbilitiesPacket);
+ return;
+ }
+
+ AdventureSettingsPacket adventureSettingsPacket = new AdventureSettingsPacket();
+ adventureSettingsPacket.setUniqueEntityId(bedrockId);
+ adventureSettingsPacket.setCommandPermission(commandPermission);
+ adventureSettingsPacket.setPlayerPermission(playerPermission);
+
Set flags = adventureSettingsPacket.getSettings();
if (canFly || spectator) {
flags.add(AdventureSetting.MAY_FLY);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerAbilitiesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerAbilitiesTranslator.java
index 44ae7f425..783f4e824 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerAbilitiesTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerAbilitiesTranslator.java
@@ -38,6 +38,8 @@ public class JavaPlayerAbilitiesTranslator extends PacketTranslator {
+
+ @Override
+ public void translate(GeyserSession session, ClientboundPlayerCombatKillPacket packet) {
+ if (packet.getPlayerId() == session.getPlayerEntity().getEntityId() && MinecraftProtocol.supports1_19_10(session)) {
+ Component deathMessage = packet.getMessage();
+ // TODO - could inject score in, but as of 1.19.10 newlines don't center and start at the left of the first text
+ DeathInfoPacket deathInfoPacket = new DeathInfoPacket();
+ deathInfoPacket.setCauseAttackName(MessageTranslator.convertMessage(deathMessage, session.getLocale()));
+ session.sendUpstreamPacket(deathInfoPacket);
+ }
+ }
+}
From fa726092e337201d914b9c98f3fec935777585bc Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Sun, 10 Jul 2022 15:52:11 -0400
Subject: [PATCH 28/39] A cleaner error on illegal set slot packet
---
.../JavaContainerSetSlotTranslator.java | 35 +++++++++++++------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java
index 36307e7bd..aef8cf8b2 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java
@@ -33,6 +33,7 @@ import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
+import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
@@ -66,27 +67,41 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator 0 || stateId != inventory.getStateId());
- inventory.setStateId(stateId);
-
InventoryTranslator translator = session.getInventoryTranslator();
if (translator != null) {
if (session.getCraftingGridFuture() != null) {
session.getCraftingGridFuture().cancel(false);
}
- updateCraftingGrid(session, packet.getSlot(), packet.getItem(), inventory, translator);
+
+ int slot = packet.getSlot();
+ if (slot >= inventory.getSize()) {
+ GeyserImpl geyser = session.getGeyser();
+ geyser.getLogger().warning("ClientboundContainerSetSlotPacket sent to " + session.name()
+ + " that exceeds inventory size!");
+ if (geyser.getConfig().isDebugMode()) {
+ geyser.getLogger().debug(packet);
+ geyser.getLogger().debug(inventory);
+ }
+ // 1.19.0 behavior: the state ID will not be set due to exception
+ return;
+ }
+
+ updateCraftingGrid(session, slot, packet.getItem(), inventory, translator);
GeyserItemStack newItem = GeyserItemStack.from(packet.getItem());
if (packet.getContainerId() == 0 && !(translator instanceof PlayerInventoryTranslator)) {
// In rare cases, the window ID can still be 0 but Java treats it as valid
- session.getPlayerInventory().setItem(packet.getSlot(), newItem, session);
- InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), packet.getSlot());
+ session.getPlayerInventory().setItem(slot, newItem, session);
+ InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), slot);
} else {
- inventory.setItem(packet.getSlot(), newItem, session);
- translator.updateSlot(session, inventory, packet.getSlot());
+ inventory.setItem(slot, newItem, session);
+ translator.updateSlot(session, inventory, slot);
}
+
+ // Intentional behavior here below the cursor; Minecraft 1.18.1 also does this.
+ int stateId = packet.getStateId();
+ session.setEmulatePost1_16Logic(stateId > 0 || stateId != inventory.getStateId());
+ inventory.setStateId(stateId);
}
}
From 4656383c671dba5922c98eed7a877cfaafb911e6 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Sun, 10 Jul 2022 17:05:19 -0400
Subject: [PATCH 29/39] Bump to 2.0.5-SNAPSHOT
---
README.md | 2 +-
ap/pom.xml | 4 ++--
api/base/pom.xml | 2 +-
api/geyser/pom.xml | 4 ++--
api/pom.xml | 2 +-
bootstrap/bungeecord/pom.xml | 4 ++--
bootstrap/pom.xml | 4 ++--
bootstrap/spigot/pom.xml | 4 ++--
bootstrap/sponge/pom.xml | 4 ++--
bootstrap/standalone/pom.xml | 4 ++--
bootstrap/velocity/pom.xml | 4 ++--
common/pom.xml | 2 +-
core/pom.xml | 8 ++++----
pom.xml | 2 +-
14 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/README.md b/README.md
index aba8babf2..796170dfd 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,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!
-### Currently supporting Minecraft Bedrock 1.19 and Minecraft Java 1.19.0.
+### Currently supporting Minecraft Bedrock 1.19.0 - 1.19.10 and Minecraft Java 1.19.0.
## Setting Up
Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser.
diff --git a/ap/pom.xml b/ap/pom.xml
index 0dbb4f504..1be050e51 100644
--- a/ap/pom.xml
+++ b/ap/pom.xml
@@ -6,9 +6,9 @@
org.geysermc
geyser-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
ap
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
\ No newline at end of file
diff --git a/api/base/pom.xml b/api/base/pom.xml
index 459d7a87a..ec0c8ac84 100644
--- a/api/base/pom.xml
+++ b/api/base/pom.xml
@@ -5,7 +5,7 @@
org.geysermc
api-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
4.0.0
diff --git a/api/geyser/pom.xml b/api/geyser/pom.xml
index 38af895f0..6842929e6 100644
--- a/api/geyser/pom.xml
+++ b/api/geyser/pom.xml
@@ -5,7 +5,7 @@
org.geysermc
api-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
4.0.0
@@ -26,7 +26,7 @@
org.geysermc
base-api
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
compile
diff --git a/api/pom.xml b/api/pom.xml
index efc85cc72..50c7cb822 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
geyser-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
api-parent
diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml
index 3c9f7904e..cd96fe6d0 100644
--- a/bootstrap/bungeecord/pom.xml
+++ b/bootstrap/bungeecord/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
bootstrap-bungeecord
@@ -14,7 +14,7 @@
org.geysermc
core
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
compile
diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml
index b47e95644..99e77f5af 100644
--- a/bootstrap/pom.xml
+++ b/bootstrap/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
geyser-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
bootstrap-parent
pom
@@ -34,7 +34,7 @@
org.geysermc
ap
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
provided
diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml
index 0101e11ae..dffe9f578 100644
--- a/bootstrap/spigot/pom.xml
+++ b/bootstrap/spigot/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
bootstrap-spigot
@@ -30,7 +30,7 @@
org.geysermc
core
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
compile
diff --git a/bootstrap/sponge/pom.xml b/bootstrap/sponge/pom.xml
index e70d2d825..e0ea5c97d 100644
--- a/bootstrap/sponge/pom.xml
+++ b/bootstrap/sponge/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
bootstrap-sponge
@@ -14,7 +14,7 @@
org.geysermc
core
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
compile
diff --git a/bootstrap/standalone/pom.xml b/bootstrap/standalone/pom.xml
index 514b80799..aca72d28c 100644
--- a/bootstrap/standalone/pom.xml
+++ b/bootstrap/standalone/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
bootstrap-standalone
@@ -18,7 +18,7 @@
org.geysermc
core
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
compile
diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml
index fa05bb2c1..62b155c97 100644
--- a/bootstrap/velocity/pom.xml
+++ b/bootstrap/velocity/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
bootstrap-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
bootstrap-velocity
@@ -14,7 +14,7 @@
org.geysermc
core
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
compile
diff --git a/common/pom.xml b/common/pom.xml
index 65b6ef7ce..f25943535 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
geyser-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
common
diff --git a/core/pom.xml b/core/pom.xml
index e264531a9..c3fca5fc8 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -6,7 +6,7 @@
org.geysermc
geyser-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
core
@@ -29,19 +29,19 @@
org.geysermc
ap
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
provided
org.geysermc
geyser-api
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
compile
org.geysermc
common
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
compile
diff --git a/pom.xml b/pom.xml
index a9370a3c0..70924b7a0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
org.geysermc
geyser-parent
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
pom
Geyser
Allows for players from Minecraft Bedrock Edition to join Minecraft Java Edition servers.
From 16bb79e7aabf3882130e59f3fcd42da0bb6c074b Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Mon, 11 Jul 2022 08:38:26 -0400
Subject: [PATCH 30/39] Support HAProxy in legacy ping passthrough
---
.../ping/GeyserLegacyPingPassthrough.java | 88 +++++++++++--------
.../geyser/session/GeyserSession.java | 2 +-
2 files changed, 53 insertions(+), 37 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
index d438110d0..7db571be0 100644
--- a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
+++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
@@ -28,6 +28,9 @@ package org.geysermc.geyser.ping;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.nukkitx.nbt.util.VarInts;
+import io.netty.handler.codec.haproxy.HAProxyCommand;
+import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol;
+import io.netty.util.NetUtil;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.network.MinecraftProtocol;
@@ -35,13 +38,12 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.net.ConnectException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketTimeoutException;
+import java.net.*;
import java.util.concurrent.TimeUnit;
public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runnable {
+ private static final byte[] HAPROXY_BINARY_PREFIX = new byte[]{13, 10, 13, 10, 0, 13, 10, 81, 85, 73, 84, 10};
+
private final GeyserImpl geyser;
public GeyserLegacyPingPassthrough(GeyserImpl geyser) {
@@ -74,54 +76,68 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
@Override
public void run() {
- try {
- Socket socket = new Socket();
+ try (Socket socket = new Socket()) {
String address = geyser.getConfig().getRemote().getAddress();
int port = geyser.getConfig().getRemote().getPort();
socket.connect(new InetSocketAddress(address, port), 5000);
ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
- DataOutputStream handshake = new DataOutputStream(byteArrayStream);
- handshake.write(0x0);
- VarInts.writeUnsignedInt(handshake, MinecraftProtocol.getJavaProtocolVersion());
- VarInts.writeUnsignedInt(handshake, address.length());
- handshake.writeBytes(address);
- handshake.writeShort(port);
- VarInts.writeUnsignedInt(handshake, 1);
+ try (DataOutputStream handshake = new DataOutputStream(byteArrayStream)) {
+ handshake.write(0x0);
+ VarInts.writeUnsignedInt(handshake, MinecraftProtocol.getJavaProtocolVersion());
+ VarInts.writeUnsignedInt(handshake, address.length());
+ handshake.writeBytes(address);
+ handshake.writeShort(port);
+ VarInts.writeUnsignedInt(handshake, 1);
+ }
- DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
- VarInts.writeUnsignedInt(dataOutputStream, byteArrayStream.size());
- dataOutputStream.write(byteArrayStream.toByteArray());
- dataOutputStream.writeByte(0x01);
- dataOutputStream.writeByte(0x00);
+ byte[] buffer;
- DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
- VarInts.readUnsignedInt(dataInputStream);
- VarInts.readUnsignedInt(dataInputStream);
- int length = VarInts.readUnsignedInt(dataInputStream);
- byte[] buffer = new byte[length];
- dataInputStream.readFully(buffer);
- dataOutputStream.writeByte(0x09);
- dataOutputStream.writeByte(0x01);
- dataOutputStream.writeLong(System.currentTimeMillis());
+ try (DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
+ if (geyser.getConfig().getRemote().isUseProxyProtocol()) {
+ // HAProxy support
+ // Based on https://github.com/netty/netty/blob/d8ad931488f6b942dabe28ecd6c399b4438da0a8/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessageEncoder.java#L78
+ dataOutputStream.write(HAPROXY_BINARY_PREFIX);
+ dataOutputStream.writeByte((0x02 << 4) | HAProxyCommand.PROXY.byteValue());
+ dataOutputStream.writeByte(socket.getLocalAddress() instanceof Inet4Address ?
+ HAProxyProxiedProtocol.TCP4.byteValue() : HAProxyProxiedProtocol.TCP6.byteValue());
+ byte[] srcAddrBytes = NetUtil.createByteArrayFromIpAddressString(
+ ((InetSocketAddress) socket.getLocalSocketAddress()).getAddress().getHostAddress());
+ byte[] dstAddrBytes = NetUtil.createByteArrayFromIpAddressString(address);
+ dataOutputStream.writeShort(srcAddrBytes.length + dstAddrBytes.length + 4);
+ dataOutputStream.write(srcAddrBytes);
+ dataOutputStream.write(dstAddrBytes);
+ dataOutputStream.writeShort(((InetSocketAddress) socket.getLocalSocketAddress()).getPort());
+ dataOutputStream.writeShort(port);
+ }
- VarInts.readUnsignedInt(dataInputStream);
- String json = new String(buffer);
+ VarInts.writeUnsignedInt(dataOutputStream, byteArrayStream.size());
+ dataOutputStream.write(byteArrayStream.toByteArray());
+ dataOutputStream.writeByte(0x01);
+ dataOutputStream.writeByte(0x00);
- this.pingInfo = GeyserImpl.JSON_MAPPER.readValue(json, GeyserPingInfo.class);
+ try (DataInputStream dataInputStream = new DataInputStream(socket.getInputStream())) {
+ VarInts.readUnsignedInt(dataInputStream);
+ VarInts.readUnsignedInt(dataInputStream);
+ int length = VarInts.readUnsignedInt(dataInputStream);
+ buffer = new byte[length];
+ dataInputStream.readFully(buffer);
+ dataOutputStream.writeByte(0x09);
+ dataOutputStream.writeByte(0x01);
+ dataOutputStream.writeLong(System.currentTimeMillis());
- byteArrayStream.close();
- handshake.close();
- dataOutputStream.close();
- dataInputStream.close();
- socket.close();
+ VarInts.readUnsignedInt(dataInputStream);
+ }
+ }
+
+ this.pingInfo = GeyserImpl.JSON_MAPPER.readValue(buffer, GeyserPingInfo.class);
} catch (SocketTimeoutException | ConnectException ex) {
this.pingInfo = null;
this.geyser.getLogger().debug("Connection timeout for ping passthrough.");
} catch (JsonParseException | JsonMappingException ex) {
this.geyser.getLogger().error("Failed to parse json when pinging server!", ex);
} catch (IOException e) {
- e.printStackTrace();
+ this.geyser.getLogger().error("IO error while trying to use legacy ping passthrough", e);
}
}
}
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 087cd0d8c..0b6508032 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -1649,7 +1649,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
if (org.geysermc.geyser.network.MinecraftProtocol.supports1_19_10(this)) {
UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket();
adventureSettingsPacket.setNoMvP(false);
- adventureSettingsPacket.setNoMvP(false);
+ adventureSettingsPacket.setNoPvM(false);
adventureSettingsPacket.setImmutableWorld(worldImmutable);
adventureSettingsPacket.setShowNameTags(false);
adventureSettingsPacket.setAutoJump(true);
From bca6359f7e4d5f8dcd63baf43faa90e7c2354d6d Mon Sep 17 00:00:00 2001
From: Kas-tle <26531652+Kas-tle@users.noreply.github.com>
Date: Tue, 12 Jul 2022 05:29:39 +0000
Subject: [PATCH 31/39] 1.19.10 fallout
---
bootstrap/spigot/build.gradle.kts | 2 +-
.../geyser/platform/spigot/GeyserPaperPingPassthrough.java | 4 ++--
build-logic/build.gradle.kts | 2 +-
build-logic/src/main/kotlin/Versions.kt | 4 ++--
.../src/main/kotlin/geyser.base-conventions.gradle.kts | 4 ++--
core/build.gradle.kts | 2 +-
.../geysermc/geyser/ping/GeyserLegacyPingPassthrough.java | 3 +--
.../java/org/geysermc/geyser/session/GeyserSession.java | 2 +-
.../translator/inventory/item/GoatHornTranslator.java | 4 ++--
.../java/entity/player/JavaPlayerCombatKillTranslator.java | 6 +++---
10 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts
index 8e2b73cd1..d755f323c 100644
--- a/bootstrap/spigot/build.gradle.kts
+++ b/bootstrap/spigot/build.gradle.kts
@@ -1,4 +1,4 @@
-val paperVersion = "1.17.1-R0.1-SNAPSHOT" // Needed because we do not support Java 17 yet
+val paperVersion = "1.19-R0.1-SNAPSHOT" // Needed because we do not support Java 17 yet
val viaVersion = "4.0.0"
val adaptersVersion = "1.4-SNAPSHOT"
val commodoreVersion = "1.13"
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 64c185585..36dd81d44 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
@@ -62,11 +62,11 @@ public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough
// Approximately pre-1.19
event = OLD_CONSTRUCTOR.newInstance(new GeyserStatusClient(inetSocketAddress),
Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(),
- Bukkit.getMaxPlayers(), Bukkit.getVersion(), MinecraftProtocol.getJavaProtocolVersion(), null);
+ Bukkit.getMaxPlayers(), Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion(), null);
} else {
event = new PaperServerListPingEvent(new GeyserStatusClient(inetSocketAddress),
Bukkit.getMotd(), Bukkit.shouldSendChatPreviews(), Bukkit.getOnlinePlayers().size(),
- Bukkit.getMaxPlayers(), Bukkit.getVersion(), MinecraftProtocol.getJavaProtocolVersion(), null);
+ Bukkit.getMaxPlayers(), Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion(), null);
}
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts
index 25cbfe9de..dc8d6d620 100644
--- a/build-logic/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -16,6 +16,6 @@ dependencies {
tasks.withType {
kotlinOptions {
- jvmTarget = "16"
+ jvmTarget = "17"
}
}
\ No newline at end of file
diff --git a/build-logic/src/main/kotlin/Versions.kt b/build-logic/src/main/kotlin/Versions.kt
index 779065bc5..919935409 100644
--- a/build-logic/src/main/kotlin/Versions.kt
+++ b/build-logic/src/main/kotlin/Versions.kt
@@ -30,10 +30,10 @@ object Versions {
const val guavaVersion = "29.0-jre"
const val nbtVersion = "2.1.0"
const val websocketVersion = "1.5.1"
- const val protocolVersion = "977a9a1"
+ const val protocolVersion = "a78a64b"
const val raknetVersion = "1.6.28-SNAPSHOT"
const val mcauthlibVersion = "d9d773e"
- const val mcprotocollibversion = "bb2b414"
+ const val mcprotocollibversion = "54fc9f0"
const val packetlibVersion = "3.0"
const val adventureVersion = "4.9.3"
const val eventVersion = "3.0.0"
diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts
index 2ea5d88a4..b4cc63deb 100644
--- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts
+++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts
@@ -26,8 +26,8 @@ tasks {
}
java {
- sourceCompatibility = JavaVersion.VERSION_16
- targetCompatibility = JavaVersion.VERSION_16
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
withSourcesJar()
}
\ No newline at end of file
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index e82af5687..561c2f554 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -31,7 +31,7 @@ dependencies {
// Network libraries
implementation("org.java-websocket", "Java-WebSocket", Versions.websocketVersion)
- api("com.github.CloudburstMC.Protocol", "bedrock-v527", Versions.protocolVersion) {
+ api("com.github.CloudburstMC.Protocol", "bedrock-v534", Versions.protocolVersion) {
exclude("com.nukkitx.network", "raknet")
exclude("com.nukkitx", "nbt")
}
diff --git a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
index 817ee9e81..199e13918 100644
--- a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
+++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
@@ -27,7 +27,6 @@ package org.geysermc.geyser.ping;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
-import com.github.steveice10.mc.protocol.MinecraftProtocol;
import com.nukkitx.nbt.util.VarInts;
import io.netty.handler.codec.haproxy.HAProxyCommand;
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol;
@@ -85,7 +84,7 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
try (DataOutputStream handshake = new DataOutputStream(byteArrayStream)) {
handshake.write(0x0);
- VarInts.writeUnsignedInt(handshake, MinecraftProtocol.getJavaProtocolVersion());
+ VarInts.writeUnsignedInt(handshake, GameProtocol.getJavaProtocolVersion());
VarInts.writeUnsignedInt(handshake, address.length());
handshake.writeBytes(address);
handshake.writeShort(port);
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 4639a952c..cf94d299d 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -1643,7 +1643,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
boolean spectator = gameMode == GameMode.SPECTATOR;
boolean worldImmutable = gameMode == GameMode.ADVENTURE || spectator;
- if (org.geysermc.geyser.network.MinecraftProtocol.supports1_19_10(this)) {
+ if (org.geysermc.geyser.network.GameProtocol.supports1_19_10(this)) {
UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket();
adventureSettingsPacket.setNoMvP(false);
adventureSettingsPacket.setNoPvM(false);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java
index 08e8534af..2cb9d7ec7 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/GoatHornTranslator.java
@@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.network.MinecraftProtocol;
+import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
@@ -91,7 +91,7 @@ public class GoatHornTranslator extends ItemTranslator {
@Override
public List getAppliedItems() {
return Collections.singletonList(
- Registries.ITEMS.forVersion(MinecraftProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
+ Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
.getMapping("minecraft:goat_horn")
);
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java
index 0f1fd4d1b..89be26e4a 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerCombatKillTranslator.java
@@ -28,7 +28,7 @@ package org.geysermc.geyser.translator.protocol.java.entity.player;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerCombatKillPacket;
import com.nukkitx.protocol.bedrock.packet.DeathInfoPacket;
import net.kyori.adventure.text.Component;
-import org.geysermc.geyser.network.MinecraftProtocol;
+import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
@@ -39,11 +39,11 @@ public class JavaPlayerCombatKillTranslator extends PacketTranslator
Date: Tue, 12 Jul 2022 14:24:53 +0000
Subject: [PATCH 32/39] Build on Java 17
---
.github/workflows/pullrequest.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml
index f5bb4c042..9d925c4dc 100644
--- a/.github/workflows/pullrequest.yml
+++ b/.github/workflows/pullrequest.yml
@@ -9,11 +9,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: Set up JDK 16
+ - name: Set up JDK 17
uses: actions/setup-java@v1
with:
distribution: 'temurin'
- java-version: 16
+ java-version: 17
cache: 'gradle'
- name: submodules-init
uses: snickerbockers/submodules-init@v4
From 8b9f41d4a6dc409c3acd98f64ad2813d8529f93a Mon Sep 17 00:00:00 2001
From: Kas-tle <26531652+Kas-tle@users.noreply.github.com>
Date: Tue, 12 Jul 2022 07:38:57 -0700
Subject: [PATCH 33/39] Java 17 (Jenkinsfile)
---
Jenkinsfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Jenkinsfile b/Jenkinsfile
index f92778318..b3df4bc95 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -2,7 +2,7 @@ pipeline {
agent any
tools {
gradle 'Gradle 7'
- jdk 'Java 16'
+ jdk 'Java 17'
}
options {
buildDiscarder(logRotator(artifactNumToKeepStr: '20'))
From 2dbd39c5a437ee14c589acb1ab2576c9779725b9 Mon Sep 17 00:00:00 2001
From: Kas-tle <26531652+Kas-tle@users.noreply.github.com>
Date: Tue, 12 Jul 2022 16:33:57 +0000
Subject: [PATCH 34/39] Per review by @Camotoy
---
bootstrap/spigot/build.gradle.kts | 2 +-
.../main/java/org/geysermc/geyser/session/GeyserSession.java | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts
index d755f323c..123ef06f2 100644
--- a/bootstrap/spigot/build.gradle.kts
+++ b/bootstrap/spigot/build.gradle.kts
@@ -1,4 +1,4 @@
-val paperVersion = "1.19-R0.1-SNAPSHOT" // Needed because we do not support Java 17 yet
+val paperVersion = "1.19-R0.1-SNAPSHOT"
val viaVersion = "4.0.0"
val adaptersVersion = "1.4-SNAPSHOT"
val commodoreVersion = "1.13"
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 cf94d299d..edaed9893 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -116,6 +116,7 @@ import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
import org.geysermc.geyser.level.JavaDimension;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.level.physics.CollisionManager;
+import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.network.netty.LocalSession;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.BlockMappings;
@@ -1643,7 +1644,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
boolean spectator = gameMode == GameMode.SPECTATOR;
boolean worldImmutable = gameMode == GameMode.ADVENTURE || spectator;
- if (org.geysermc.geyser.network.GameProtocol.supports1_19_10(this)) {
+ if (GameProtocol.supports1_19_10(this)) {
UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket();
adventureSettingsPacket.setNoMvP(false);
adventureSettingsPacket.setNoPvM(false);
From d1fbb909a54ac4114bee7034b2d2df1300ac3d97 Mon Sep 17 00:00:00 2001
From: Kas-tle <26531652+Kas-tle@users.noreply.github.com>
Date: Tue, 12 Jul 2022 17:09:48 +0000
Subject: [PATCH 35/39] fixed java 16 thanks to @davchoo
---
bootstrap/spigot/build.gradle.kts | 14 ++++++++++++--
build-logic/build.gradle.kts | 2 +-
.../main/kotlin/geyser.base-conventions.gradle.kts | 4 ++--
3 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts
index 123ef06f2..5a12ded01 100644
--- a/bootstrap/spigot/build.gradle.kts
+++ b/bootstrap/spigot/build.gradle.kts
@@ -9,6 +9,18 @@ dependencies {
implementation("org.geysermc.geyser.adapters", "spigot-all", adaptersVersion)
implementation("me.lucko", "commodore", commodoreVersion)
+
+ // Both paper-api and paper-mojangapi only provide Java 17 versions for 1.19
+ compileOnly("io.papermc.paper", "paper-api", paperVersion) {
+ attributes {
+ attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
+ }
+ }
+ compileOnly("io.papermc.paper", "paper-mojangapi", paperVersion) {
+ attributes {
+ attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
+ }
+ }
}
platformRelocate("it.unimi.dsi.fastutil")
@@ -19,8 +31,6 @@ platformRelocate("me.lucko.commodore")
platformRelocate("io.netty.channel.kqueue")
// These dependencies are already present on the platform
-provided("io.papermc.paper", "paper-api", paperVersion)
-provided("io.papermc.paper", "paper-mojangapi", paperVersion)
provided("com.viaversion", "viaversion", viaVersion)
application {
diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts
index dc8d6d620..25cbfe9de 100644
--- a/build-logic/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -16,6 +16,6 @@ dependencies {
tasks.withType {
kotlinOptions {
- jvmTarget = "17"
+ jvmTarget = "16"
}
}
\ No newline at end of file
diff --git a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts
index b4cc63deb..2ea5d88a4 100644
--- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts
+++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts
@@ -26,8 +26,8 @@ tasks {
}
java {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
+ sourceCompatibility = JavaVersion.VERSION_16
+ targetCompatibility = JavaVersion.VERSION_16
withSourcesJar()
}
\ No newline at end of file
From 109e1c0a97c180dc47884f5100354a8b1d7c6f3f Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Tue, 12 Jul 2022 16:05:06 -0400
Subject: [PATCH 36/39] Fix dropping items in 1.19.10
---
.../main/java/org/geysermc/geyser/session/GeyserSession.java | 2 ++
1 file changed, 2 insertions(+)
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 0b6508032..3dd763546 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -1669,6 +1669,8 @@ public class GeyserSession implements GeyserConnection, CommandSender {
// Default stuff we have to fill in
abilities.add(Ability.BUILD);
abilities.add(Ability.MINE);
+ // Needed so you can drop items
+ abilities.add(Ability.DOORS_AND_SWITCHES);
if (gameMode == GameMode.CREATIVE) {
// Needed so the client doesn't attempt to take away items
abilities.add(Ability.INSTABUILD);
From 0335c8263c21e30a28baa0f34a9eb97dbe808de3 Mon Sep 17 00:00:00 2001
From: Kas-tle <26531652+Kas-tle@users.noreply.github.com>
Date: Wed, 13 Jul 2022 16:20:42 +0000
Subject: [PATCH 37/39] Address @Camotoy's review
---
bootstrap/spigot/build.gradle.kts | 2 +-
build-logic/src/main/kotlin/Versions.kt | 2 ++
settings.gradle.kts | 7 ++++++-
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts
index 5a12ded01..02883999d 100644
--- a/bootstrap/spigot/build.gradle.kts
+++ b/bootstrap/spigot/build.gradle.kts
@@ -1,6 +1,6 @@
val paperVersion = "1.19-R0.1-SNAPSHOT"
val viaVersion = "4.0.0"
-val adaptersVersion = "1.4-SNAPSHOT"
+val adaptersVersion = "1.5-SNAPSHOT"
val commodoreVersion = "1.13"
dependencies {
diff --git a/build-logic/src/main/kotlin/Versions.kt b/build-logic/src/main/kotlin/Versions.kt
index 919935409..27f7bcaf5 100644
--- a/build-logic/src/main/kotlin/Versions.kt
+++ b/build-logic/src/main/kotlin/Versions.kt
@@ -31,6 +31,8 @@ object Versions {
const val nbtVersion = "2.1.0"
const val websocketVersion = "1.5.1"
const val protocolVersion = "a78a64b"
+ // Not pinned to specific version due to possible gradle bug
+ // See comment in settings.gradle.kts
const val raknetVersion = "1.6.28-SNAPSHOT"
const val mcauthlibVersion = "d9d773e"
const val mcprotocollibversion = "54fc9f0"
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 0bc694b43..dd08f3922 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -8,7 +8,12 @@ dependencyResolutionManagement {
mavenContent { releasesOnly() }
}
maven("https://repo.opencollab.dev/maven-snapshots") {
- mavenContent { snapshotsOnly() }
+ mavenContent {
+ // This has the unintended side effect of not allowing snapshot version pinning.
+ // Likely a bug in Gradle's implementation of snapshot pinning
+ // See https://github.com/gradle/gradle/pull/406
+ snapshotsOnly()
+ }
}
// Paper, Velocity
From f6f8886f2300f3d01e836e17150196e33bbcebcf Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Wed, 13 Jul 2022 21:31:10 -0400
Subject: [PATCH 38/39] Fix PS4 players crashing on certain dimension switches
---
.../geysermc/geyser/session/GeyserSession.java | 2 +-
.../geysermc/geyser/session/cache/TagCache.java | 6 +++---
.../inventory/MerchantInventoryTranslator.java | 2 +-
.../player/JavaPlayerPositionTranslator.java | 10 ++++++++++
.../geysermc/geyser/util/DimensionUtils.java | 17 +++++++++++++++++
5 files changed, 32 insertions(+), 5 deletions(-)
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 3dd763546..519eef3b5 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -392,7 +392,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
* Whether to work around 1.13's different behavior in villager trading menus.
*/
@Setter
- private boolean emulatePost1_14Logic = true;
+ private boolean emulatePost1_13Logic = true;
/**
* Starting in 1.17, Java servers expect the carriedItem
parameter of the serverbound click container
* packet to be the current contents of the mouse after the transaction has been done. 1.16 expects the clicked slot
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
index 7db01e655..ac0c93204 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
@@ -101,10 +101,10 @@ public class TagCache {
this.smallFlowers = IntList.of(itemTags.get("minecraft:small_flowers"));
// Hack btw
- boolean emulatePost1_14Logic = itemTags.get("minecraft:signs").length > 1;
- session.setEmulatePost1_14Logic(emulatePost1_14Logic);
+ boolean emulatePost1_13Logic = itemTags.get("minecraft:signs").length > 1;
+ session.setEmulatePost1_13Logic(emulatePost1_13Logic);
if (logger.isDebug()) {
- logger.debug("Emulating post 1.14 villager logic for " + session.name() + "? " + emulatePost1_14Logic);
+ logger.debug("Emulating post 1.13 villager logic for " + session.name() + "? " + emulatePost1_13Logic);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java
index 061f6c5ea..031fb606e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java
@@ -159,7 +159,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
ServerboundSelectTradePacket packet = new ServerboundSelectTradePacket(tradeChoice);
session.sendDownstreamPacket(packet);
- if (session.isEmulatePost1_14Logic()) {
+ if (session.isEmulatePost1_13Logic()) {
// 1.18 Java cooperates nicer than older versions
if (inventory instanceof MerchantContainer merchantInventory) {
merchantInventory.onTradeSelected(session, tradeChoice);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
index f5d21ecc9..2d2d7279f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
@@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.Serverb
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData;
+import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
@@ -84,6 +85,15 @@ public class JavaPlayerPositionTranslator extends PacketTranslator 47 && !session.isEmulatePost1_13Logic()) {
+ // See DimensionUtils for an explanation
+ ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket();
+ chunkRadiusUpdatedPacket.setRadius(session.getServerRenderDistance());
+ session.sendUpstreamPacket(chunkRadiusUpdatedPacket);
+
+ session.setLastChunkPosition(null);
+ }
+
ChunkUtils.updateChunkPosition(session, pos.toInt());
if (session.getGeyser().getConfig().isDebugMode()) {
diff --git a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
index fbc891131..7e5d65a97 100644
--- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.util;
import com.github.steveice10.mc.protocol.data.game.entity.Effect;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.ChangeDimensionPacket;
+import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
import com.nukkitx.protocol.bedrock.packet.MobEffectPacket;
import com.nukkitx.protocol.bedrock.packet.StopSoundPacket;
import org.geysermc.geyser.entity.type.Entity;
@@ -69,6 +70,22 @@ public class DimensionUtils {
session.getPistonCache().clear();
session.getSkullCache().clear();
+ if (session.getServerRenderDistance() > 47 && !session.isEmulatePost1_13Logic()) {
+ // The server-sided view distance wasn't a thing until Minecraft Java 1.14
+ // So ViaVersion compensates by sending a "view distance" of 64
+ // That's fine, except when the actual view distance sent from the server is five chunks
+ // The client locks up when switching dimensions, expecting more chunks than it's getting
+ // To solve this, we cap at 32 unless we know that the render distance actually exceeds 32
+ // 47 is the Bedrock equivalent of 32
+ // Also, as of 1.19: PS4 crashes with a ChunkRadiusUpdatedPacket too large
+ session.getGeyser().getLogger().debug("Applying dimension switching workaround for Bedrock render distance of "
+ + session.getServerRenderDistance());
+ ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket();
+ chunkRadiusUpdatedPacket.setRadius(47);
+ session.sendUpstreamPacket(chunkRadiusUpdatedPacket);
+ // Will be re-adjusted on spawn
+ }
+
Vector3f pos = Vector3f.from(0, Short.MAX_VALUE, 0);
ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket();
From 616c088b66830c8640a2b6e9f39f36af9ef14eb5 Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Wed, 20 Jul 2022 18:35:40 -0400
Subject: [PATCH 39/39] Fix custom items with
ItemTranslator#getBedrockItemMapping
---
.../geysermc/geyser/inventory/Inventory.java | 7 +++----
.../inventory/item/ItemTranslator.java | 17 ++++++++++++-----
.../BedrockInventoryTransactionTranslator.java | 2 +-
3 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java
index ca7e90a25..58d551489 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java
@@ -34,7 +34,6 @@ import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import org.jetbrains.annotations.Range;
@@ -136,9 +135,9 @@ public abstract class Inventory {
protected void updateItemNetId(GeyserItemStack oldItem, GeyserItemStack newItem, GeyserSession session) {
if (!newItem.isEmpty()) {
- ItemMapping oldMapping = ItemTranslator.getBedrockItemMapping(session, oldItem);
- ItemMapping newMapping = ItemTranslator.getBedrockItemMapping(session, newItem);
- if (oldMapping.getBedrockId() == newMapping.getBedrockId()) {
+ int oldMapping = ItemTranslator.getBedrockItemId(session, oldItem);
+ int newMapping = ItemTranslator.getBedrockItemId(session, newItem);
+ if (oldMapping == newMapping) {
newItem.setNetId(oldItem.getNetId());
} else {
newItem.setNetId(session.getNextItemNetId());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
index 0a2ab57df..b36833cb1 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java
@@ -266,16 +266,23 @@ public abstract class ItemTranslator {
}
/**
- * Given an item stack, determine the item mapping that should be applied to Bedrock players.
+ * Given an item stack, determine the Bedrock item ID that should be applied to Bedrock players.
*/
- @Nonnull
- public static ItemMapping getBedrockItemMapping(GeyserSession session, @Nonnull GeyserItemStack itemStack) {
+ public static int getBedrockItemId(GeyserSession session, @Nonnull GeyserItemStack itemStack) {
if (itemStack.isEmpty()) {
- return ItemMapping.AIR;
+ return ItemMapping.AIR.getJavaId();
}
int javaId = itemStack.getJavaId();
- return ITEM_STACK_TRANSLATORS.getOrDefault(javaId, DEFAULT_TRANSLATOR)
+ ItemMapping mapping = ITEM_STACK_TRANSLATORS.getOrDefault(javaId, DEFAULT_TRANSLATOR)
.getItemMapping(javaId, itemStack.getNbt(), session.getItemMappings());
+
+ int customItemId = getCustomItem(itemStack.getNbt(), mapping);
+ if (customItemId == -1) {
+ // No custom item
+ return mapping.getBedrockId();
+ } else {
+ return customItemId;
+ }
}
private static final ItemTranslator DEFAULT_TRANSLATOR = new ItemTranslator() {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
index 24c046ef2..815456132 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java
@@ -542,7 +542,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator