diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java index e9d612976..b9fbd6cdc 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java @@ -25,7 +25,10 @@ package org.geysermc.geyser.platform.mod.world; +import com.github.steveice10.mc.protocol.data.game.Holder; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -43,6 +46,7 @@ import net.minecraft.world.item.component.WrittenBookContent; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BannerBlockEntity; +import net.minecraft.world.level.block.entity.BannerPatternLayers; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; import net.minecraft.world.level.chunk.ChunkAccess; @@ -62,6 +66,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -217,8 +222,8 @@ public class GeyserModWorldManager extends GeyserWorldManager { @NonNull @Override - public CompletableFuture getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { - CompletableFuture future = new CompletableFuture<>(); + public CompletableFuture getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { + CompletableFuture future = new CompletableFuture<>(); server.execute(() -> { ServerPlayer player = getPlayer(session); if (player == null) { @@ -235,7 +240,22 @@ public class GeyserModWorldManager extends GeyserWorldManager { // the banner might have a custom name, both of which a Java client knows and caches ItemStack itemStack = banner.getItem(); - future.complete(null); // todo 1.20.5 + com.github.steveice10.mc.protocol.data.game.item.component.DataComponents components = + new com.github.steveice10.mc.protocol.data.game.item.component.DataComponents(new HashMap<>()); + + components.put(DataComponentType.DAMAGE, itemStack.getDamageValue()); + + Component customName = itemStack.getComponents().get(DataComponents.CUSTOM_NAME); + if (customName != null) { + components.put(DataComponentType.CUSTOM_NAME, toKyoriComponent(customName)); + } + + BannerPatternLayers pattern = itemStack.get(DataComponents.BANNER_PATTERNS); + if (pattern != null) { + components.put(DataComponentType.BANNER_PATTERNS, toPatternList(pattern)); + } + + future.complete(components); return; } future.complete(null); @@ -262,8 +282,7 @@ public class GeyserModWorldManager extends GeyserWorldManager { if (writtenBookContent != null) { return writtenBookContent.pages().stream() .map(Filterable::raw) - .map((component) -> Component.Serializer.toJson(component, RegistryAccess.EMPTY)) - .map((json -> LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty())))) + .map(GeyserModWorldManager::fromComponent) .toList(); } else { WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT); @@ -275,4 +294,25 @@ public class GeyserModWorldManager extends GeyserWorldManager { .toList(); } } + + private static String fromComponent(Component component) { + String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY); + return LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty())); + } + + private static net.kyori.adventure.text.Component toKyoriComponent(Component component) { + String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY); + return GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty()); + } + + private static List toPatternList(BannerPatternLayers patternLayers) { + return patternLayers.layers().stream() + .map(layer -> { + BannerPatternLayer.BannerPattern pattern = new BannerPatternLayer.BannerPattern( + layer.pattern().value().assetId().toString(), layer.pattern().value().translationKey() + ); + return new BannerPatternLayer(Holder.ofCustom(pattern), layer.color().getId()); + }) + .toList(); + } } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java index 42f0d17f4..07a9d489a 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java @@ -26,8 +26,8 @@ package org.geysermc.geyser.platform.spigot.world.manager; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; @@ -39,7 +39,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.erosion.bukkit.BukkitLecterns; import org.geysermc.erosion.bukkit.BukkitUtils; -import org.geysermc.erosion.bukkit.PickBlockUtils; import org.geysermc.erosion.bukkit.SchedulerUtils; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.GameRule; @@ -205,8 +204,8 @@ public class GeyserSpigotWorldManager extends WorldManager { } @Override - public @NonNull CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { - CompletableFuture<@Nullable CompoundTag> future = new CompletableFuture<>(); + public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { + CompletableFuture<@Nullable DataComponents> future = new CompletableFuture<>(); Player bukkitPlayer; if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) { future.complete(null); @@ -215,7 +214,7 @@ public class GeyserSpigotWorldManager extends WorldManager { Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z); // Paper 1.19.3 complains about async access otherwise. // java.lang.IllegalStateException: Tile is null, asynchronous access? - SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block); + SchedulerUtils.runTask(this.plugin, () -> future.complete(/*PickBlockUtils.pickBlock(block)*/ null), block); // TODO fix erosion once clear how to handle this return future; } diff --git a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java index 3ae458f63..57147fc49 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -25,8 +25,8 @@ package org.geysermc.geyser.erosion; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.level.block.value.PistonValueType; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import io.netty.channel.Channel; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; @@ -43,7 +43,14 @@ import org.geysermc.erosion.packet.ErosionPacketHandler; import org.geysermc.erosion.packet.ErosionPacketSender; import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket; import org.geysermc.erosion.packet.backendbound.BackendboundPacket; -import org.geysermc.erosion.packet.geyserbound.*; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBatchBlockIdPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockEntityPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockIdPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockLookupFailPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockPlacePacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundHandshakePacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundPickBlockPacket; +import org.geysermc.erosion.packet.geyserbound.GeyserboundPistonEventPacket; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.network.GameProtocol; @@ -64,7 +71,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke @Setter private CompletableFuture pendingBatchLookup = null; @Setter - private CompletableFuture pickBlockLookup = null; + private CompletableFuture pickBlockLookup = null; private final AtomicInteger nextTransactionId = new AtomicInteger(1); @@ -140,7 +147,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke @Override public void handlePickBlock(GeyserboundPickBlockPacket packet) { if (this.pickBlockLookup != null) { - this.pickBlockLookup.complete(packet.getTag()); + //this.pickBlockLookup.complete(packet.getTag()); // TODO 1.20.5 } } diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java index 44c3b94b3..9a9eac2df 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java @@ -26,8 +26,8 @@ package org.geysermc.geyser.level; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -36,7 +36,11 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.geysermc.erosion.packet.backendbound.*; +import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockEntityPacket; +import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket; +import org.geysermc.erosion.packet.backendbound.BackendboundBlockEntityPacket; +import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket; +import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket; import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.session.GeyserSession; @@ -174,12 +178,12 @@ public class GeyserWorldManager extends WorldManager { @NonNull @Override - public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { + public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { var erosionHandler = session.getErosionHandler().getAsActive(); if (erosionHandler == null) { - return super.getPickItemNbt(session, x, y, z, addNbtData); + return super.getPickItemComponents(session, x, y, z, addNbtData); } - CompletableFuture future = new CompletableFuture<>(); + CompletableFuture future = new CompletableFuture<>(); erosionHandler.setPickBlockLookup(future); erosionHandler.sendPacket(new BackendboundPickBlockPacket(Vector3i.from(x, y, z))); return future; diff --git a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java index be7e2c139..aa0b43b80 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -26,9 +26,9 @@ package org.geysermc.geyser.level; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo; import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; @@ -220,7 +220,7 @@ public abstract class WorldManager { * @return expected NBT for this item. */ @NonNull - public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) { + public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) { return CompletableFuture.completedFuture(null); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java index 3781ef3c0..f4116ec0c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java @@ -26,9 +26,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; import com.github.steveice10.mc.protocol.data.game.item.ItemStack; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket; import org.geysermc.geyser.entity.EntityDefinitions; @@ -68,33 +65,23 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator session.ensureInEventLoop(() -> { - if (tag == null) { + boolean addExtraData = packet.isAddUserData() && blockMapping.isBlockEntity(); // Holding down CTRL + if (BlockStateValues.getBannerColor(blockToPick) != -1 || addExtraData) { //TODO + session.getGeyser().getWorldManager().getPickItemComponents(session, vector.getX(), vector.getY(), vector.getZ(), addExtraData) + .whenComplete((components, ex) -> session.ensureInEventLoop(() -> { + if (components == null) { pickItem(session, blockMapping); return; } - if (addNbtData) { - ListTag lore = new ListTag("Lore"); - lore.add(new StringTag("", "\"(+NBT)\"")); - CompoundTag display = tag.get("display"); - if (display == null) { - display = new CompoundTag("display"); - tag.put(display); - } - display.put(lore); - } // I don't really like this... I'd rather get an ID from the block mapping I think ItemMapping mapping = session.getItemMappings().getMapping(blockMapping.getPickItem()); - ItemStack itemStack = new ItemStack(mapping.getJavaItem().javaId(), 1, tag); + ItemStack itemStack = new ItemStack(mapping.getJavaItem().javaId(), 1, components); InventoryUtils.findOrCreateItem(session, itemStack); })); return; - }*/ + } pickItem(session, blockMapping); } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b7e692ab7..f2e068c22 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "d9d773e" -mcprotocollib = "4ee05b62" # Revert from jitpack after release +mcprotocollib = "7026b600" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2"