diff --git a/README.md b/README.md index d4b375a5c..593514e52 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.17.30 - 1.17.41 + 1.18.0 - 1.18.2 and Minecraft Java 1.18/1.18.1. +### Currently supporting Minecraft Bedrock 1.17.41 + 1.18.0 - 1.18.10 and Minecraft Java 1.18/1.18.1. ## Setting Up Take a look [here](https://github.com/GeyserMC/Geyser/wiki/Setup) for how to set up Geyser. diff --git a/ap/pom.xml b/ap/pom.xml index cc282dd55..dce28a7d7 100644 --- a/ap/pom.xml +++ b/ap/pom.xml @@ -6,9 +6,9 @@ org.geysermc geyser-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT ap - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT \ No newline at end of file diff --git a/api/base/pom.xml b/api/base/pom.xml index 0d7ed05da..17edb1a85 100644 --- a/api/base/pom.xml +++ b/api/base/pom.xml @@ -5,7 +5,7 @@ org.geysermc api-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT 4.0.0 diff --git a/api/geyser/pom.xml b/api/geyser/pom.xml index 435643b0a..de9c63e83 100644 --- a/api/geyser/pom.xml +++ b/api/geyser/pom.xml @@ -5,7 +5,7 @@ org.geysermc api-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT ../pom.xml 4.0.0 @@ -35,7 +35,7 @@ org.geysermc base-api - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT compile diff --git a/api/pom.xml b/api/pom.xml index f66b982fb..b6d865cb4 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -6,7 +6,7 @@ org.geysermc geyser-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT ../pom.xml diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml index 9dcd0943e..45a08c7db 100644 --- a/bootstrap/bungeecord/pom.xml +++ b/bootstrap/bungeecord/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT bootstrap-bungeecord @@ -14,7 +14,7 @@ org.geysermc core - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT compile diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml index 3b0bdda55..58c651455 100644 --- a/bootstrap/pom.xml +++ b/bootstrap/pom.xml @@ -6,7 +6,7 @@ org.geysermc geyser-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT bootstrap-parent pom @@ -34,7 +34,7 @@ org.geysermc ap - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT provided diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml index 5aa2c59cf..6eda527f3 100644 --- a/bootstrap/spigot/pom.xml +++ b/bootstrap/spigot/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT bootstrap-spigot @@ -25,7 +25,7 @@ org.geysermc core - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT compile diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java index 999353d8a..981d00b97 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java @@ -97,7 +97,7 @@ public class GeyserPistonListener implements Listener { int dX = Math.abs(location.getBlockX() - player.getLocation().getBlockX()) >> 4; int dZ = Math.abs(location.getBlockZ() - player.getLocation().getBlockZ()) >> 4; - if ((dX * dX + dZ * dZ) > session.getRenderDistance() * session.getRenderDistance()) { + if ((dX * dX + dZ * dZ) > session.getServerRenderDistance() * session.getServerRenderDistance()) { // Ignore pistons outside the player's render distance continue; } diff --git a/bootstrap/sponge/pom.xml b/bootstrap/sponge/pom.xml index fa7989b43..ab3b7d970 100644 --- a/bootstrap/sponge/pom.xml +++ b/bootstrap/sponge/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT bootstrap-sponge @@ -14,7 +14,7 @@ org.geysermc core - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT compile diff --git a/bootstrap/standalone/pom.xml b/bootstrap/standalone/pom.xml index 00c0410e4..881c87e6c 100644 --- a/bootstrap/standalone/pom.xml +++ b/bootstrap/standalone/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT bootstrap-standalone @@ -18,7 +18,7 @@ org.geysermc core - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT compile diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml index e1e3331ef..ff052471d 100644 --- a/bootstrap/velocity/pom.xml +++ b/bootstrap/velocity/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT bootstrap-velocity @@ -14,7 +14,7 @@ org.geysermc core - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT compile diff --git a/common/pom.xml b/common/pom.xml index 8e7be26f4..fde2605bc 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -6,7 +6,7 @@ org.geysermc geyser-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT common diff --git a/core/pom.xml b/core/pom.xml index 6f4e0fa3c..31f9a075f 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -6,7 +6,7 @@ org.geysermc geyser-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT core @@ -20,19 +20,19 @@ org.geysermc ap - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT provided org.geysermc geyser-api - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT compile org.geysermc common - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT compile @@ -119,8 +119,8 @@ com.github.CloudburstMC.Protocol - bedrock-v475 - c22aa595 + bedrock-v486 + 0cd24c0 compile diff --git a/core/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/core/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index e24146cb2..f754368f0 100644 --- a/core/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -64,7 +64,7 @@ public class GeyserSession { } public int getRenderDistance() { - return this.handle.getRenderDistance(); + return this.handle.getServerRenderDistance(); } public boolean isSentSpawnPacket() { diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 47aa905ea..68bb69b46 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -68,6 +68,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.SessionManager; import org.geysermc.geyser.session.auth.AuthType; import org.geysermc.geyser.skin.FloodgateSkinUploader; +import org.geysermc.geyser.skin.SkinProvider; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.inventory.item.ItemTranslator; @@ -211,6 +212,8 @@ public class GeyserImpl implements GeyserApi { ScoreboardUpdater.init(); + SkinProvider.registerCacheImageTask(this); + ResourcePack.loadPacks(); this.extensionManager.enableExtensions(); diff --git a/core/src/main/java/org/geysermc/geyser/GeyserLogger.java b/core/src/main/java/org/geysermc/geyser/GeyserLogger.java index a61c5db25..b47801cb5 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserLogger.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserLogger.java @@ -25,6 +25,8 @@ package org.geysermc.geyser; +import javax.annotation.Nullable; + public interface GeyserLogger { /** @@ -78,6 +80,15 @@ public interface GeyserLogger { */ void debug(String message); + /** + * Logs an object to console if debug mode is enabled + * + * @param object the object to log + */ + default void debug(@Nullable Object object) { + debug(String.valueOf(object)); + } + /** * Sets if the logger should print debug messages * diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java index 3fc7971b0..3b7cad44c 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java @@ -76,6 +76,10 @@ public interface GeyserConfiguration { boolean isShowCoordinates(); + boolean isDisableBedrockScaffolding(); + + boolean isAlwaysQuickChangeArmor(); + EmoteOffhandWorkaroundOption getEmoteOffhandWorkaround(); String getDefaultLocale(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index 55721f894..97c5bfea8 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -105,6 +105,12 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration @JsonProperty("show-coordinates") private boolean showCoordinates = true; + @JsonProperty("disable-bedrock-scaffolding") + private boolean disableBedrockScaffolding = false; + + @JsonProperty("always-quick-change-armor") + private boolean alwaysQuickChangeArmor = false; + @JsonDeserialize(using = EmoteOffhandWorkaroundOption.Deserializer.class) @JsonProperty("emote-offhand-workaround") private EmoteOffhandWorkaroundOption emoteOffhandWorkaround = EmoteOffhandWorkaroundOption.DISABLED; diff --git a/core/src/main/java/org/geysermc/geyser/entity/GeyserDirtyMetadata.java b/core/src/main/java/org/geysermc/geyser/entity/GeyserDirtyMetadata.java index caa373549..f0095d26a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/GeyserDirtyMetadata.java +++ b/core/src/main/java/org/geysermc/geyser/entity/GeyserDirtyMetadata.java @@ -34,7 +34,7 @@ import java.util.Map; /** * A write-only wrapper for temporarily storing entity metadata that will be sent to Bedrock. */ -public class GeyserDirtyMetadata { +public final class GeyserDirtyMetadata { private final Map metadata = new Object2ObjectLinkedOpenHashMap<>(); public void put(EntityData entityData, Object value) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java index 9139e0a99..69aac5a26 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemFrameEntity.java @@ -37,12 +37,11 @@ import com.nukkitx.nbt.NbtMapBuilder; import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; -import com.nukkitx.protocol.bedrock.v465.Bedrock_v465; import lombok.Getter; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.item.ItemTranslator; -import org.geysermc.geyser.registry.type.ItemMapping; import java.util.UUID; @@ -85,10 +84,8 @@ public class ItemFrameEntity extends Entity { .putInt("version", session.getBlockMappings().getBlockStateVersion()); NbtMapBuilder statesBuilder = NbtMap.builder() .putInt("facing_direction", direction.ordinal()) - .putByte("item_frame_map_bit", (byte) 0); - if (session.getUpstream().getProtocolVersion() >= Bedrock_v465.V465_CODEC.getProtocolVersion()) { - statesBuilder.putByte("item_frame_photo_bit", (byte) 0); - } + .putByte("item_frame_map_bit", (byte) 0) + .putByte("item_frame_photo_bit", (byte) 0); blockBuilder.put("states", statesBuilder.build()); bedrockRuntimeId = session.getBlockMappings().getItemFrame(blockBuilder.build()); 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 9980cd2c1..10086be9c 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 @@ -136,7 +136,7 @@ public class ArmorStandEntity extends LivingEntity { } isSmall = newIsSmall; - if (!isMarker) { + if (!isMarker && !isInvisible) { // Addition for isInvisible check caused by https://github.com/GeyserMC/Geyser/issues/2780 toggleSmallStatus(); } } 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 71bab079d..70b5ede99 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 @@ -382,15 +382,26 @@ public class PlayerEntity extends LivingEntity { @Override protected void setDimensions(Pose pose) { float height; + float width; switch (pose) { - case SNEAKING -> height = SNEAKING_POSE_HEIGHT; - case FALL_FLYING, SPIN_ATTACK, SWIMMING -> height = 0.6f; + case SNEAKING -> { + height = SNEAKING_POSE_HEIGHT; + width = definition.width(); + } + case FALL_FLYING, SPIN_ATTACK, SWIMMING -> { + height = 0.6f; + width = definition.width(); + } + case DYING -> { + height = 0.2f; + width = 0.2f; + } default -> { super.setDimensions(pose); return; } } - setBoundingBoxWidth(definition.width()); + setBoundingBoxWidth(width); setBoundingBoxHeight(height); } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/BedrockContainerSlot.java b/core/src/main/java/org/geysermc/geyser/inventory/BedrockContainerSlot.java index e225c5f4d..87c0c92a3 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/BedrockContainerSlot.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/BedrockContainerSlot.java @@ -26,10 +26,6 @@ package org.geysermc.geyser.inventory; import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType; -import lombok.Value; -@Value -public class BedrockContainerSlot { - ContainerSlotType container; - int slot; +public record BedrockContainerSlot(ContainerSlotType container, int slot) { } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Container.java index cf47b8bd6..569802a5a 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Container.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Container.java @@ -27,9 +27,11 @@ package org.geysermc.geyser.inventory; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import lombok.Getter; -import lombok.NonNull; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; +import org.jetbrains.annotations.Range; + +import javax.annotation.Nonnull; /** * Combination of {@link Inventory} and {@link PlayerInventory} @@ -60,7 +62,12 @@ public class Container extends Inventory { } @Override - public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) { + public int getOffsetForHotbar(@Range(from = 0, to = 8) int slot) { + return playerInventory.getOffsetForHotbar(slot) - InventoryTranslator.PLAYER_INVENTORY_OFFSET + this.size; + } + + @Override + public void setItem(int slot, @Nonnull GeyserItemStack newItem, GeyserSession session) { if (slot < this.size) { super.setItem(slot, newItem, session); } else { 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 a78c9cf51..ca7e90a25 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Inventory.java @@ -31,17 +31,19 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.math.vector.Vector3i; import lombok.Getter; -import lombok.NonNull; 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; +import javax.annotation.Nonnull; import java.util.Arrays; @ToString -public class Inventory { - +public abstract class Inventory { @Getter protected final int id; @@ -69,8 +71,7 @@ public class Inventory { protected final ContainerType containerType; @Getter - @Setter - protected String title; + protected final String title; protected final GeyserItemStack[] items; @@ -110,7 +111,9 @@ public class Inventory { return items[slot]; } - public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) { + public abstract int getOffsetForHotbar(@Range(from = 0, to = 8) int slot); + + public void setItem(int slot, @Nonnull GeyserItemStack newItem, GeyserSession session) { if (slot > this.size) { session.getGeyser().getLogger().debug("Tried to set an item out of bounds! " + this); return; @@ -133,7 +136,9 @@ public class Inventory { protected void updateItemNetId(GeyserItemStack oldItem, GeyserItemStack newItem, GeyserSession session) { if (!newItem.isEmpty()) { - if (newItem.getItemData(session).equals(oldItem.getItemData(session), false, false, false)) { + ItemMapping oldMapping = ItemTranslator.getBedrockItemMapping(session, oldItem); + ItemMapping newMapping = ItemTranslator.getBedrockItemMapping(session, newItem); + if (oldMapping.getBedrockId() == newMapping.getBedrockId()) { newItem.setNetId(oldItem.getNetId()); } else { newItem.setNetId(session.getNextItemNetId()); diff --git a/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java b/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java index c4a6a8363..14c796a5f 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java @@ -26,10 +26,12 @@ package org.geysermc.geyser.inventory; import lombok.Getter; -import lombok.NonNull; import lombok.Setter; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; +import org.jetbrains.annotations.Range; + +import javax.annotation.Nonnull; public class PlayerInventory extends Inventory { /** @@ -41,7 +43,7 @@ public class PlayerInventory extends Inventory { private int heldItemSlot; @Getter - @NonNull + @Nonnull private GeyserItemStack cursor = GeyserItemStack.EMPTY; public PlayerInventory() { @@ -49,7 +51,12 @@ public class PlayerInventory extends Inventory { heldItemSlot = 0; } - public void setCursor(@NonNull GeyserItemStack newCursor, GeyserSession session) { + @Override + public int getOffsetForHotbar(@Range(from = 0, to = 8) int slot) { + return slot + 36; + } + + public void setCursor(@Nonnull GeyserItemStack newCursor, GeyserSession session) { updateItemNetId(cursor, newCursor, session); cursor = newCursor; } @@ -62,7 +69,7 @@ public class PlayerInventory extends Inventory { return items[36 + heldItemSlot]; } - public void setItemInHand(@NonNull GeyserItemStack item) { + public void setItemInHand(@Nonnull GeyserItemStack item) { if (36 + heldItemSlot > this.size) { GeyserImpl.getInstance().getLogger().debug("Held item slot was larger than expected!"); return; diff --git a/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java b/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java index 0a1d0a36e..b0cca53d9 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/click/ClickPlan.java @@ -40,20 +40,22 @@ import org.geysermc.geyser.inventory.SlotType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.CraftingInventoryTranslator; import org.geysermc.geyser.translator.inventory.InventoryTranslator; -import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator; import org.geysermc.geyser.util.InventoryUtils; import org.jetbrains.annotations.Contract; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.ListIterator; -public class ClickPlan { +public final class ClickPlan { private final List plan = new ArrayList<>(); private final Int2ObjectMap simulatedItems; + /** + * Used for 1.17.1+ proper packet translation - any non-cursor item that is changed in a single transaction gets sent here. + */ + private Int2ObjectMap changedItems; private GeyserItemStack simulatedCursor; - private boolean simulating; + private boolean finished; private final GeyserSession session; private final InventoryTranslator translator; @@ -66,16 +68,11 @@ public class ClickPlan { this.inventory = inventory; this.simulatedItems = new Int2ObjectOpenHashMap<>(inventory.getSize()); + this.changedItems = null; this.simulatedCursor = session.getPlayerInventory().getCursor().copy(); - this.simulating = true; + this.finished = false; - if (translator instanceof PlayerInventoryTranslator) { - gridSize = 4; - } else if (translator instanceof CraftingInventoryTranslator) { - gridSize = 9; - } else { - gridSize = -1; - } + gridSize = translator.getGridSize(); } private void resetSimulation() { @@ -88,7 +85,7 @@ public class ClickPlan { } public void add(Click click, int slot, boolean force) { - if (!simulating) + if (finished) throw new UnsupportedOperationException("ClickPlan already executed"); if (click == Click.LEFT_OUTSIDE || click == Click.RIGHT_OUTSIDE) { @@ -97,6 +94,8 @@ public class ClickPlan { ClickAction action = new ClickAction(click, slot, force); plan.add(action); + // RUNNING THE SIMULATION HERE IS IMPORTANT. The contents of the simulation are used in complex, multi-stage tasks + // such as autocrafting. simulateAction(action); } @@ -112,33 +111,48 @@ public class ClickPlan { refresh = true; } - //int stateId = stateIdHack(action); + changedItems = new Int2ObjectOpenHashMap<>(); - //simulateAction(action); + boolean emulatePost1_16Logic = session.isEmulatePost1_16Logic(); + + int stateId; + if (emulatePost1_16Logic) { + stateId = stateIdHack(action); + simulateAction(action); + } else { + stateId = inventory.getStateId(); + } ItemStack clickedItemStack; if (!planIter.hasNext() && refresh) { clickedItemStack = InventoryUtils.REFRESH_ITEM; - } else if (action.click.actionType == ContainerActionType.DROP_ITEM || action.slot == Click.OUTSIDE_SLOT) { - clickedItemStack = null; } else { - //// The action must be simulated first as Java expects the new contents of the cursor (as of 1.18.1) - //clickedItemStack = simulatedCursor.getItemStack(); TODO fix - this is the proper behavior but it terribly breaks 1.16.5 - clickedItemStack = getItem(action.slot).getItemStack(); + if (emulatePost1_16Logic) { + // The action must be simulated first as Java expects the new contents of the cursor (as of 1.18.1) + clickedItemStack = simulatedCursor.getItemStack(); + } else { + if (action.click.actionType == ContainerActionType.DROP_ITEM || action.slot == Click.OUTSIDE_SLOT) { + clickedItemStack = null; + } else { + clickedItemStack = getItem(action.slot).getItemStack(); + } + } + } + + if (!emulatePost1_16Logic) { + simulateAction(action); } ServerboundContainerClickPacket clickPacket = new ServerboundContainerClickPacket( inventory.getId(), - inventory.getStateId(), + stateId, action.slot, action.click.actionType, action.click.action, clickedItemStack, - Collections.emptyMap() // Anything else we change, at this time, should have a packet sent to address + changedItems ); - simulateAction(action); - session.sendDownstreamPacket(clickPacket); } @@ -146,19 +160,11 @@ public class ClickPlan { for (Int2ObjectMap.Entry simulatedSlot : simulatedItems.int2ObjectEntrySet()) { inventory.setItem(simulatedSlot.getIntKey(), simulatedSlot.getValue(), session); } - simulating = false; + finished = true; } public GeyserItemStack getItem(int slot) { - return getItem(slot, true); - } - - public GeyserItemStack getItem(int slot, boolean generate) { - if (generate) { - return simulatedItems.computeIfAbsent(slot, k -> inventory.getItem(slot).copy()); - } else { - return simulatedItems.getOrDefault(slot, inventory.getItem(slot)); - } + return simulatedItems.computeIfAbsent(slot, k -> inventory.getItem(slot).copy()); } public GeyserItemStack getCursor() { @@ -166,23 +172,40 @@ public class ClickPlan { } private void setItem(int slot, GeyserItemStack item) { - if (simulating) { - simulatedItems.put(slot, item); - } else { - inventory.setItem(slot, item, session); - } + simulatedItems.put(slot, item); + onSlotItemChange(slot, item); } private void setCursor(GeyserItemStack item) { - if (simulating) { - simulatedCursor = item; - } else { - session.getPlayerInventory().setCursor(item, session); + simulatedCursor = item; + } + + private void add(int slot, GeyserItemStack itemStack, int amount) { + itemStack.add(amount); + onSlotItemChange(slot, itemStack); + } + + private void sub(int slot, GeyserItemStack itemStack, int amount) { + itemStack.sub(amount); + onSlotItemChange(slot, itemStack); + } + + private void setAmount(int slot, GeyserItemStack itemStack, int amount) { + itemStack.setAmount(amount); + onSlotItemChange(slot, itemStack); + } + + /** + * Does not need to be called for the cursor + */ + private void onSlotItemChange(int slot, GeyserItemStack itemStack) { + if (changedItems != null) { + changedItems.put(slot, itemStack.getItemStack()); } } private void simulateAction(ClickAction action) { - GeyserItemStack cursor = simulating ? getCursor() : session.getPlayerInventory().getCursor(); + GeyserItemStack cursor = getCursor(); switch (action.click) { case LEFT_OUTSIDE -> { setCursor(GeyserItemStack.EMPTY); @@ -196,7 +219,7 @@ public class ClickPlan { } } - GeyserItemStack clicked = simulating ? getItem(action.slot) : inventory.getItem(action.slot); + GeyserItemStack clicked = getItem(action.slot); if (translator.getSlotType(action.slot) == SlotType.OUTPUT) { switch (action.click) { case LEFT, RIGHT -> { @@ -206,6 +229,7 @@ public class ClickPlan { cursor.add(clicked.getAmount()); } reduceCraftingGrid(false); + setItem(action.slot, GeyserItemStack.EMPTY); // Matches Java Edition 1.18.1 } case LEFT_SHIFT -> reduceCraftingGrid(true); } @@ -217,55 +241,55 @@ public class ClickPlan { setItem(action.slot, cursor); } else { setCursor(GeyserItemStack.EMPTY); - clicked.add(cursor.getAmount()); + add(action.slot, clicked, cursor.getAmount()); } break; case RIGHT: if (cursor.isEmpty() && !clicked.isEmpty()) { int half = clicked.getAmount() / 2; //smaller half setCursor(clicked.copy(clicked.getAmount() - half)); //larger half - clicked.setAmount(half); + setAmount(action.slot, clicked, half); } else if (!cursor.isEmpty() && clicked.isEmpty()) { cursor.sub(1); setItem(action.slot, cursor.copy(1)); } else if (InventoryUtils.canStack(cursor, clicked)) { cursor.sub(1); - clicked.add(1); + add(action.slot, clicked, 1); } break; case SWAP_TO_HOTBAR_1: - swap(action.slot, 36, clicked); + swap(action.slot, inventory.getOffsetForHotbar(0), clicked); break; case SWAP_TO_HOTBAR_2: - swap(action.slot, 37, clicked); + swap(action.slot, inventory.getOffsetForHotbar(1), clicked); break; case SWAP_TO_HOTBAR_3: - swap(action.slot, 38, clicked); + swap(action.slot, inventory.getOffsetForHotbar(2), clicked); break; case SWAP_TO_HOTBAR_4: - swap(action.slot, 39, clicked); + swap(action.slot, inventory.getOffsetForHotbar(3), clicked); break; case SWAP_TO_HOTBAR_5: - swap(action.slot, 40, clicked); + swap(action.slot, inventory.getOffsetForHotbar(4), clicked); break; case SWAP_TO_HOTBAR_6: - swap(action.slot, 41, clicked); + swap(action.slot, inventory.getOffsetForHotbar(5), clicked); break; case SWAP_TO_HOTBAR_7: - swap(action.slot, 42, clicked); + swap(action.slot, inventory.getOffsetForHotbar(6), clicked); break; case SWAP_TO_HOTBAR_8: - swap(action.slot, 43, clicked); + swap(action.slot, inventory.getOffsetForHotbar(7), clicked); break; case SWAP_TO_HOTBAR_9: - swap(action.slot, 44, clicked); + swap(action.slot, inventory.getOffsetForHotbar(8), clicked); break; case LEFT_SHIFT: //TODO break; case DROP_ONE: if (!clicked.isEmpty()) { - clicked.sub(1); + sub(action.slot, clicked, 1); } break; case DROP_ALL: @@ -279,7 +303,7 @@ public class ClickPlan { * Swap between two inventory slots without a cursor. This should only be used with {@link ContainerActionType#MOVE_TO_HOTBAR_SLOT} */ private void swap(int sourceSlot, int destSlot, GeyserItemStack sourceItem) { - GeyserItemStack destinationItem = simulating ? getItem(destSlot) : inventory.getItem(destSlot); + GeyserItemStack destinationItem = getItem(destSlot); setItem(sourceSlot, destinationItem); setItem(destSlot, sourceItem); } @@ -292,63 +316,44 @@ public class ClickPlan { stateId = inventory.getStateId(); } - // This is a hack. - // Java will never ever send more than one container click packet per set of actions. + // Java will never ever send more than one container click packet per set of actions*. + // *(exception being Java's "quick craft"/painting feature) // Bedrock might, and this would generally fall into one of two categories: // - Bedrock is sending an item directly from one slot to another, without picking it up, that cannot // be expressed with a shift click // - Bedrock wants to pick up or place an arbitrary amount of items that cannot be expressed from // one left/right click action. - // When Bedrock does one of these actions and sends multiple packets, a 1.17.1+ server will - // increment the state ID on each confirmation packet it sends back (I.E. set slot). Then when it - // reads our next packet, because we kept the same state ID but the server incremented it, it'll be - // desynced and send the entire inventory contents back at us. - // This hack therefore increments the state ID to what the server will presumably send back to us. - // (This won't be perfect, but should get us through most vanilla situations, and if this is wrong the - // server will just send a set content packet back at us) + // Java typically doesn't increment the state ID if you send a vanilla-accurate container click packet, + // but it will increment the state ID with a vanilla client in at least the crafting table if (inventory.getContainerType() == ContainerType.CRAFTING && CraftingInventoryTranslator.isCraftingGrid(action.slot)) { // 1.18.1 sends a second set slot update for any action in the crafting grid // And an additional packet if something is removed (Mojmap: CraftingContainer#removeItem) - //TODO this code kind of really sucks; it's potentially possible to see what Bedrock sends us and send a PlaceRecipePacket int stateIdIncrements; GeyserItemStack clicked = getItem(action.slot); if (action.click == Click.LEFT) { if (!clicked.isEmpty() && !InventoryUtils.canStack(simulatedCursor, clicked)) { // An item is removed from the crafting table; yes deletion - stateIdIncrements = 3; + stateIdIncrements = 2; } else { // We can stack and we add all the items to the crafting slot; no deletion - stateIdIncrements = 2; + stateIdIncrements = 1; } } else if (action.click == Click.RIGHT) { - if (simulatedCursor.isEmpty() && !clicked.isEmpty()) { - // Items are taken; yes deletion - stateIdIncrements = 3; - } else if ((!simulatedCursor.isEmpty() && clicked.isEmpty()) || InventoryUtils.canStack(simulatedCursor, clicked)) { - // Adding our cursor item to the slot; no deletion - stateIdIncrements = 2; - } else { - // ?? nothing I guess - stateIdIncrements = 2; - } + stateIdIncrements = 1; + } else if (action.click.actionType == ContainerActionType.MOVE_TO_HOTBAR_SLOT) { + stateIdIncrements = 1; } else { if (session.getGeyser().getConfig().isDebugMode()) { session.getGeyser().getLogger().debug("Not sure how to handle state ID hack in crafting table: " + plan); } - stateIdIncrements = 2; + stateIdIncrements = 1; } inventory.incrementStateId(stateIdIncrements); - } else if (action.click.action instanceof MoveToHotbarAction) { - // Two slot changes sent - inventory.incrementStateId(2); - } else { - inventory.incrementStateId(1); } return stateId; } - //TODO private void reduceCraftingGrid(boolean makeAll) { if (gridSize == -1) return; @@ -370,9 +375,12 @@ public class ClickPlan { } for (int i = 0; i < gridSize; i++) { - GeyserItemStack item = getItem(i + 1); - if (!item.isEmpty()) - item.sub(crafted); + final int slot = i + 1; + GeyserItemStack item = getItem(slot); + if (!item.isEmpty()) { + // These changes should be broadcasted to the server + sub(slot, item, crafted); + } } } @@ -385,6 +393,10 @@ public class ClickPlan { for (ClickAction action : plan) { if (translator.getSlotType(action.slot) == SlotType.NORMAL && action.slot != Click.OUTSIDE_SLOT) { affectedSlots.add(action.slot); + if (action.click.actionType == ContainerActionType.MOVE_TO_HOTBAR_SLOT) { + //TODO won't work if offhand is added + affectedSlots.add(inventory.getOffsetForHotbar(((MoveToHotbarAction) action.click.action).ordinal())); + } } } return affectedSlots; 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 d28b95203..c4bd05b13 100644 --- a/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/MinecraftProtocol.java @@ -28,9 +28,9 @@ package org.geysermc.geyser.network; 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.v465.Bedrock_v465; import com.nukkitx.protocol.bedrock.v471.Bedrock_v471; import com.nukkitx.protocol.bedrock.v475.Bedrock_v475; +import com.nukkitx.protocol.bedrock.v486.Bedrock_v486; import java.util.ArrayList; import java.util.Arrays; @@ -45,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_v475.V475_CODEC; + public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v486.V486_CODEC; /** * A list of all supported Bedrock versions that can join Geyser */ @@ -58,8 +58,8 @@ public final class MinecraftProtocol { private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; static { - SUPPORTED_BEDROCK_CODECS.add(Bedrock_v465.V465_CODEC); SUPPORTED_BEDROCK_CODECS.add(Bedrock_v471.V471_CODEC); + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v475.V475_CODEC.toBuilder().minecraftVersion("1.18.0/1.18.1/1.18.2").build()); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java new file mode 100644 index 000000000..892f4a6df --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java @@ -0,0 +1,122 @@ +/* + * 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.registry; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.geysermc.geyser.registry.loader.RegistryLoader; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +/** + * A mapped registry with an integer as the key. This class is designed to minimize the need for boxing/unboxing keys. + * + * @param the value + */ +public class IntMappedRegistry extends AbstractMappedRegistry> { + protected IntMappedRegistry(I input, RegistryLoader> registryLoader) { + super(input, registryLoader); + } + + /** + * Returns the value registered by the given integer. + * + * @param i the integer + * @return the value registered by the given integer. + */ + public V get(int i) { + return this.mappings.get(i); + } + + @Nullable + @Override + @Deprecated + public V get(Integer key) { + return super.get(key); + } + + /** + * Returns the value registered by the given key or the default value + * specified if null. + * + * @param i the key + * @param defaultValue the default value + * @return the value registered by the given key or the default value + * specified if null. + */ + public V getOrDefault(int i, V defaultValue) { + return this.mappings.getOrDefault(i, defaultValue); + } + + @Override + @Deprecated + public V getOrDefault(Integer key, V defaultValue) { + return super.getOrDefault(key, defaultValue); + } + + /** + * Registers a new value into this registry with the given key. + * + * @param i the key + * @param value the value + * @return a new value into this registry with the given key. + */ + public V register(int i, V value) { + return this.mappings.put(i, value); + } + + @Override + @Deprecated + public V register(Integer key, V value) { + return super.register(key, value); + } + + /** + * Creates a new integer mapped registry with the given {@link RegistryLoader}. The + * input type is not specified here, meaning the loader return type is either + * predefined, or the registry is populated at a later point. + * + * @param registryLoader the registry loader + * @param the input + * @param the map value + * @return a new registry with the given RegistryLoader + */ + public static IntMappedRegistry create(RegistryLoader> registryLoader) { + return new IntMappedRegistry<>(null, registryLoader); + } + + /** + * Creates a new integer mapped registry with the given {@link RegistryLoader} and input. + * + * @param registryLoader the registry loader + * @param the input + * @param the map value + * @return a new registry with the given RegistryLoader supplier + */ + public static IntMappedRegistry create(I input, Supplier>> registryLoader) { + return new IntMappedRegistry<>(input, registryLoader.get()); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index 173bfbd1a..791134aa7 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -44,20 +44,20 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.kyori.adventure.key.Key; import org.geysermc.geyser.api.extension.ExtensionLoader; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.registry.populator.PacketRegistryPopulator; -import org.geysermc.geyser.translator.collision.BlockCollision; import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment; -import org.geysermc.geyser.translator.sound.SoundTranslator; -import org.geysermc.geyser.translator.sound.SoundInteractionTranslator; -import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; -import org.geysermc.geyser.translator.level.event.LevelEventTranslator; import org.geysermc.geyser.registry.loader.*; import org.geysermc.geyser.registry.populator.ItemRegistryPopulator; +import org.geysermc.geyser.registry.populator.PacketRegistryPopulator; import org.geysermc.geyser.registry.populator.RecipeRegistryPopulator; import org.geysermc.geyser.registry.type.EnchantmentData; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ParticleMapping; import org.geysermc.geyser.registry.type.SoundMapping; +import org.geysermc.geyser.translator.collision.BlockCollision; +import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; +import org.geysermc.geyser.translator.level.event.LevelEventTranslator; +import org.geysermc.geyser.translator.sound.SoundInteractionTranslator; +import org.geysermc.geyser.translator.sound.SoundTranslator; import java.util.EnumMap; import java.util.List; @@ -96,7 +96,7 @@ public final class Registries { /** * A mapped registry containing which holds block IDs to its {@link BlockCollision}. */ - public static final SimpleMappedRegistry COLLISIONS = SimpleMappedRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collision.json"), CollisionRegistryLoader::new); + public static final IntMappedRegistry COLLISIONS = IntMappedRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collision.json"), CollisionRegistryLoader::new); /** * A versioned registry which holds a {@link RecipeType} to a corresponding list of {@link CraftingData}. @@ -154,7 +154,7 @@ public final class Registries { * A mapped registry holding the available records, with the ID of the record being the key, and the {@link com.nukkitx.protocol.bedrock.data.SoundEvent} * as the value. */ - public static final SimpleMappedRegistry RECORDS = SimpleMappedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); + public static final IntMappedRegistry RECORDS = IntMappedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); /** * A mapped registry holding sound identifiers to their corresponding {@link SoundMapping}. diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java index c6cd092d4..b74573a4e 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java @@ -50,10 +50,10 @@ import java.util.regex.Pattern; /** * Loads collision data from the given resource path. */ -public class CollisionRegistryLoader extends MultiResourceRegistryLoader> { +public class CollisionRegistryLoader extends MultiResourceRegistryLoader> { @Override - public Map load(Pair input) { + public Int2ObjectMap load(Pair input) { Int2ObjectMap collisions = new Int2ObjectOpenHashMap<>(); Map, CollisionInfo> annotationMap = new IdentityHashMap<>(); 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 b1066c79c..8238bcea1 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 @@ -28,8 +28,8 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableMap; import com.nukkitx.nbt.*; -import com.nukkitx.protocol.bedrock.v465.Bedrock_v465; import com.nukkitx.protocol.bedrock.v471.Bedrock_v471; +import com.nukkitx.protocol.bedrock.v486.Bedrock_v486; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.Object2IntMap; @@ -46,7 +46,10 @@ import org.geysermc.geyser.util.BlockUtils; import java.io.DataInputStream; import java.io.InputStream; -import java.util.*; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; +import java.util.Map; import java.util.function.BiFunction; import java.util.zip.GZIPInputStream; @@ -59,8 +62,34 @@ public class BlockRegistryPopulator { static { ImmutableMap.Builder, BiFunction> stateMapperBuilder = ImmutableMap., BiFunction>builder() - .put(ObjectIntPair.of("1_17_30", Bedrock_v465.V465_CODEC.getProtocolVersion()), EMPTY_MAPPER) - .put(ObjectIntPair.of("1_17_40", Bedrock_v471.V471_CODEC.getProtocolVersion()), EMPTY_MAPPER); + .put(ObjectIntPair.of("1_17_40", Bedrock_v471.V471_CODEC.getProtocolVersion()), EMPTY_MAPPER) + .put(ObjectIntPair.of("1_18_10", Bedrock_v486.V486_CODEC.getProtocolVersion()), (bedrockIdentifier, statesBuilder) -> { + statesBuilder.remove("no_drop_bit"); // Used in skulls + if (bedrockIdentifier.equals("minecraft:glow_lichen")) { + // Moved around north, south, west + int bits = (int) statesBuilder.get("multi_face_direction_bits"); + boolean north = (bits & (1 << 2)) != 0; + boolean south = (bits & (1 << 3)) != 0; + boolean west = (bits & (1 << 4)) != 0; + if (north) { + bits |= 1 << 4; + } else { + bits &= ~(1 << 4); + } + if (south) { + bits |= 1 << 2; + } else { + bits &= ~(1 << 2); + } + if (west) { + bits |= 1 << 3; + } else { + bits &= ~(1 << 3); + } + statesBuilder.put("multi_face_direction_bits", bits); + } + return null; + }); BLOCK_MAPPERS = stateMapperBuilder.build(); } 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 d448bfa6a..1b56a83de 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 @@ -35,9 +35,9 @@ import com.nukkitx.protocol.bedrock.data.SoundEvent; import com.nukkitx.protocol.bedrock.data.inventory.ComponentItemData; import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.StartGamePacket; -import com.nukkitx.protocol.bedrock.v465.Bedrock_v465; import com.nukkitx.protocol.bedrock.v471.Bedrock_v471; import com.nukkitx.protocol.bedrock.v475.Bedrock_v475; +import com.nukkitx.protocol.bedrock.v486.Bedrock_v486; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; @@ -63,9 +63,9 @@ public class ItemRegistryPopulator { static { PALETTE_VERSIONS = new Object2ObjectOpenHashMap<>(); - PALETTE_VERSIONS.put("1_17_30", new PaletteVersion(Bedrock_v465.V465_CODEC.getProtocolVersion(), Collections.emptyMap())); PALETTE_VERSIONS.put("1_17_40", new PaletteVersion(Bedrock_v471.V471_CODEC.getProtocolVersion(), Collections.emptyMap())); PALETTE_VERSIONS.put("1_18_0", new PaletteVersion(Bedrock_v475.V475_CODEC.getProtocolVersion(), Collections.emptyMap())); + PALETTE_VERSIONS.put("1_18_10", new PaletteVersion(Bedrock_v486.V486_CODEC.getProtocolVersion(), Collections.emptyMap())); } private record PaletteVersion(int protocolVersion, Map additionalTranslatedItems) { 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 591934d6d..c79980f6f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -38,10 +38,14 @@ import com.github.steveice10.mc.protocol.data.ProtocolState; import com.github.steveice10.mc.protocol.data.UnexpectedEncryptionException; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.entity.player.HandPreference; import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; +import com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility; +import com.github.steveice10.mc.protocol.data.game.setting.SkinPart; import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic; import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientInformationPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket; @@ -245,7 +249,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private Vector2i lastChunkPosition = null; - private int renderDistance; + @Setter + private int clientRenderDistance = -1; + private int serverRenderDistance; // Exposed for GeyserConnect usage protected boolean sentSpawnPacket; @@ -355,6 +361,15 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private Int2ObjectMap stonecutterRecipes; + /** + * 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 + * contents before any transaction is done. With the current ViaVersion structure, if we do not send what 1.16 expects + * and send multiple click container packets, then successive transactions will be rejected. + */ + @Setter + private boolean emulatePost1_16Logic = true; + /** * The current attack speed of the player. Used for sending proper cooldown timings. * Setting a default fixes cooldowns not showing up on a fresh world. @@ -790,6 +805,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { FloodgateSkinUploader skinUploader = geyser.getSkinUploader(); FloodgateCipher cipher = geyser.getCipher(); + String bedrockAddress = upstream.getAddress().getAddress().getHostAddress(); + // both BungeeCord and Velocity remove the IPv6 scope (if there is one) for Spigot + int ipv6ScopeIndex = bedrockAddress.indexOf('%'); + if (ipv6ScopeIndex != -1) { + bedrockAddress = bedrockAddress.substring(0, ipv6ScopeIndex); + } + encryptedData = cipher.encryptFromString(BedrockData.of( clientData.getGameVersion(), authData.name(), @@ -798,7 +820,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { clientData.getLanguageCode(), clientData.getUiProfile().ordinal(), clientData.getCurrentInputMode().ordinal(), - upstream.getAddress().getAddress().getHostAddress(), + bedrockAddress, skinUploader.getId(), skinUploader.getVerifyCode() ).toString()); @@ -1160,9 +1182,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { return clientData.getLanguageCode(); } - public void setRenderDistance(int renderDistance) { + public void setServerRenderDistance(int renderDistance) { renderDistance = GenericMath.ceil(++renderDistance * MathUtils.SQRT_OF_TWO); //square to circle - this.renderDistance = renderDistance; + this.serverRenderDistance = renderDistance; ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket(); chunkRadiusUpdatedPacket.setRadius(renderDistance); @@ -1420,6 +1442,27 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { sendUpstreamPacket(adventureSettingsPacket); } + private int getRenderDistance() { + if (clientRenderDistance != -1) { + // The client has sent a render distance + return clientRenderDistance; + } + return serverRenderDistance; + } + + // We need to send our skin parts to the server otherwise java sees us with no hat, jacket etc + private static final List SKIN_PARTS = Arrays.asList(SkinPart.values()); + + /** + * Send a packet to the server to indicate client render distance, locale, skin parts, and hand preference. + */ + public void sendJavaClientSettings() { + ServerboundClientInformationPacket clientSettingsPacket = new ServerboundClientInformationPacket(locale(), + getRenderDistance(), ChatVisibility.FULL, true, SKIN_PARTS, + HandPreference.RIGHT_HAND, false, true); + sendDownstreamPacket(clientSettingsPacket); + } + /** * 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/LodestoneCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java index f0cbbb189..05c2628df 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/LodestoneCache.java @@ -30,9 +30,6 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; -import lombok.Getter; import org.geysermc.geyser.inventory.GeyserItemStack; import javax.annotation.Nullable; @@ -43,7 +40,7 @@ import java.util.WeakHashMap; * A temporary cache for lodestone information. * Bedrock requests the lodestone position information separately from the item. */ -public class LodestoneCache { +public final class LodestoneCache { /** * A list of any GeyserItemStacks that are lodestones. Used mainly to minimize Bedrock's "pop-in" effect * when a new item has been created; instead we can re-use already existing IDs @@ -121,8 +118,16 @@ public class LodestoneCache { } public @Nullable LodestonePos getPos(int id) { - // We should not need to check the activeLodestones map as Bedrock should already be aware of this ID - return this.lodestones.remove(id); + LodestonePos pos = this.lodestones.remove(id); + if (pos != null) { + return pos; + } + for (LodestonePos activePos : this.activeLodestones.values()) { + if (activePos.id == id) { + return activePos; + } + } + return null; } public void clear() { @@ -131,16 +136,7 @@ public class LodestoneCache { this.lodestones.clear(); } - @Getter - @AllArgsConstructor - @EqualsAndHashCode - public static class LodestonePos { - private final int id; - private final int x; - private final int y; - private final int z; - private final String dimension; - + public record LodestonePos(int id, int x, int y, int z, String dimension) { boolean equals(int x, int y, int z, String dimension) { return this.x == x && this.y == y && this.z == z && this.dimension.equals(dimension); } diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java index 67364f5c6..4383dc4e9 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -115,10 +115,12 @@ public class SkinProvider { WEARING_CUSTOM_SKULL = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkull\"}}", wearingCustomSkull, false); String wearingCustomSkullSlim = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json"), StandardCharsets.UTF_8); WEARING_CUSTOM_SKULL_SLIM = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkullSlim\"}}", wearingCustomSkullSlim, false); + } + public static void registerCacheImageTask(GeyserImpl geyser) { // Schedule Daily Image Expiry if we are caching them - if (GeyserImpl.getInstance().getConfig().getCacheImages() > 0) { - GeyserImpl.getInstance().getScheduledThread().scheduleAtFixedRate(() -> { + if (geyser.getConfig().getCacheImages() > 0) { + geyser.getScheduledThread().scheduleAtFixedRate(() -> { File cacheFolder = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("images").toFile(); if (!cacheFolder.exists()) { return; 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 f6abdfcd2..f194d0d3f 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 @@ -38,17 +38,16 @@ import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequ import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket; +import it.unimi.dsi.fastutil.ints.IntSets; import org.geysermc.geyser.inventory.BeaconContainer; +import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.PlayerInventory; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InventoryUtils; -import java.util.Collections; - public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator { public BeaconInventoryTranslator() { super(1, new BlockInventoryHolder("minecraft:beacon", com.nukkitx.protocol.bedrock.data.inventory.ContainerType.BEACON) { @@ -104,7 +103,7 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator } @Override - public boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { + protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { return action.getType() == StackRequestActionType.BEACON_PAYMENT; } @@ -114,7 +113,7 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator BeaconPaymentStackRequestActionData beaconPayment = (BeaconPaymentStackRequestActionData) request.getActions()[0]; ServerboundSetBeaconPacket packet = new ServerboundSetBeaconPacket(beaconPayment.getPrimaryEffect(), beaconPayment.getSecondaryEffect()); session.sendDownstreamPacket(packet); - return acceptRequest(request, makeContainerEntries(session, inventory, Collections.emptySet())); + return acceptRequest(request, makeContainerEntries(session, inventory, IntSets.emptySet())); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java index ec3335f3c..61e2258b6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java @@ -37,6 +37,11 @@ public class CraftingInventoryTranslator extends AbstractBlockInventoryTranslato super(10, "minecraft:crafting_table", ContainerType.WORKBENCH, UIInventoryUpdater.INSTANCE); } + @Override + public int getGridSize() { + return 9; + } + @Override public SlotType getSlotType(int javaSlot) { if (javaSlot == 0) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java index 97b78aec5..800b35901 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java @@ -27,23 +27,22 @@ package org.geysermc.geyser.translator.inventory; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; -import com.nukkitx.protocol.bedrock.data.inventory.*; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType; +import com.nukkitx.protocol.bedrock.data.inventory.EnchantOptionData; +import com.nukkitx.protocol.bedrock.data.inventory.ItemStackRequest; +import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeStackRequestActionData; import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData; import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType; import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket; import com.nukkitx.protocol.bedrock.packet.PlayerEnchantOptionsPacket; -import org.geysermc.geyser.inventory.EnchantingContainer; -import org.geysermc.geyser.inventory.GeyserEnchantOption; -import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.inventory.PlayerInventory; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.inventory.BedrockContainerSlot; -import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import it.unimi.dsi.fastutil.ints.IntSets; +import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.item.Enchantment; +import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.session.GeyserSession; import java.util.Arrays; -import java.util.Collections; public class EnchantingInventoryTranslator extends AbstractBlockInventoryTranslator { public EnchantingInventoryTranslator() { @@ -104,7 +103,7 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla } @Override - public boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { + protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { return action.getType() == StackRequestActionType.CRAFT_RECIPE; } @@ -130,7 +129,7 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla } ServerboundContainerButtonClickPacket packet = new ServerboundContainerButtonClickPacket(inventory.getId(), javaSlot); session.sendDownstreamPacket(packet); - return acceptRequest(request, makeContainerEntries(session, inventory, Collections.emptySet())); + return acceptRequest(request, makeContainerEntries(session, inventory, IntSets.emptySet())); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 8318e18f6..e6a9faf74 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -26,12 +26,11 @@ package org.geysermc.geyser.translator.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; -import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType; @@ -43,15 +42,10 @@ import it.unimi.dsi.fastutil.ints.*; import lombok.AllArgsConstructor; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.CartographyContainer; -import org.geysermc.geyser.inventory.GeyserItemStack; -import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.inventory.PlayerInventory; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.inventory.BedrockContainerSlot; -import org.geysermc.geyser.inventory.SlotType; +import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.click.Click; import org.geysermc.geyser.inventory.click.ClickPlan; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator; import org.geysermc.geyser.translator.inventory.chest.SingleChestInventoryTranslator; import org.geysermc.geyser.translator.inventory.furnace.BlastFurnaceInventoryTranslator; @@ -119,6 +113,13 @@ public abstract class InventoryTranslator { public abstract SlotType getSlotType(int javaSlot); public abstract Inventory createInventory(String name, int windowId, ContainerType containerType, PlayerInventory playerInventory); + /** + * Used for crafting-related transactions. Will override in PlayerInventoryTranslator and CraftingInventoryTranslator. + */ + public int getGridSize() { + return -1; + } + /** * Should be overwritten in cases where specific inventories should reject an item being in a specific spot. * For examples, looms use this to reject items that are dyes in Bedrock but not in Java. @@ -136,7 +137,7 @@ public abstract class InventoryTranslator { * Should be overrided if this request matches a certain criteria and shouldn't be treated normally. * E.G. anvil renaming or enchanting */ - public boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { + protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { return false; } @@ -147,7 +148,7 @@ public abstract class InventoryTranslator { return rejectRequest(request); } - public void translateRequests(GeyserSession session, Inventory inventory, List requests) { + public final void translateRequests(GeyserSession session, Inventory inventory, List requests) { boolean refresh = false; ItemStackResponsePacket responsePacket = new ItemStackResponsePacket(); for (ItemStackRequest request : requests) { @@ -199,10 +200,6 @@ public abstract class InventoryTranslator { case PLACE: { TransferStackRequestActionData transferAction = (TransferStackRequestActionData) action; if (!(checkNetId(session, inventory, transferAction.getSource()) && checkNetId(session, inventory, transferAction.getDestination()))) { - if (session.getGameMode().equals(GameMode.CREATIVE) && transferAction.getSource().getContainer() == ContainerSlotType.CRAFTING_INPUT && - transferAction.getSource().getSlot() >= 28 && transferAction.getSource().getSlot() <= 31) { - return rejectRequest(request, false); - } if (session.getGeyser().getConfig().isDebugMode()) { session.getGeyser().getLogger().error("DEBUG: About to reject TAKE/PLACE request made by " + session.name()); dumpStackRequestDetails(session, inventory, transferAction.getSource(), transferAction.getDestination()); @@ -212,17 +209,19 @@ public abstract class InventoryTranslator { int sourceSlot = bedrockSlotToJava(transferAction.getSource()); int destSlot = bedrockSlotToJava(transferAction.getDestination()); + boolean isSourceCursor = isCursor(transferAction.getSource()); + boolean isDestCursor = isCursor(transferAction.getDestination()); if (shouldRejectItemPlace(session, inventory, transferAction.getSource().getContainer(), - isCursor(transferAction.getSource()) ? -1 : sourceSlot, - transferAction.getDestination().getContainer(), isCursor(transferAction.getDestination()) ? -1 : destSlot)) { + isSourceCursor ? -1 : sourceSlot, + transferAction.getDestination().getContainer(), isDestCursor ? -1 : destSlot)) { // This item would not be here in Java return rejectRequest(request, false); } - if (isCursor(transferAction.getSource()) && isCursor(transferAction.getDestination())) { //??? + if (isSourceCursor && isDestCursor) { //??? return rejectRequest(request); - } else if (isCursor(transferAction.getSource())) { //releasing cursor + } else if (isSourceCursor) { //releasing cursor int sourceAmount = cursor.getAmount(); if (transferAction.getCount() == sourceAmount) { //release all plan.add(Click.LEFT, destSlot); @@ -231,7 +230,7 @@ public abstract class InventoryTranslator { plan.add(Click.RIGHT, destSlot); } } - } else if (isCursor(transferAction.getDestination())) { //picking up into cursor + } else if (isDestCursor) { //picking up into cursor GeyserItemStack sourceItem = plan.getItem(sourceSlot); int sourceAmount = sourceItem.getAmount(); if (cursor.isEmpty()) { //picking up into empty cursor @@ -313,18 +312,7 @@ public abstract class InventoryTranslator { if (!isSourceCursor && destination.getContainer() == ContainerSlotType.HOTBAR || destination.getContainer() == ContainerSlotType.HOTBAR_AND_INVENTORY) { // Tell the server we're pressing one of the hotbar keys to save clicks - Click click = switch (destination.getSlot()) { - case 0 -> Click.SWAP_TO_HOTBAR_1; - case 1 -> Click.SWAP_TO_HOTBAR_2; - case 2 -> Click.SWAP_TO_HOTBAR_3; - case 3 -> Click.SWAP_TO_HOTBAR_4; - case 4 -> Click.SWAP_TO_HOTBAR_5; - case 5 -> Click.SWAP_TO_HOTBAR_6; - case 6 -> Click.SWAP_TO_HOTBAR_7; - case 7 -> Click.SWAP_TO_HOTBAR_8; - case 8 -> Click.SWAP_TO_HOTBAR_9; - default -> null; - }; + Click click = InventoryUtils.getClickForHotbarSwap(destination.getSlot()); if (click != null) { plan.add(click, sourceSlot); break; @@ -442,6 +430,8 @@ public abstract class InventoryTranslator { int leftover = 0; ClickPlan plan = new ClickPlan(session, this, inventory); + // Track all the crafting table slots to report back the contents of the slots after crafting + IntSet affectedSlots = new IntOpenHashSet(); for (StackRequestActionData action : request.getActions()) { switch (action.getType()) { case CRAFT_RECIPE: { @@ -473,6 +463,7 @@ public abstract class InventoryTranslator { return rejectRequest(request); } craftState = CraftState.INGREDIENTS; + affectedSlots.add(bedrockSlotToJava(((ConsumeStackRequestActionData) action).getSource())); break; } case TAKE: @@ -533,21 +524,16 @@ public abstract class InventoryTranslator { } } plan.execute(false); - return acceptRequest(request, makeContainerEntries(session, inventory, plan.getAffectedSlots())); + affectedSlots.addAll(plan.getAffectedSlots()); + return acceptRequest(request, makeContainerEntries(session, inventory, affectedSlots)); } public ItemStackResponsePacket.Response translateAutoCraftingRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { - int gridSize; - int gridDimensions; - if (this instanceof PlayerInventoryTranslator) { - gridSize = 4; - gridDimensions = 2; - } else if (this instanceof CraftingInventoryTranslator) { - gridSize = 9; - gridDimensions = 3; - } else { + final int gridSize = getGridSize(); + if (gridSize == -1) { return rejectRequest(request); } + int gridDimensions = gridSize == 4 ? 2 : 3; Recipe recipe; Ingredient[] ingredients = new Ingredient[0]; @@ -733,7 +719,7 @@ public abstract class InventoryTranslator { /** * Handled in {@link PlayerInventoryTranslator} */ - public ItemStackResponsePacket.Response translateCreativeRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { + protected ItemStackResponsePacket.Response translateCreativeRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { return rejectRequest(request); } @@ -768,14 +754,14 @@ public abstract class InventoryTranslator { } } - public static ItemStackResponsePacket.Response acceptRequest(ItemStackRequest request, List containerEntries) { + protected static ItemStackResponsePacket.Response acceptRequest(ItemStackRequest request, List containerEntries) { return new ItemStackResponsePacket.Response(ItemStackResponsePacket.ResponseStatus.OK, request.getRequestId(), containerEntries); } /** * Reject an incorrect ItemStackRequest. */ - public static ItemStackResponsePacket.Response rejectRequest(ItemStackRequest request) { + protected static ItemStackResponsePacket.Response rejectRequest(ItemStackRequest request) { return rejectRequest(request, true); } @@ -785,7 +771,7 @@ public abstract class InventoryTranslator { * @param throwError whether this request was truly erroneous (true), or known as an outcome and should not be treated * as bad (false). */ - public static ItemStackResponsePacket.Response rejectRequest(ItemStackRequest request, boolean throwError) { + protected static ItemStackResponsePacket.Response rejectRequest(ItemStackRequest request, boolean throwError) { if (throwError && GeyserImpl.getInstance().getConfig().isDebugMode()) { new Throwable("DEBUGGING: ItemStackRequest rejected " + request.toString()).printStackTrace(); } @@ -860,12 +846,15 @@ public abstract class InventoryTranslator { return -1; } - public List makeContainerEntries(GeyserSession session, Inventory inventory, Set affectedSlots) { + protected final List makeContainerEntries(GeyserSession session, Inventory inventory, IntSet affectedSlots) { Map> containerMap = new HashMap<>(); - for (int slot : affectedSlots) { + // Manually call iterator to prevent Integer boxing + IntIterator it = affectedSlots.iterator(); + while (it.hasNext()) { + int slot = it.nextInt(); BedrockContainerSlot bedrockSlot = javaSlotToBedrockContainer(slot); - List list = containerMap.computeIfAbsent(bedrockSlot.getContainer(), k -> new ArrayList<>()); - list.add(makeItemEntry(session, bedrockSlot.getSlot(), inventory.getItem(slot))); + List list = containerMap.computeIfAbsent(bedrockSlot.container(), k -> new ArrayList<>()); + list.add(makeItemEntry(session, bedrockSlot.slot(), inventory.getItem(slot))); } List containerEntries = new ArrayList<>(); @@ -879,7 +868,7 @@ public abstract class InventoryTranslator { return containerEntries; } - public static ItemStackResponsePacket.ItemEntry makeItemEntry(GeyserSession session, int bedrockSlot, GeyserItemStack itemStack) { + private static ItemStackResponsePacket.ItemEntry makeItemEntry(GeyserSession session, int bedrockSlot, GeyserItemStack itemStack) { ItemStackResponsePacket.ItemEntry itemEntry; if (!itemStack.isEmpty()) { // As of 1.16.210: Bedrock needs confirmation on what the current item durability is. 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 acdaaf4c1..a862a7e0d 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 @@ -117,7 +117,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { } @Override - public boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { + 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) diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java index 04de68a1e..e2349e5a5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java @@ -35,6 +35,7 @@ import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.*; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket; +import it.unimi.dsi.fastutil.ints.IntIterator; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import org.geysermc.geyser.inventory.*; @@ -55,6 +56,11 @@ public class PlayerInventoryTranslator extends InventoryTranslator { super(46); } + @Override + public int getGridSize() { + return 4; + } + @Override public void updateInventory(GeyserSession session, Inventory inventory) { updateCraftingGrid(session, inventory); @@ -370,14 +376,17 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } } } - for (int slot : affectedSlots) { + // Manually call iterator to prevent Integer boxing + IntIterator it = affectedSlots.iterator(); + while (it.hasNext()) { + int slot = it.nextInt(); sendCreativeAction(session, inventory, slot); } return acceptRequest(request, makeContainerEntries(session, inventory, affectedSlots)); } @Override - public ItemStackResponsePacket.Response translateCreativeRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { + protected ItemStackResponsePacket.Response translateCreativeRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { ItemStack javaCreativeItem = null; IntSet affectedSlots = new IntOpenHashSet(); CraftState craftState = CraftState.START; @@ -478,7 +487,10 @@ public class PlayerInventoryTranslator extends InventoryTranslator { return rejectRequest(request); } } - for (int slot : affectedSlots) { + // Manually call iterator to prevent Integer boxing + IntIterator it = affectedSlots.iterator(); + while (it.hasNext()) { + int slot = it.nextInt(); sendCreativeAction(session, inventory, slot); } return acceptRequest(request, makeContainerEntries(session, inventory, affectedSlots)); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java index 3bc881696..ae25a9ffd 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java @@ -52,7 +52,7 @@ public class StonecutterInventoryTranslator extends AbstractBlockInventoryTransl } @Override - public boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { + protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { // First is pre-1.18. TODO remove after 1.17.40 support is dropped and refactor stonecutter support to use CraftRecipeStackRequestActionData's recipe ID return action.getType() == StackRequestActionType.CRAFT_NON_IMPLEMENTED_DEPRECATED || action.getType() == StackRequestActionType.CRAFT_RECIPE; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/BannerTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/BannerTranslator.java index 3c566e76c..a5c3235a2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/BannerTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/BannerTranslator.java @@ -155,7 +155,7 @@ public class BannerTranslator extends ItemTranslator { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { + protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { if (itemStack.getNbt() == null) { return super.translateToBedrock(itemStack, mapping, mappings); } @@ -163,9 +163,7 @@ public class BannerTranslator extends ItemTranslator { ItemData.Builder builder = super.translateToBedrock(itemStack, mapping, mappings); CompoundTag blockEntityTag = itemStack.getNbt().get("BlockEntityTag"); - if (blockEntityTag != null && blockEntityTag.contains("Patterns")) { - ListTag patterns = blockEntityTag.get("Patterns"); - + if (blockEntityTag != null && blockEntityTag.get("Patterns") instanceof ListTag patterns) { NbtMapBuilder nbtBuilder = builder.build().getTag().toBuilder(); //TODO fix ugly hack if (patterns.equals(OMINOUS_BANNER_PATTERN)) { // Remove the current patterns and set the ominous banner type diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java index 65f26542f..9637f1aa9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/CompassTranslator.java @@ -26,7 +26,9 @@ 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.*; +import com.github.steveice10.opennbt.tag.builtin.ByteTag; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.network.MinecraftProtocol; import org.geysermc.geyser.registry.Registries; @@ -51,19 +53,30 @@ public class CompassTranslator extends ItemTranslator { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { - if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, mapping, mappings); - - Tag lodestoneTag = itemStack.getNbt().get("LodestoneTracked"); - if (lodestoneTag instanceof ByteTag) { - // Get the fake lodestonecompass entry - mapping = mappings.getStoredItems().lodestoneCompass(); - // NBT will be translated in nbt/LodestoneCompassTranslator + protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { + if (isLodestoneCompass(itemStack.getNbt())) { + // NBT will be translated in nbt/LodestoneCompassTranslator if applicable + return super.translateToBedrock(itemStack, mappings.getStoredItems().lodestoneCompass(), mappings); } - return super.translateToBedrock(itemStack, mapping, mappings); } + @Override + protected ItemMapping getItemMapping(int javaId, CompoundTag nbt, ItemMappings mappings) { + if (isLodestoneCompass(nbt)) { + return mappings.getStoredItems().lodestoneCompass(); + } + return super.getItemMapping(javaId, nbt, mappings); + } + + private boolean isLodestoneCompass(CompoundTag nbt) { + if (nbt != null) { + Tag lodestoneTag = nbt.get("LodestoneTracked"); + return lodestoneTag instanceof ByteTag; + } + return false; + } + @Override public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) { if (mapping.getBedrockIdentifier().equals("minecraft:lodestone_compass")) { 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 34e9364ce..c8e492634 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 @@ -37,6 +37,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; @@ -157,18 +158,13 @@ public abstract class ItemTranslator { nbt = translateDisplayProperties(session, nbt, bedrockItem); if (session.isAdvancedTooltips()) { - nbt = addAdvancedTooltips(nbt, session.getItemMappings().getMapping(stack), session.locale()); + nbt = addAdvancedTooltips(nbt, bedrockItem, session.locale()); } ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), nbt); - ItemData.Builder builder; - ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(bedrockItem.getJavaId()); - if (itemStackTranslator != null) { - builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); - } else { - builder = DEFAULT_TRANSLATOR.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); - } + ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(bedrockItem.getJavaId(), DEFAULT_TRANSLATOR); + ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); if (bedrockItem.isBlock()) { builder.blockRuntimeId(bedrockItem.getBedrockBlockId()); } @@ -263,6 +259,19 @@ public abstract class ItemTranslator { return canModifyBedrock; } + /** + * Given an item stack, determine the item mapping that should be applied to Bedrock players. + */ + @Nonnull + public static ItemMapping getBedrockItemMapping(GeyserSession session, @Nonnull GeyserItemStack itemStack) { + if (itemStack.isEmpty()) { + return ItemMapping.AIR; + } + int javaId = itemStack.getJavaId(); + return ITEM_STACK_TRANSLATORS.getOrDefault(javaId, DEFAULT_TRANSLATOR) + .getItemMapping(javaId, itemStack.getNbt(), session.getItemMappings()); + } + private static final ItemTranslator DEFAULT_TRANSLATOR = new ItemTranslator() { @Override public List getAppliedItems() { @@ -270,7 +279,7 @@ public abstract class ItemTranslator { } }; - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { + protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { if (itemStack == null) { // Return, essentially, air return ItemData.builder(); @@ -295,6 +304,10 @@ public abstract class ItemTranslator { public abstract List getAppliedItems(); + protected ItemMapping getItemMapping(int javaId, CompoundTag nbt, ItemMappings mappings) { + return mappings.getMapping(javaId); + } + public NbtMap translateNbtToBedrock(CompoundTag tag) { NbtMapBuilder builder = NbtMap.builder(); if (tag.getValue() != null && !tag.getValue().isEmpty()) { @@ -469,9 +482,8 @@ public abstract class ItemTranslator { public static CompoundTag translateDisplayProperties(GeyserSession session, CompoundTag tag, ItemMapping mapping, char translationColor) { boolean hasCustomName = false; if (tag != null) { - CompoundTag display = tag.get("display"); - if (display != null && display.contains("Name")) { - String name = ((StringTag) display.get("Name")).getValue(); + if (tag.get("display") instanceof CompoundTag display && display.get("Name") instanceof StringTag tagName) { + String name = tagName.getValue(); // Get the translated name and prefix it with a reset char name = MessageTranslator.convertMessageLenient(name, session.locale()); @@ -491,8 +503,10 @@ public abstract class ItemTranslator { if (tag == null) { tag = new CompoundTag(""); } - CompoundTag display = tag.get("display"); - if (display == null) { + CompoundTag display; + if (tag.get("display") instanceof CompoundTag oldDisplay) { + display = oldDisplay; + } else { display = new CompoundTag("display"); // Add to the new root tag tag.put(display); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java index 272092da6..54a6deadb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/PotionTranslator.java @@ -54,7 +54,7 @@ public class PotionTranslator extends ItemTranslator { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { + protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, mapping, mappings); Tag potionTag = itemStack.getNbt().get("Potion"); if (potionTag instanceof StringTag) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java index 4925d3e69..35e8baa07 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/TippedArrowTranslator.java @@ -59,7 +59,7 @@ public class TippedArrowTranslator extends ItemTranslator { } @Override - public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { + protected ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) { if (!mapping.getJavaIdentifier().equals("minecraft:tipped_arrow") || itemStack.getNbt() == null) { // We're only concerned about minecraft:arrow when translating Bedrock -> Java return super.translateToBedrock(itemStack, mapping, mappings); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BasicItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BasicItemTranslator.java index d50a8c579..72ef0cf0a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BasicItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/nbt/BasicItemTranslator.java @@ -51,13 +51,11 @@ public class BasicItemTranslator extends NbtItemStackTranslator { } } - CompoundTag displayTag = itemTag.get("display"); - if (displayTag == null) { + if (!(itemTag.get("display") instanceof CompoundTag displayTag)) { return; } - Tag loreTag = displayTag.get("Lore"); - if (loreTag instanceof ListTag listTag) { + if (displayTag.get("Lore") instanceof ListTag listTag) { List lore = new ArrayList<>(); for (Tag tag : listTag.getValue()) { if (!(tag instanceof StringTag)) continue; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java index 93ce71a3d..d00914fb1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockEntityDataTranslator.java @@ -41,12 +41,14 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator SignUtils.JAVA_CHARACTER_WIDTH_MAX) { @@ -111,7 +113,7 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator { + Vector3i blockPos = BlockUtils.getBlockPosition(packet.getBlockPosition(), packet.getBlockFace()); + + if (session.getGeyser().getConfig().isDisableBedrockScaffolding()) { + float yaw = session.getPlayerEntity().getYaw(); + boolean isGodBridging = switch (packet.getBlockFace()) { + case 2 -> yaw <= -135f || yaw > 135f; + case 3 -> yaw <= 45f && yaw > -45f; + case 4 -> yaw > 45f && yaw <= 135f; + case 5 -> yaw <= -45f && yaw > -135f; + default -> false; + }; + if (isGodBridging) { + restoreCorrectBlock(session, blockPos, packet); + return; + } + } + // Check to make sure the client isn't spamming interaction // Based on Nukkit 1.0, with changes to ensure holding down still works boolean hasAlreadyClicked = System.currentTimeMillis() - session.getLastInteractionTime() < 110.0 && @@ -138,7 +163,6 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { - if (packet.getActions().size() == 1 && packet.getLegacySlots().size() > 0) { - InventoryActionData actionData = packet.getActions().get(0); - LegacySetItemSlotData slotData = packet.getLegacySlots().get(0); - if (slotData.getContainerId() == 6 && actionData.getToItem().getId() != 0) { - // The player is trying to swap out an armor piece that already has an item in it - // Java Edition does not allow this; let's revert it - session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory()); - } - } - // Handled when sneaking if (session.getPlayerInventory().getItemInHand().getJavaId() == mappings.getStoredItems().shield().getJavaId()) { break; @@ -282,6 +296,43 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator legacySlots = packet.getLegacySlots(); + if (packet.getActions().size() == 1 && legacySlots.size() > 0) { + InventoryActionData actionData = packet.getActions().get(0); + LegacySetItemSlotData slotData = legacySlots.get(0); + if (slotData.getContainerId() == 6 && actionData.getToItem().getId() != 0) { + // The player is trying to swap out an armor piece that already has an item in it + if (session.getGeyser().getConfig().isAlwaysQuickChangeArmor()) { + // Java doesn't know when a player is in its own inventory and not, so we + // can abuse this feature to send a swap inventory packet + int bedrockHotbarSlot = packet.getHotbarSlot(); + Click click = InventoryUtils.getClickForHotbarSwap(bedrockHotbarSlot); + if (click != null && slotData.getSlots().length != 0) { + Inventory playerInventory = session.getPlayerInventory(); + // Bedrock sends us the index of the slot in the armor container; armor in Java + // Edition is offset by 5 in the player inventory + int armorSlot = slotData.getSlots()[0] + 5; + GeyserItemStack armorSlotItem = playerInventory.getItem(armorSlot); + GeyserItemStack hotbarItem = playerInventory.getItem(playerInventory.getOffsetForHotbar(bedrockHotbarSlot)); + playerInventory.setItem(armorSlot, hotbarItem, session); + playerInventory.setItem(bedrockHotbarSlot, armorSlotItem, session); + + Int2ObjectMap changedSlots = new Int2ObjectOpenHashMap<>(2); + changedSlots.put(armorSlot, hotbarItem.getItemStack()); + changedSlots.put(bedrockHotbarSlot, armorSlotItem.getItemStack()); + + ServerboundContainerClickPacket clickPacket = new ServerboundContainerClickPacket( + playerInventory.getId(), playerInventory.getStateId(), armorSlot, + click.actionType, click.action, null, changedSlots); + session.sendDownstreamPacket(clickPacket); + } + } else { + // Disallowed; let's revert + session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory()); + } + } + } } case 2 -> { int blockState = session.getGameMode() == GameMode.CREATIVE ? diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPositionTrackingDBClientRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPositionTrackingDBClientRequestTranslator.java index a6551afbd..f3d0ff344 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPositionTrackingDBClientRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockPositionTrackingDBClientRequestTranslator.java @@ -58,14 +58,14 @@ public class BedrockPositionTrackingDBClientRequestTranslator extends PacketTran // Build the NBT data for the update NbtMapBuilder builder = NbtMap.builder(); - builder.putInt("dim", DimensionUtils.javaToBedrock(pos.getDimension())); + builder.putInt("dim", DimensionUtils.javaToBedrock(pos.dimension())); builder.putString("id", "0x" + String.format("%08X", packet.getTrackingId())); builder.putByte("version", (byte) 1); // Not sure what this is for builder.putByte("status", (byte) 0); // Not sure what this is for // Build the position for the update - builder.putList("pos", NbtType.INT, pos.getX(), pos.getY(), pos.getZ()); + builder.putList("pos", NbtType.INT, pos.x(), pos.y(), pos.z()); broadcastPacket.setTag(builder.build()); session.sendUpstreamPacket(broadcastPacket); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestChunkRadiusTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestChunkRadiusTranslator.java new file mode 100644 index 000000000..0a27f7b64 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestChunkRadiusTranslator.java @@ -0,0 +1,47 @@ +/* + * 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.bedrock; + +import com.nukkitx.protocol.bedrock.packet.RequestChunkRadiusPacket; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.translator.protocol.Translator; + +/** + * Sent when the client updates its desired render distance. + */ +@Translator(packet = RequestChunkRadiusPacket.class) +public class BedrockRequestChunkRadiusTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, RequestChunkRadiusPacket packet) { + session.setClientRenderDistance(packet.getRadius()); + + if (session.isLoggedIn()) { + session.sendJavaClientSettings(); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRespawnTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRespawnTranslator.java index 77b7143b2..1631ea4c7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRespawnTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRespawnTranslator.java @@ -27,10 +27,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; import com.github.steveice10.mc.protocol.data.game.ClientCommand; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; -import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket; import com.nukkitx.protocol.bedrock.packet.RespawnPacket; -import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -41,28 +38,6 @@ public class BedrockRespawnTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, RespawnPacket packet) { if (packet.getState() == RespawnPacket.State.CLIENT_READY) { - // Previously we only sent the respawn packet before the server finished loading - // The message included was 'Otherwise when immediate respawn is on the client never loads' - // But I assume the new if statement below fixes that problem - RespawnPacket respawnPacket = new RespawnPacket(); - respawnPacket.setRuntimeEntityId(0); - respawnPacket.setPosition(Vector3f.ZERO); - respawnPacket.setState(RespawnPacket.State.SERVER_READY); - session.sendUpstreamPacket(respawnPacket); - - if (session.isSpawned()) { - // Client might be stuck; resend spawn information - PlayerEntity entity = session.getPlayerEntity(); - entity.updateBedrockMetadata(); // TODO test? - - MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); - movePlayerPacket.setRuntimeEntityId(entity.getGeyserId()); - movePlayerPacket.setPosition(entity.getPosition()); - movePlayerPacket.setRotation(entity.getBedrockRotation()); - movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN); - session.sendUpstreamPacket(movePlayerPacket); - } - ServerboundClientCommandPacket javaRespawnPacket = new ServerboundClientCommandPacket(ClientCommand.RESPAWN); session.sendDownstreamPacket(javaRespawnPacket); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockTextTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockTextTranslator.java index 035a2afe2..1a6771cc5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockTextTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockTextTranslator.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket; import com.nukkitx.protocol.bedrock.packet.TextPacket; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -44,6 +45,18 @@ public class BedrockTextTranslator extends PacketTranslator { return; } + if (message.indexOf(ChatColor.ESCAPE) != -1) { + // Filter out all escape characters - Java doesn't let you type these + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < message.length(); i++) { + char c = message.charAt(i); + if (c != ChatColor.ESCAPE) { + builder.append(c); + } + } + message = builder.toString(); + } + if (MessageTranslator.isTooLong(message, session)) { return; } 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 08a913b77..14dc37e5d 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,31 +25,25 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.protocol.data.game.entity.player.HandPreference; -import com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility; -import com.github.steveice10.mc.protocol.data.game.setting.SkinPart; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLoginPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientInformationPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket; import com.nukkitx.protocol.bedrock.data.GameRuleData; import com.nukkitx.protocol.bedrock.data.PlayerPermission; -import com.nukkitx.protocol.bedrock.packet.*; -import org.geysermc.geyser.session.auth.AuthType; +import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket; +import com.nukkitx.protocol.bedrock.packet.GameRulesChangedPacket; +import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.auth.AuthType; +import org.geysermc.geyser.translator.level.BiomeTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; -import org.geysermc.geyser.translator.level.BiomeTranslator; import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.PluginMessageUtils; -import java.util.Arrays; -import java.util.List; - @Translator(packet = ClientboundLoginPacket.class) public class JavaLoginTranslator extends PacketTranslator { - private static final List SKIN_PART_VALUES = Arrays.asList(SkinPart.values()); @Override public void translate(GeyserSession session, ClientboundLoginPacket packet) { @@ -99,13 +93,10 @@ public class JavaLoginTranslator extends PacketTranslator= Bedrock_v486.V486_CODEC.getProtocolVersion(); + Int2ObjectMap recipeMap = new Int2ObjectOpenHashMap<>(Registries.RECIPES.forVersion(session.getUpstream().getProtocolVersion())); Int2ObjectMap> unsortedStonecutterData = new Int2ObjectOpenHashMap<>(); CraftingDataPacket craftingDataPacket = new CraftingDataPacket(); @@ -128,6 +132,27 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator { + // Required to translate these as of 1.18.10, or else they cannot be crafted + if (!applySmithingRecipes) { + continue; + } + + SmithingRecipeData recipeData = (SmithingRecipeData) recipe.getData(); + ItemData output = ItemTranslator.translateToBedrock(session, recipeData.getResult()); + for (ItemStack base : recipeData.getBase().getOptions()) { + ItemData bedrockBase = ItemTranslator.translateToBedrock(session, base); + + for (ItemStack addition : recipeData.getAddition().getOptions()) { + ItemData bedrockAddition = ItemTranslator.translateToBedrock(session, addition); + + UUID uuid = UUID.randomUUID(); + craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(), + Arrays.asList(bedrockBase, bedrockAddition), + Collections.singletonList(output), uuid, "smithing_table", 2, netId++)); + } + } + } default -> { List craftingData = recipeTypes.get(recipe.getType()); if (craftingData != null) { 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 f34f7bd17..de4a2c22b 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 @@ -245,8 +245,8 @@ public class JavaEntityEventTranslator extends PacketTranslator { 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 e2fe1103f..97487ea6a 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 @@ -86,13 +86,14 @@ public class JavaPlayerPositionTranslator extends PacketTranslator inventorySize) { + GeyserImpl geyser = session.getGeyser(); + geyser.getLogger().warning("ClientboundContainerSetContentPacket sent to " + session.name() + + " that exceeds inventory size!"); + if (geyser.getConfig().isDebugMode()) { + geyser.getLogger().debug(packet); + geyser.getLogger().debug(inventory); + } + InventoryTranslator translator = session.getInventoryTranslator(); + if (translator != null) { + translator.updateInventory(session, inventory); + } + // 1.18.1 behavior: the previous items will be correctly set, but the state ID and carried item will not + // as this produces a stack trace on the client. + // If Java processes this correctly in the future, we can revert this behavior + return; + } + GeyserItemStack newItem = GeyserItemStack.from(packet.getItems()[i]); inventory.setItem(i, newItem, session); } @@ -55,6 +73,10 @@ public class JavaContainerSetContentTranslator extends PacketTranslator 0 || stateId != inventory.getStateId()); + inventory.setStateId(stateId); + session.getPlayerInventory().setCursor(GeyserItemStack.from(packet.getCarriedItem()), session); InventoryUtils.updateCursor(session); } 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 283d95fc4..4bb2a8e60 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 @@ -30,7 +30,6 @@ import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData; -import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket; import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; import com.nukkitx.protocol.bedrock.data.inventory.CraftingData; @@ -40,17 +39,15 @@ import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.translator.protocol.PacketTranslator; -import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.inventory.InventoryTranslator; -import org.geysermc.geyser.translator.inventory.CraftingInventoryTranslator; import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator; 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.InventoryUtils; import java.util.Arrays; import java.util.Collections; -import java.util.Objects; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -72,14 +69,16 @@ 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); } - session.setCraftingGridFuture(session.scheduleInEventLoop(() -> updateCraftingGrid(session, packet, inventory, translator), 150, TimeUnit.MILLISECONDS)); + updateCraftingGrid(session, packet.getSlot(), packet.getItem(), inventory, translator); GeyserItemStack newItem = GeyserItemStack.from(packet.getItem()); if (packet.getContainerId() == 0 && !(translator instanceof PlayerInventoryTranslator)) { @@ -93,21 +92,23 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator { int offset = gridSize == 4 ? 28 : 32; int gridDimensions = gridSize == 4 ? 2 : 3; int firstRow = -1, height = -1; @@ -135,62 +136,10 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator 0 ? packet.getVillagerLevel() - 1 : 0); // -1 crashes client - recipe.put("buyA", getItemTag(session, trade.getFirstInput(), trade.getSpecialPrice())); - if (trade.getSecondInput() != null) { - recipe.put("buyB", getItemTag(session, trade.getSecondInput(), 0)); - } + recipe.put("buyA", getItemTag(session, trade.getFirstInput(), trade.getSpecialPrice(), trade.getDemand(), trade.getPriceMultiplier())); + recipe.put("buyB", getItemTag(session, trade.getSecondInput())); recipe.putInt("uses", trade.getNumUses()); recipe.putByte("rewardExp", (byte) 1); tags.add(recipe.build()); @@ -144,12 +146,31 @@ public class JavaMerchantOffersTranslator extends PacketTranslator effectPacket.setType(LevelEventType.PARTICLE_EYE_OF_ENDER_DEATH); case MOB_SPAWN -> effectPacket.setType(LevelEventType.PARTICLE_MOB_BLOCK_SPAWN); // TODO: Check, but I don't think I really verified this ever went into effect on Java case BONEMEAL_GROW_WITH_SOUND, BONEMEAL_GROW -> { - effectPacket.setType((particleEvent == ParticleEvent.BONEMEAL_GROW - && session.getUpstream().getProtocolVersion() >= Bedrock_v465.V465_CODEC.getProtocolVersion()) ? LevelEventType.PARTICLE_TURTLE_EGG : LevelEventType.PARTICLE_CROP_GROWTH); + effectPacket.setType(particleEvent == ParticleEvent.BONEMEAL_GROW ? LevelEventType.PARTICLE_TURTLE_EGG : LevelEventType.PARTICLE_CROP_GROWTH); BonemealGrowEventData growEventData = (BonemealGrowEventData) packet.getData(); effectPacket.setData(growEventData.getParticleCount()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheRadiusTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheRadiusTranslator.java index 8fee27250..3a0a77cc0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheRadiusTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetChunkCacheRadiusTranslator.java @@ -35,6 +35,6 @@ public class JavaSetChunkCacheRadiusTranslator extends PacketTranslator Click.SWAP_TO_HOTBAR_1; + case 1 -> Click.SWAP_TO_HOTBAR_2; + case 2 -> Click.SWAP_TO_HOTBAR_3; + case 3 -> Click.SWAP_TO_HOTBAR_4; + case 4 -> Click.SWAP_TO_HOTBAR_5; + case 5 -> Click.SWAP_TO_HOTBAR_6; + case 6 -> Click.SWAP_TO_HOTBAR_7; + case 7 -> Click.SWAP_TO_HOTBAR_8; + case 8 -> Click.SWAP_TO_HOTBAR_9; + default -> null; + }; + } + + /** + * Test all known recipes to find a valid match + * + * @param output if not null, the recipe has to output this item + */ + @Nullable + public static Recipe getValidRecipe(final GeyserSession session, final @Nullable ItemStack output, final IntFunction inventoryGetter, + final int gridDimensions, final int firstRow, final int height, final int firstCol, final int width) { + int nonAirCount = 0; // Used for shapeless recipes for amount of items needed in recipe + for (int row = firstRow; row < height + firstRow; row++) { + for (int col = firstCol; col < width + firstCol; col++) { + if (!inventoryGetter.apply(col + (row * gridDimensions) + 1).isEmpty()) { + nonAirCount++; + } + } + } + + recipes: + for (Recipe recipe : session.getCraftingRecipes().values()) { + if (recipe.getType() == RecipeType.CRAFTING_SHAPED) { + ShapedRecipeData data = (ShapedRecipeData) recipe.getData(); + if (output != null && !data.getResult().equals(output)) { + continue; + } + Ingredient[] ingredients = data.getIngredients(); + if (data.getWidth() != width || data.getHeight() != height || width * height != ingredients.length) { + continue; + } + + if (!testShapedRecipe(ingredients, inventoryGetter, gridDimensions, firstRow, height, firstCol, width)) { + Ingredient[] mirroredIngredients = new Ingredient[ingredients.length]; + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + mirroredIngredients[col + (row * width)] = ingredients[(width - 1 - col) + (row * width)]; + } + } + + if (Arrays.equals(ingredients, mirroredIngredients) || + !testShapedRecipe(mirroredIngredients, inventoryGetter, gridDimensions, firstRow, height, firstCol, width)) { + continue; + } + } + return recipe; + } else if (recipe.getType() == RecipeType.CRAFTING_SHAPELESS) { + ShapelessRecipeData data = (ShapelessRecipeData) recipe.getData(); + if (output != null && !data.getResult().equals(output)) { + continue; + } + if (nonAirCount != data.getIngredients().length) { + // There is an amount of items on the crafting table that is not the same as the ingredient count so this is invalid + continue; + } + for (int i = 0; i < data.getIngredients().length; i++) { + Ingredient ingredient = data.getIngredients()[i]; + for (ItemStack itemStack : ingredient.getOptions()) { + boolean inventoryHasItem = false; + // Iterate only over the crafting table to find this item + crafting: + for (int row = firstRow; row < height + firstRow; row++) { + for (int col = firstCol; col < width + firstCol; col++) { + GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1); + if (geyserItemStack.isEmpty()) { + inventoryHasItem = itemStack == null || itemStack.getId() == 0; + if (inventoryHasItem) { + break crafting; + } + } else if (itemStack.equals(geyserItemStack.getItemStack(1))) { + inventoryHasItem = true; + break crafting; + } + } + } + if (!inventoryHasItem) { + continue recipes; + } + } + } + return recipe; + } + } + return null; + } + + private static boolean testShapedRecipe(final Ingredient[] ingredients, final IntFunction inventoryGetter, + final int gridDimensions, final int firstRow, final int height, final int firstCol, final int width) { + int ingredientIndex = 0; + for (int row = firstRow; row < height + firstRow; row++) { + for (int col = firstCol; col < width + firstCol; col++) { + GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1); + Ingredient ingredient = ingredients[ingredientIndex++]; + if (ingredient.getOptions().length == 0) { + if (!geyserItemStack.isEmpty()) { + return false; + } + } else { + boolean inventoryHasItem = false; + for (ItemStack item : ingredient.getOptions()) { + if (Objects.equals(geyserItemStack.getItemStack(1), item)) { + inventoryHasItem = true; + break; + } + } + if (!inventoryHasItem) { + return false; + } + } + } + } + return true; + } } diff --git a/core/src/main/resources/bedrock/block_palette.1_17_30.nbt b/core/src/main/resources/bedrock/block_palette.1_17_30.nbt deleted file mode 100644 index fde145ca5..000000000 Binary files a/core/src/main/resources/bedrock/block_palette.1_17_30.nbt and /dev/null differ diff --git a/core/src/main/resources/bedrock/block_palette.1_18_10.nbt b/core/src/main/resources/bedrock/block_palette.1_18_10.nbt new file mode 100644 index 000000000..637bfc952 Binary files /dev/null and b/core/src/main/resources/bedrock/block_palette.1_18_10.nbt differ diff --git a/core/src/main/resources/bedrock/creative_items.1_17_30.json b/core/src/main/resources/bedrock/creative_items.1_18_10.json similarity index 91% rename from core/src/main/resources/bedrock/creative_items.1_17_30.json rename to core/src/main/resources/bedrock/creative_items.1_18_10.json index bb73854dc..dadabf91f 100644 --- a/core/src/main/resources/bedrock/creative_items.1_17_30.json +++ b/core/src/main/resources/bedrock/creative_items.1_18_10.json @@ -2,39 +2,35 @@ "items" : [ { "id" : "minecraft:planks", - "blockRuntimeId" : 5794 + "blockRuntimeId" : 5800 }, { "id" : "minecraft:planks", - "blockRuntimeId" : 5795 + "blockRuntimeId" : 5801 }, { "id" : "minecraft:planks", - "blockRuntimeId" : 5796 + "blockRuntimeId" : 5802 }, { "id" : "minecraft:planks", - "blockRuntimeId" : 5797 + "blockRuntimeId" : 5803 }, { "id" : "minecraft:planks", - "blockRuntimeId" : 5798 + "blockRuntimeId" : 5804 }, { "id" : "minecraft:planks", - "blockRuntimeId" : 5799 + "blockRuntimeId" : 5805 }, { "id" : "minecraft:crimson_planks", - "blockRuntimeId" : 3839 + "blockRuntimeId" : 3840 }, { "id" : "minecraft:warped_planks", - "blockRuntimeId" : 7594 - }, - { - "id" : "minecraft:cobblestone_wall", - "blockRuntimeId" : 1318 + "blockRuntimeId" : 7596 }, { "id" : "minecraft:cobblestone_wall", @@ -56,69 +52,69 @@ "id" : "minecraft:cobblestone_wall", "blockRuntimeId" : 1323 }, - { - "id" : "minecraft:cobblestone_wall", - "blockRuntimeId" : 1330 - }, - { - "id" : "minecraft:cobblestone_wall", - "blockRuntimeId" : 1325 - }, - { - "id" : "minecraft:cobblestone_wall", - "blockRuntimeId" : 1326 - }, { "id" : "minecraft:cobblestone_wall", "blockRuntimeId" : 1324 }, - { - "id" : "minecraft:cobblestone_wall", - "blockRuntimeId" : 1327 - }, { "id" : "minecraft:cobblestone_wall", "blockRuntimeId" : 1331 }, + { + "id" : "minecraft:cobblestone_wall", + "blockRuntimeId" : 1326 + }, + { + "id" : "minecraft:cobblestone_wall", + "blockRuntimeId" : 1327 + }, + { + "id" : "minecraft:cobblestone_wall", + "blockRuntimeId" : 1325 + }, { "id" : "minecraft:cobblestone_wall", "blockRuntimeId" : 1328 }, + { + "id" : "minecraft:cobblestone_wall", + "blockRuntimeId" : 1332 + }, { "id" : "minecraft:cobblestone_wall", "blockRuntimeId" : 1329 }, + { + "id" : "minecraft:cobblestone_wall", + "blockRuntimeId" : 1330 + }, { "id" : "minecraft:blackstone_wall", "blockRuntimeId" : 507 }, { "id" : "minecraft:polished_blackstone_wall", - "blockRuntimeId" : 6038 + "blockRuntimeId" : 6044 }, { "id" : "minecraft:polished_blackstone_brick_wall", - "blockRuntimeId" : 5835 + "blockRuntimeId" : 5841 }, { "id" : "minecraft:cobbled_deepslate_wall", - "blockRuntimeId" : 1155 + "blockRuntimeId" : 1156 }, { "id" : "minecraft:deepslate_tile_wall", - "blockRuntimeId" : 4297 + "blockRuntimeId" : 4298 }, { "id" : "minecraft:polished_deepslate_wall", - "blockRuntimeId" : 6213 + "blockRuntimeId" : 6219 }, { "id" : "minecraft:deepslate_brick_wall", - "blockRuntimeId" : 4114 - }, - { - "id" : "minecraft:fence", - "blockRuntimeId" : 4773 + "blockRuntimeId" : 4115 }, { "id" : "minecraft:fence", @@ -141,24 +137,28 @@ "blockRuntimeId" : 4778 }, { - "id" : "minecraft:nether_brick_fence", - "blockRuntimeId" : 5686 - }, - { - "id" : "minecraft:crimson_fence", - "blockRuntimeId" : 3817 - }, - { - "id" : "minecraft:warped_fence", - "blockRuntimeId" : 7572 - }, - { - "id" : "minecraft:fence_gate", + "id" : "minecraft:fence", "blockRuntimeId" : 4779 }, + { + "id" : "minecraft:nether_brick_fence", + "blockRuntimeId" : 5690 + }, + { + "id" : "minecraft:crimson_fence", + "blockRuntimeId" : 3818 + }, + { + "id" : "minecraft:warped_fence", + "blockRuntimeId" : 7574 + }, + { + "id" : "minecraft:fence_gate", + "blockRuntimeId" : 4780 + }, { "id" : "minecraft:spruce_fence_gate", - "blockRuntimeId" : 7006 + "blockRuntimeId" : 7007 }, { "id" : "minecraft:birch_fence_gate", @@ -166,7 +166,7 @@ }, { "id" : "minecraft:jungle_fence_gate", - "blockRuntimeId" : 5252 + "blockRuntimeId" : 5254 }, { "id" : "minecraft:acacia_fence_gate", @@ -174,35 +174,35 @@ }, { "id" : "minecraft:dark_oak_fence_gate", - "blockRuntimeId" : 3980 + "blockRuntimeId" : 3981 }, { "id" : "minecraft:crimson_fence_gate", - "blockRuntimeId" : 3818 + "blockRuntimeId" : 3819 }, { "id" : "minecraft:warped_fence_gate", - "blockRuntimeId" : 7573 + "blockRuntimeId" : 7575 }, { "id" : "minecraft:normal_stone_stairs", - "blockRuntimeId" : 5705 + "blockRuntimeId" : 5709 }, { "id" : "minecraft:stone_stairs", - "blockRuntimeId" : 7277 + "blockRuntimeId" : 7278 }, { "id" : "minecraft:mossy_cobblestone_stairs", - "blockRuntimeId" : 5667 + "blockRuntimeId" : 5669 }, { "id" : "minecraft:oak_stairs", - "blockRuntimeId" : 5714 + "blockRuntimeId" : 5718 }, { "id" : "minecraft:spruce_stairs", - "blockRuntimeId" : 7038 + "blockRuntimeId" : 7039 }, { "id" : "minecraft:birch_stairs", @@ -210,7 +210,7 @@ }, { "id" : "minecraft:jungle_stairs", - "blockRuntimeId" : 5284 + "blockRuntimeId" : 5286 }, { "id" : "minecraft:acacia_stairs", @@ -218,47 +218,47 @@ }, { "id" : "minecraft:dark_oak_stairs", - "blockRuntimeId" : 4012 + "blockRuntimeId" : 4013 }, { "id" : "minecraft:stone_brick_stairs", - "blockRuntimeId" : 7183 + "blockRuntimeId" : 7184 }, { "id" : "minecraft:mossy_stone_brick_stairs", - "blockRuntimeId" : 5675 + "blockRuntimeId" : 5677 }, { "id" : "minecraft:sandstone_stairs", - "blockRuntimeId" : 6707 + "blockRuntimeId" : 6713 }, { "id" : "minecraft:smooth_sandstone_stairs", - "blockRuntimeId" : 6899 + "blockRuntimeId" : 6900 }, { "id" : "minecraft:red_sandstone_stairs", - "blockRuntimeId" : 6634 + "blockRuntimeId" : 6640 }, { "id" : "minecraft:smooth_red_sandstone_stairs", - "blockRuntimeId" : 6891 + "blockRuntimeId" : 6892 }, { "id" : "minecraft:granite_stairs", - "blockRuntimeId" : 4988 + "blockRuntimeId" : 4990 }, { "id" : "minecraft:polished_granite_stairs", - "blockRuntimeId" : 6383 + "blockRuntimeId" : 6389 }, { "id" : "minecraft:diorite_stairs", - "blockRuntimeId" : 4475 + "blockRuntimeId" : 4476 }, { "id" : "minecraft:polished_diorite_stairs", - "blockRuntimeId" : 6375 + "blockRuntimeId" : 6381 }, { "id" : "minecraft:andesite_stairs", @@ -266,7 +266,7 @@ }, { "id" : "minecraft:polished_andesite_stairs", - "blockRuntimeId" : 5811 + "blockRuntimeId" : 5817 }, { "id" : "minecraft:brick_stairs", @@ -274,47 +274,47 @@ }, { "id" : "minecraft:nether_brick_stairs", - "blockRuntimeId" : 5687 + "blockRuntimeId" : 5691 }, { "id" : "minecraft:red_nether_brick_stairs", - "blockRuntimeId" : 6622 + "blockRuntimeId" : 6628 }, { "id" : "minecraft:end_brick_stairs", - "blockRuntimeId" : 4719 + "blockRuntimeId" : 4720 }, { "id" : "minecraft:quartz_stairs", - "blockRuntimeId" : 6556 + "blockRuntimeId" : 6562 }, { "id" : "minecraft:smooth_quartz_stairs", - "blockRuntimeId" : 6883 + "blockRuntimeId" : 6884 }, { "id" : "minecraft:purpur_stairs", - "blockRuntimeId" : 6534 + "blockRuntimeId" : 6540 }, { "id" : "minecraft:prismarine_stairs", - "blockRuntimeId" : 6446 + "blockRuntimeId" : 6452 }, { "id" : "minecraft:dark_prismarine_stairs", - "blockRuntimeId" : 4036 + "blockRuntimeId" : 4037 }, { "id" : "minecraft:prismarine_bricks_stairs", - "blockRuntimeId" : 6438 + "blockRuntimeId" : 6444 }, { "id" : "minecraft:crimson_stairs", - "blockRuntimeId" : 3859 + "blockRuntimeId" : 3860 }, { "id" : "minecraft:warped_stairs", - "blockRuntimeId" : 7614 + "blockRuntimeId" : 7616 }, { "id" : "minecraft:blackstone_stairs", @@ -322,59 +322,59 @@ }, { "id" : "minecraft:polished_blackstone_stairs", - "blockRuntimeId" : 6030 + "blockRuntimeId" : 6036 }, { "id" : "minecraft:polished_blackstone_brick_stairs", - "blockRuntimeId" : 5827 + "blockRuntimeId" : 5833 }, { "id" : "minecraft:cut_copper_stairs", - "blockRuntimeId" : 3912 + "blockRuntimeId" : 3913 }, { "id" : "minecraft:exposed_cut_copper_stairs", - "blockRuntimeId" : 4755 + "blockRuntimeId" : 4756 }, { "id" : "minecraft:weathered_cut_copper_stairs", - "blockRuntimeId" : 7741 + "blockRuntimeId" : 7743 }, { "id" : "minecraft:oxidized_cut_copper_stairs", - "blockRuntimeId" : 5755 + "blockRuntimeId" : 5760 }, { "id" : "minecraft:waxed_cut_copper_stairs", - "blockRuntimeId" : 7685 + "blockRuntimeId" : 7687 }, { "id" : "minecraft:waxed_exposed_cut_copper_stairs", - "blockRuntimeId" : 7699 + "blockRuntimeId" : 7701 }, { "id" : "minecraft:waxed_weathered_cut_copper_stairs", - "blockRuntimeId" : 7727 + "blockRuntimeId" : 7729 }, { "id" : "minecraft:waxed_oxidized_cut_copper_stairs", - "blockRuntimeId" : 7713 + "blockRuntimeId" : 7715 }, { "id" : "minecraft:cobbled_deepslate_stairs", - "blockRuntimeId" : 1147 + "blockRuntimeId" : 1148 }, { "id" : "minecraft:deepslate_tile_stairs", - "blockRuntimeId" : 4289 + "blockRuntimeId" : 4290 }, { "id" : "minecraft:polished_deepslate_stairs", - "blockRuntimeId" : 6205 + "blockRuntimeId" : 6211 }, { "id" : "minecraft:deepslate_brick_stairs", - "blockRuntimeId" : 4106 + "blockRuntimeId" : 4107 }, { "id" : "minecraft:wooden_door" @@ -405,11 +405,11 @@ }, { "id" : "minecraft:trapdoor", - "blockRuntimeId" : 7359 + "blockRuntimeId" : 7360 }, { "id" : "minecraft:spruce_trapdoor", - "blockRuntimeId" : 7062 + "blockRuntimeId" : 7063 }, { "id" : "minecraft:birch_trapdoor", @@ -417,7 +417,7 @@ }, { "id" : "minecraft:jungle_trapdoor", - "blockRuntimeId" : 5308 + "blockRuntimeId" : 5310 }, { "id" : "minecraft:acacia_trapdoor", @@ -425,51 +425,27 @@ }, { "id" : "minecraft:dark_oak_trapdoor", - "blockRuntimeId" : 4020 + "blockRuntimeId" : 4021 }, { "id" : "minecraft:iron_trapdoor", - "blockRuntimeId" : 5167 + "blockRuntimeId" : 5169 }, { "id" : "minecraft:crimson_trapdoor", - "blockRuntimeId" : 3886 + "blockRuntimeId" : 3887 }, { "id" : "minecraft:warped_trapdoor", - "blockRuntimeId" : 7641 + "blockRuntimeId" : 7643 }, { "id" : "minecraft:iron_bars", - "blockRuntimeId" : 5132 + "blockRuntimeId" : 5134 }, { "id" : "minecraft:glass", - "blockRuntimeId" : 4882 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7084 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7092 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7091 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7099 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7096 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7098 + "blockRuntimeId" : 4884 }, { "id" : "minecraft:stained_glass", @@ -477,11 +453,15 @@ }, { "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7088 + "blockRuntimeId" : 7093 }, { "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7089 + "blockRuntimeId" : 7092 + }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7100 }, { "id" : "minecraft:stained_glass", @@ -489,59 +469,55 @@ }, { "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7093 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7087 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7095 - }, - { - "id" : "minecraft:stained_glass", - "blockRuntimeId" : 7094 + "blockRuntimeId" : 7099 }, { "id" : "minecraft:stained_glass", "blockRuntimeId" : 7086 }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7089 + }, { "id" : "minecraft:stained_glass", "blockRuntimeId" : 7090 }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7098 + }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7094 + }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7088 + }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7096 + }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7095 + }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7087 + }, + { + "id" : "minecraft:stained_glass", + "blockRuntimeId" : 7091 + }, { "id" : "minecraft:tinted_glass", - "blockRuntimeId" : 7348 + "blockRuntimeId" : 7349 }, { "id" : "minecraft:glass_pane", - "blockRuntimeId" : 4883 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7100 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7108 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7107 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7115 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7112 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7114 + "blockRuntimeId" : 4885 }, { "id" : "minecraft:stained_glass_pane", @@ -549,11 +525,15 @@ }, { "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7104 + "blockRuntimeId" : 7109 }, { "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7105 + "blockRuntimeId" : 7108 + }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7116 }, { "id" : "minecraft:stained_glass_pane", @@ -561,59 +541,71 @@ }, { "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7109 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7103 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7111 - }, - { - "id" : "minecraft:stained_glass_pane", - "blockRuntimeId" : 7110 + "blockRuntimeId" : 7115 }, { "id" : "minecraft:stained_glass_pane", "blockRuntimeId" : 7102 }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7105 + }, { "id" : "minecraft:stained_glass_pane", "blockRuntimeId" : 7106 }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7114 + }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7110 + }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7104 + }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7112 + }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7111 + }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7103 + }, + { + "id" : "minecraft:stained_glass_pane", + "blockRuntimeId" : 7107 + }, { "id" : "minecraft:ladder", - "blockRuntimeId" : 5356 + "blockRuntimeId" : 5358 }, { "id" : "minecraft:scaffolding", - "blockRuntimeId" : 6727 + "blockRuntimeId" : 6733 }, { "id" : "minecraft:double_stone_slab", - "blockRuntimeId" : 7219 + "blockRuntimeId" : 7220 }, { "id" : "minecraft:double_stone_slab4", - "blockRuntimeId" : 7269 + "blockRuntimeId" : 7270 }, { "id" : "minecraft:double_stone_slab", - "blockRuntimeId" : 7222 + "blockRuntimeId" : 7223 }, { "id" : "minecraft:double_stone_slab2", - "blockRuntimeId" : 7240 - }, - { - "id" : "minecraft:wooden_slab", - "blockRuntimeId" : 7899 - }, - { - "id" : "minecraft:wooden_slab", - "blockRuntimeId" : 7900 + "blockRuntimeId" : 7241 }, { "id" : "minecraft:wooden_slab", @@ -632,76 +624,12 @@ "blockRuntimeId" : 7904 }, { - "id" : "minecraft:double_stone_slab", - "blockRuntimeId" : 7224 + "id" : "minecraft:wooden_slab", + "blockRuntimeId" : 7905 }, { - "id" : "minecraft:double_stone_slab4", - "blockRuntimeId" : 7267 - }, - { - "id" : "minecraft:double_stone_slab", - "blockRuntimeId" : 7220 - }, - { - "id" : "minecraft:double_stone_slab4", - "blockRuntimeId" : 7270 - }, - { - "id" : "minecraft:double_stone_slab2", - "blockRuntimeId" : 7241 - }, - { - "id" : "minecraft:double_stone_slab2", - "blockRuntimeId" : 7235 - }, - { - "id" : "minecraft:double_stone_slab4", - "blockRuntimeId" : 7271 - }, - { - "id" : "minecraft:double_stone_slab3", - "blockRuntimeId" : 7252 - }, - { - "id" : "minecraft:double_stone_slab3", - "blockRuntimeId" : 7257 - }, - { - "id" : "minecraft:double_stone_slab3", - "blockRuntimeId" : 7258 - }, - { - "id" : "minecraft:double_stone_slab3", - "blockRuntimeId" : 7255 - }, - { - "id" : "minecraft:double_stone_slab3", - "blockRuntimeId" : 7256 - }, - { - "id" : "minecraft:double_stone_slab3", - "blockRuntimeId" : 7254 - }, - { - "id" : "minecraft:double_stone_slab3", - "blockRuntimeId" : 7253 - }, - { - "id" : "minecraft:double_stone_slab", - "blockRuntimeId" : 7223 - }, - { - "id" : "minecraft:double_stone_slab", - "blockRuntimeId" : 7226 - }, - { - "id" : "minecraft:double_stone_slab2", - "blockRuntimeId" : 7242 - }, - { - "id" : "minecraft:double_stone_slab3", - "blockRuntimeId" : 7251 + "id" : "minecraft:wooden_slab", + "blockRuntimeId" : 7906 }, { "id" : "minecraft:double_stone_slab", @@ -711,10 +639,78 @@ "id" : "minecraft:double_stone_slab4", "blockRuntimeId" : 7268 }, + { + "id" : "minecraft:double_stone_slab", + "blockRuntimeId" : 7221 + }, + { + "id" : "minecraft:double_stone_slab4", + "blockRuntimeId" : 7271 + }, + { + "id" : "minecraft:double_stone_slab2", + "blockRuntimeId" : 7242 + }, { "id" : "minecraft:double_stone_slab2", "blockRuntimeId" : 7236 }, + { + "id" : "minecraft:double_stone_slab4", + "blockRuntimeId" : 7272 + }, + { + "id" : "minecraft:double_stone_slab3", + "blockRuntimeId" : 7253 + }, + { + "id" : "minecraft:double_stone_slab3", + "blockRuntimeId" : 7258 + }, + { + "id" : "minecraft:double_stone_slab3", + "blockRuntimeId" : 7259 + }, + { + "id" : "minecraft:double_stone_slab3", + "blockRuntimeId" : 7256 + }, + { + "id" : "minecraft:double_stone_slab3", + "blockRuntimeId" : 7257 + }, + { + "id" : "minecraft:double_stone_slab3", + "blockRuntimeId" : 7255 + }, + { + "id" : "minecraft:double_stone_slab3", + "blockRuntimeId" : 7254 + }, + { + "id" : "minecraft:double_stone_slab", + "blockRuntimeId" : 7224 + }, + { + "id" : "minecraft:double_stone_slab", + "blockRuntimeId" : 7227 + }, + { + "id" : "minecraft:double_stone_slab2", + "blockRuntimeId" : 7243 + }, + { + "id" : "minecraft:double_stone_slab3", + "blockRuntimeId" : 7252 + }, + { + "id" : "minecraft:double_stone_slab", + "blockRuntimeId" : 7226 + }, + { + "id" : "minecraft:double_stone_slab4", + "blockRuntimeId" : 7269 + }, { "id" : "minecraft:double_stone_slab2", "blockRuntimeId" : 7237 @@ -727,13 +723,17 @@ "id" : "minecraft:double_stone_slab2", "blockRuntimeId" : 7239 }, + { + "id" : "minecraft:double_stone_slab2", + "blockRuntimeId" : 7240 + }, { "id" : "minecraft:crimson_slab", - "blockRuntimeId" : 3857 + "blockRuntimeId" : 3858 }, { "id" : "minecraft:warped_slab", - "blockRuntimeId" : 7612 + "blockRuntimeId" : 7614 }, { "id" : "minecraft:blackstone_slab", @@ -741,59 +741,59 @@ }, { "id" : "minecraft:polished_blackstone_slab", - "blockRuntimeId" : 6028 + "blockRuntimeId" : 6034 }, { "id" : "minecraft:polished_blackstone_brick_slab", - "blockRuntimeId" : 5825 + "blockRuntimeId" : 5831 }, { "id" : "minecraft:cut_copper_slab", - "blockRuntimeId" : 3910 + "blockRuntimeId" : 3911 }, { "id" : "minecraft:exposed_cut_copper_slab", - "blockRuntimeId" : 4753 + "blockRuntimeId" : 4754 }, { "id" : "minecraft:weathered_cut_copper_slab", - "blockRuntimeId" : 7739 + "blockRuntimeId" : 7741 }, { "id" : "minecraft:oxidized_cut_copper_slab", - "blockRuntimeId" : 5753 + "blockRuntimeId" : 5758 }, { "id" : "minecraft:waxed_cut_copper_slab", - "blockRuntimeId" : 7683 + "blockRuntimeId" : 7685 }, { "id" : "minecraft:waxed_exposed_cut_copper_slab", - "blockRuntimeId" : 7697 + "blockRuntimeId" : 7699 }, { "id" : "minecraft:waxed_weathered_cut_copper_slab", - "blockRuntimeId" : 7725 + "blockRuntimeId" : 7727 }, { "id" : "minecraft:waxed_oxidized_cut_copper_slab", - "blockRuntimeId" : 7711 + "blockRuntimeId" : 7713 }, { "id" : "minecraft:cobbled_deepslate_slab", - "blockRuntimeId" : 1145 + "blockRuntimeId" : 1146 }, { "id" : "minecraft:polished_deepslate_slab", - "blockRuntimeId" : 6203 + "blockRuntimeId" : 6209 }, { "id" : "minecraft:deepslate_tile_slab", - "blockRuntimeId" : 4287 + "blockRuntimeId" : 4288 }, { "id" : "minecraft:deepslate_brick_slab", - "blockRuntimeId" : 4104 + "blockRuntimeId" : 4105 }, { "id" : "minecraft:brick_block", @@ -805,15 +805,11 @@ }, { "id" : "minecraft:cracked_nether_bricks", - "blockRuntimeId" : 3768 + "blockRuntimeId" : 3769 }, { "id" : "minecraft:quartz_bricks", - "blockRuntimeId" : 6554 - }, - { - "id" : "minecraft:stonebrick", - "blockRuntimeId" : 7285 + "blockRuntimeId" : 6560 }, { "id" : "minecraft:stonebrick", @@ -827,25 +823,29 @@ "id" : "minecraft:stonebrick", "blockRuntimeId" : 7288 }, + { + "id" : "minecraft:stonebrick", + "blockRuntimeId" : 7289 + }, { "id" : "minecraft:end_bricks", - "blockRuntimeId" : 4727 + "blockRuntimeId" : 4728 }, { "id" : "minecraft:prismarine", - "blockRuntimeId" : 6437 + "blockRuntimeId" : 6443 }, { "id" : "minecraft:polished_blackstone_bricks", - "blockRuntimeId" : 5997 + "blockRuntimeId" : 6003 }, { "id" : "minecraft:cracked_polished_blackstone_bricks", - "blockRuntimeId" : 3769 + "blockRuntimeId" : 3770 }, { "id" : "minecraft:gilded_blackstone", - "blockRuntimeId" : 4881 + "blockRuntimeId" : 4883 }, { "id" : "minecraft:chiseled_polished_blackstone", @@ -853,19 +853,19 @@ }, { "id" : "minecraft:deepslate_tiles", - "blockRuntimeId" : 4459 + "blockRuntimeId" : 4460 }, { "id" : "minecraft:cracked_deepslate_tiles", - "blockRuntimeId" : 3767 + "blockRuntimeId" : 3768 }, { "id" : "minecraft:deepslate_bricks", - "blockRuntimeId" : 4276 + "blockRuntimeId" : 4277 }, { "id" : "minecraft:cracked_deepslate_bricks", - "blockRuntimeId" : 3766 + "blockRuntimeId" : 3767 }, { "id" : "minecraft:chiseled_deepslate", @@ -873,195 +873,195 @@ }, { "id" : "minecraft:cobblestone", - "blockRuntimeId" : 1317 + "blockRuntimeId" : 1318 }, { "id" : "minecraft:mossy_cobblestone", - "blockRuntimeId" : 5666 + "blockRuntimeId" : 5668 }, { "id" : "minecraft:cobbled_deepslate", - "blockRuntimeId" : 1142 + "blockRuntimeId" : 1143 }, { "id" : "minecraft:smooth_stone", - "blockRuntimeId" : 6907 + "blockRuntimeId" : 6908 }, { "id" : "minecraft:sandstone", - "blockRuntimeId" : 6703 + "blockRuntimeId" : 6709 }, { "id" : "minecraft:sandstone", - "blockRuntimeId" : 6704 + "blockRuntimeId" : 6710 }, { "id" : "minecraft:sandstone", - "blockRuntimeId" : 6705 + "blockRuntimeId" : 6711 }, { "id" : "minecraft:sandstone", - "blockRuntimeId" : 6706 + "blockRuntimeId" : 6712 }, { "id" : "minecraft:red_sandstone", - "blockRuntimeId" : 6630 + "blockRuntimeId" : 6636 }, { "id" : "minecraft:red_sandstone", - "blockRuntimeId" : 6631 + "blockRuntimeId" : 6637 }, { "id" : "minecraft:red_sandstone", - "blockRuntimeId" : 6632 + "blockRuntimeId" : 6638 }, { "id" : "minecraft:red_sandstone", - "blockRuntimeId" : 6633 + "blockRuntimeId" : 6639 }, { "id" : "minecraft:coal_block", - "blockRuntimeId" : 1140 + "blockRuntimeId" : 1141 }, { "id" : "minecraft:dried_kelp_block", - "blockRuntimeId" : 4583 + "blockRuntimeId" : 4584 }, { "id" : "minecraft:gold_block", - "blockRuntimeId" : 4974 + "blockRuntimeId" : 4976 }, { "id" : "minecraft:iron_block", - "blockRuntimeId" : 5133 + "blockRuntimeId" : 5135 }, { "id" : "minecraft:copper_block", - "blockRuntimeId" : 3676 + "blockRuntimeId" : 3677 }, { "id" : "minecraft:exposed_copper", - "blockRuntimeId" : 4751 - }, - { - "id" : "minecraft:weathered_copper", - "blockRuntimeId" : 7737 - }, - { - "id" : "minecraft:oxidized_copper", - "blockRuntimeId" : 5751 - }, - { - "id" : "minecraft:waxed_copper", - "blockRuntimeId" : 7681 - }, - { - "id" : "minecraft:waxed_exposed_copper", - "blockRuntimeId" : 7695 - }, - { - "id" : "minecraft:waxed_weathered_copper", - "blockRuntimeId" : 7723 - }, - { - "id" : "minecraft:waxed_oxidized_copper", - "blockRuntimeId" : 7709 - }, - { - "id" : "minecraft:cut_copper", - "blockRuntimeId" : 3909 - }, - { - "id" : "minecraft:exposed_cut_copper", "blockRuntimeId" : 4752 }, + { + "id" : "minecraft:weathered_copper", + "blockRuntimeId" : 7739 + }, + { + "id" : "minecraft:oxidized_copper", + "blockRuntimeId" : 5756 + }, + { + "id" : "minecraft:waxed_copper", + "blockRuntimeId" : 7683 + }, + { + "id" : "minecraft:waxed_exposed_copper", + "blockRuntimeId" : 7697 + }, + { + "id" : "minecraft:waxed_weathered_copper", + "blockRuntimeId" : 7725 + }, + { + "id" : "minecraft:waxed_oxidized_copper", + "blockRuntimeId" : 7711 + }, + { + "id" : "minecraft:cut_copper", + "blockRuntimeId" : 3910 + }, + { + "id" : "minecraft:exposed_cut_copper", + "blockRuntimeId" : 4753 + }, { "id" : "minecraft:weathered_cut_copper", - "blockRuntimeId" : 7738 + "blockRuntimeId" : 7740 }, { "id" : "minecraft:oxidized_cut_copper", - "blockRuntimeId" : 5752 + "blockRuntimeId" : 5757 }, { "id" : "minecraft:waxed_cut_copper", - "blockRuntimeId" : 7682 + "blockRuntimeId" : 7684 }, { "id" : "minecraft:waxed_exposed_cut_copper", - "blockRuntimeId" : 7696 + "blockRuntimeId" : 7698 }, { "id" : "minecraft:waxed_weathered_cut_copper", - "blockRuntimeId" : 7724 + "blockRuntimeId" : 7726 }, { "id" : "minecraft:waxed_oxidized_cut_copper", - "blockRuntimeId" : 7710 + "blockRuntimeId" : 7712 }, { "id" : "minecraft:emerald_block", - "blockRuntimeId" : 4716 + "blockRuntimeId" : 4717 }, { "id" : "minecraft:diamond_block", - "blockRuntimeId" : 4473 + "blockRuntimeId" : 4474 }, { "id" : "minecraft:lapis_block", - "blockRuntimeId" : 5364 + "blockRuntimeId" : 5366 }, { "id" : "minecraft:raw_iron_block", - "blockRuntimeId" : 6576 + "blockRuntimeId" : 6582 }, { "id" : "minecraft:raw_copper_block", - "blockRuntimeId" : 6574 + "blockRuntimeId" : 6580 }, { "id" : "minecraft:raw_gold_block", - "blockRuntimeId" : 6575 + "blockRuntimeId" : 6581 }, { "id" : "minecraft:quartz_block", - "blockRuntimeId" : 6542 + "blockRuntimeId" : 6548 }, { "id" : "minecraft:quartz_block", - "blockRuntimeId" : 6544 + "blockRuntimeId" : 6550 }, { "id" : "minecraft:quartz_block", - "blockRuntimeId" : 6543 + "blockRuntimeId" : 6549 }, { "id" : "minecraft:quartz_block", - "blockRuntimeId" : 6545 + "blockRuntimeId" : 6551 }, { "id" : "minecraft:prismarine", - "blockRuntimeId" : 6435 + "blockRuntimeId" : 6441 }, { "id" : "minecraft:prismarine", - "blockRuntimeId" : 6436 + "blockRuntimeId" : 6442 }, { "id" : "minecraft:slime", - "blockRuntimeId" : 6860 + "blockRuntimeId" : 6861 }, { "id" : "minecraft:honey_block", - "blockRuntimeId" : 5111 + "blockRuntimeId" : 5113 }, { "id" : "minecraft:honeycomb_block", - "blockRuntimeId" : 5112 + "blockRuntimeId" : 5114 }, { "id" : "minecraft:hay_block", - "blockRuntimeId" : 5083 + "blockRuntimeId" : 5085 }, { "id" : "minecraft:bone_block", @@ -1069,27 +1069,51 @@ }, { "id" : "minecraft:nether_brick", - "blockRuntimeId" : 5685 + "blockRuntimeId" : 5689 }, { "id" : "minecraft:red_nether_brick", - "blockRuntimeId" : 6621 + "blockRuntimeId" : 6627 }, { "id" : "minecraft:netherite_block", - "blockRuntimeId" : 5702 + "blockRuntimeId" : 5706 }, { "id" : "minecraft:lodestone", - "blockRuntimeId" : 5562 + "blockRuntimeId" : 5564 }, { "id" : "minecraft:wool", - "blockRuntimeId" : 7911 + "blockRuntimeId" : 7913 }, { "id" : "minecraft:wool", - "blockRuntimeId" : 7919 + "blockRuntimeId" : 7921 + }, + { + "id" : "minecraft:wool", + "blockRuntimeId" : 7920 + }, + { + "id" : "minecraft:wool", + "blockRuntimeId" : 7928 + }, + { + "id" : "minecraft:wool", + "blockRuntimeId" : 7925 + }, + { + "id" : "minecraft:wool", + "blockRuntimeId" : 7927 + }, + { + "id" : "minecraft:wool", + "blockRuntimeId" : 7914 + }, + { + "id" : "minecraft:wool", + "blockRuntimeId" : 7917 }, { "id" : "minecraft:wool", @@ -1101,19 +1125,7 @@ }, { "id" : "minecraft:wool", - "blockRuntimeId" : 7923 - }, - { - "id" : "minecraft:wool", - "blockRuntimeId" : 7925 - }, - { - "id" : "minecraft:wool", - "blockRuntimeId" : 7912 - }, - { - "id" : "minecraft:wool", - "blockRuntimeId" : 7915 + "blockRuntimeId" : 7922 }, { "id" : "minecraft:wool", @@ -1125,27 +1137,15 @@ }, { "id" : "minecraft:wool", - "blockRuntimeId" : 7920 + "blockRuntimeId" : 7923 }, { "id" : "minecraft:wool", - "blockRuntimeId" : 7914 + "blockRuntimeId" : 7915 }, { "id" : "minecraft:wool", - "blockRuntimeId" : 7922 - }, - { - "id" : "minecraft:wool", - "blockRuntimeId" : 7921 - }, - { - "id" : "minecraft:wool", - "blockRuntimeId" : 7913 - }, - { - "id" : "minecraft:wool", - "blockRuntimeId" : 7917 + "blockRuntimeId" : 7919 }, { "id" : "minecraft:carpet", @@ -1211,93 +1211,69 @@ "id" : "minecraft:carpet", "blockRuntimeId" : 969 }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3659 - }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3667 - }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3666 - }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3674 - }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3671 - }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3673 - }, { "id" : "minecraft:concrete_powder", "blockRuntimeId" : 3660 }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3663 - }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3664 - }, - { - "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3672 - }, { "id" : "minecraft:concrete_powder", "blockRuntimeId" : 3668 }, { "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3662 + "blockRuntimeId" : 3667 }, { "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3670 + "blockRuntimeId" : 3675 }, { "id" : "minecraft:concrete_powder", - "blockRuntimeId" : 3669 + "blockRuntimeId" : 3672 + }, + { + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3674 }, { "id" : "minecraft:concrete_powder", "blockRuntimeId" : 3661 }, + { + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3664 + }, { "id" : "minecraft:concrete_powder", "blockRuntimeId" : 3665 }, { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3643 + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3673 }, { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3651 + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3669 }, { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3650 + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3663 }, { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3658 + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3671 }, { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3655 + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3670 }, { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3657 + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3662 + }, + { + "id" : "minecraft:concrete_powder", + "blockRuntimeId" : 3666 }, { "id" : "minecraft:concrete", @@ -1305,11 +1281,15 @@ }, { "id" : "minecraft:concrete", - "blockRuntimeId" : 3647 + "blockRuntimeId" : 3652 }, { "id" : "minecraft:concrete", - "blockRuntimeId" : 3648 + "blockRuntimeId" : 3651 + }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3659 }, { "id" : "minecraft:concrete", @@ -1317,59 +1297,55 @@ }, { "id" : "minecraft:concrete", - "blockRuntimeId" : 3652 - }, - { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3646 - }, - { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3654 - }, - { - "id" : "minecraft:concrete", - "blockRuntimeId" : 3653 + "blockRuntimeId" : 3658 }, { "id" : "minecraft:concrete", "blockRuntimeId" : 3645 }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3648 + }, { "id" : "minecraft:concrete", "blockRuntimeId" : 3649 }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3657 + }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3653 + }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3647 + }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3655 + }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3654 + }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3646 + }, + { + "id" : "minecraft:concrete", + "blockRuntimeId" : 3650 + }, { "id" : "minecraft:clay", "blockRuntimeId" : 1139 }, { "id" : "minecraft:hardened_clay", - "blockRuntimeId" : 5082 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7116 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7124 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7123 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7131 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7128 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7130 + "blockRuntimeId" : 5084 }, { "id" : "minecraft:stained_hardened_clay", @@ -1377,11 +1353,15 @@ }, { "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7120 + "blockRuntimeId" : 7125 }, { "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7121 + "blockRuntimeId" : 7124 + }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7132 }, { "id" : "minecraft:stained_hardened_clay", @@ -1389,39 +1369,59 @@ }, { "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7125 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7119 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7127 - }, - { - "id" : "minecraft:stained_hardened_clay", - "blockRuntimeId" : 7126 + "blockRuntimeId" : 7131 }, { "id" : "minecraft:stained_hardened_clay", "blockRuntimeId" : 7118 }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7121 + }, { "id" : "minecraft:stained_hardened_clay", "blockRuntimeId" : 7122 }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7130 + }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7126 + }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7120 + }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7128 + }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7127 + }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7119 + }, + { + "id" : "minecraft:stained_hardened_clay", + "blockRuntimeId" : 7123 + }, { "id" : "minecraft:white_glazed_terracotta", - "blockRuntimeId" : 7796 + "blockRuntimeId" : 7798 }, { "id" : "minecraft:silver_glazed_terracotta", - "blockRuntimeId" : 6842 + "blockRuntimeId" : 6849 }, { "id" : "minecraft:gray_glazed_terracotta", - "blockRuntimeId" : 5009 + "blockRuntimeId" : 5011 }, { "id" : "minecraft:black_glazed_terracotta", @@ -1433,31 +1433,31 @@ }, { "id" : "minecraft:red_glazed_terracotta", - "blockRuntimeId" : 6598 + "blockRuntimeId" : 6604 }, { "id" : "minecraft:orange_glazed_terracotta", - "blockRuntimeId" : 5745 + "blockRuntimeId" : 5750 }, { "id" : "minecraft:yellow_glazed_terracotta", - "blockRuntimeId" : 7938 + "blockRuntimeId" : 7940 }, { "id" : "minecraft:lime_glazed_terracotta", - "blockRuntimeId" : 5531 + "blockRuntimeId" : 5533 }, { "id" : "minecraft:green_glazed_terracotta", - "blockRuntimeId" : 5025 + "blockRuntimeId" : 5027 }, { "id" : "minecraft:cyan_glazed_terracotta", - "blockRuntimeId" : 3930 + "blockRuntimeId" : 3931 }, { "id" : "minecraft:light_blue_glazed_terracotta", - "blockRuntimeId" : 5483 + "blockRuntimeId" : 5485 }, { "id" : "minecraft:blue_glazed_terracotta", @@ -1465,43 +1465,43 @@ }, { "id" : "minecraft:purple_glazed_terracotta", - "blockRuntimeId" : 6516 - }, - { - "id" : "minecraft:magenta_glazed_terracotta", - "blockRuntimeId" : 5595 - }, - { - "id" : "minecraft:pink_glazed_terracotta", - "blockRuntimeId" : 5776 - }, - { - "id" : "minecraft:purpur_block", "blockRuntimeId" : 6522 }, + { + "id" : "minecraft:magenta_glazed_terracotta", + "blockRuntimeId" : 5597 + }, + { + "id" : "minecraft:pink_glazed_terracotta", + "blockRuntimeId" : 5782 + }, { "id" : "minecraft:purpur_block", - "blockRuntimeId" : 6524 + "blockRuntimeId" : 6528 + }, + { + "id" : "minecraft:purpur_block", + "blockRuntimeId" : 6530 }, { "id" : "minecraft:nether_wart_block", - "blockRuntimeId" : 5701 + "blockRuntimeId" : 5705 }, { "id" : "minecraft:warped_wart_block", - "blockRuntimeId" : 7663 + "blockRuntimeId" : 7665 }, { "id" : "minecraft:shroomlight", - "blockRuntimeId" : 6825 + "blockRuntimeId" : 6832 }, { "id" : "minecraft:crimson_nylium", - "blockRuntimeId" : 3838 + "blockRuntimeId" : 3839 }, { "id" : "minecraft:warped_nylium", - "blockRuntimeId" : 7593 + "blockRuntimeId" : 7595 }, { "id" : "minecraft:basalt", @@ -1509,87 +1509,87 @@ }, { "id" : "minecraft:polished_basalt", - "blockRuntimeId" : 5819 + "blockRuntimeId" : 5825 }, { "id" : "minecraft:smooth_basalt", - "blockRuntimeId" : 6882 + "blockRuntimeId" : 6883 }, { "id" : "minecraft:soul_soil", - "blockRuntimeId" : 6952 - }, - { - "id" : "minecraft:dirt", - "blockRuntimeId" : 4483 + "blockRuntimeId" : 6953 }, { "id" : "minecraft:dirt", "blockRuntimeId" : 4484 }, + { + "id" : "minecraft:dirt", + "blockRuntimeId" : 4485 + }, { "id" : "minecraft:farmland", - "blockRuntimeId" : 4765 + "blockRuntimeId" : 4766 }, { "id" : "minecraft:grass", - "blockRuntimeId" : 4996 + "blockRuntimeId" : 4998 }, { "id" : "minecraft:grass_path", - "blockRuntimeId" : 4997 + "blockRuntimeId" : 4999 }, { "id" : "minecraft:podzol", - "blockRuntimeId" : 5800 + "blockRuntimeId" : 5806 }, { "id" : "minecraft:mycelium", - "blockRuntimeId" : 5684 + "blockRuntimeId" : 5686 }, { "id" : "minecraft:stone", - "blockRuntimeId" : 7176 + "blockRuntimeId" : 7177 }, { "id" : "minecraft:iron_ore", - "blockRuntimeId" : 5166 + "blockRuntimeId" : 5168 }, { "id" : "minecraft:gold_ore", - "blockRuntimeId" : 4975 + "blockRuntimeId" : 4977 }, { "id" : "minecraft:diamond_ore", - "blockRuntimeId" : 4474 + "blockRuntimeId" : 4475 }, { "id" : "minecraft:lapis_ore", - "blockRuntimeId" : 5365 + "blockRuntimeId" : 5367 }, { "id" : "minecraft:redstone_ore", - "blockRuntimeId" : 6644 + "blockRuntimeId" : 6650 }, { "id" : "minecraft:coal_ore", - "blockRuntimeId" : 1141 + "blockRuntimeId" : 1142 }, { "id" : "minecraft:copper_ore", - "blockRuntimeId" : 3677 + "blockRuntimeId" : 3678 }, { "id" : "minecraft:emerald_ore", - "blockRuntimeId" : 4717 + "blockRuntimeId" : 4718 }, { "id" : "minecraft:quartz_ore", - "blockRuntimeId" : 6555 + "blockRuntimeId" : 6561 }, { "id" : "minecraft:nether_gold_ore", - "blockRuntimeId" : 5695 + "blockRuntimeId" : 5699 }, { "id" : "minecraft:ancient_debris", @@ -1597,59 +1597,39 @@ }, { "id" : "minecraft:deepslate_iron_ore", - "blockRuntimeId" : 4282 - }, - { - "id" : "minecraft:deepslate_gold_ore", - "blockRuntimeId" : 4281 - }, - { - "id" : "minecraft:deepslate_diamond_ore", - "blockRuntimeId" : 4279 - }, - { - "id" : "minecraft:deepslate_lapis_ore", "blockRuntimeId" : 4283 }, { - "id" : "minecraft:deepslate_redstone_ore", - "blockRuntimeId" : 4284 + "id" : "minecraft:deepslate_gold_ore", + "blockRuntimeId" : 4282 }, { - "id" : "minecraft:deepslate_emerald_ore", + "id" : "minecraft:deepslate_diamond_ore", "blockRuntimeId" : 4280 }, { - "id" : "minecraft:deepslate_coal_ore", - "blockRuntimeId" : 4277 + "id" : "minecraft:deepslate_lapis_ore", + "blockRuntimeId" : 4284 }, { - "id" : "minecraft:deepslate_copper_ore", + "id" : "minecraft:deepslate_redstone_ore", + "blockRuntimeId" : 4285 + }, + { + "id" : "minecraft:deepslate_emerald_ore", + "blockRuntimeId" : 4281 + }, + { + "id" : "minecraft:deepslate_coal_ore", "blockRuntimeId" : 4278 }, + { + "id" : "minecraft:deepslate_copper_ore", + "blockRuntimeId" : 4279 + }, { "id" : "minecraft:gravel", - "blockRuntimeId" : 4998 - }, - { - "id" : "minecraft:stone", - "blockRuntimeId" : 7177 - }, - { - "id" : "minecraft:stone", - "blockRuntimeId" : 7179 - }, - { - "id" : "minecraft:stone", - "blockRuntimeId" : 7181 - }, - { - "id" : "minecraft:blackstone", - "blockRuntimeId" : 494 - }, - { - "id" : "minecraft:deepslate", - "blockRuntimeId" : 4099 + "blockRuntimeId" : 5000 }, { "id" : "minecraft:stone", @@ -1663,105 +1643,109 @@ "id" : "minecraft:stone", "blockRuntimeId" : 7182 }, + { + "id" : "minecraft:blackstone", + "blockRuntimeId" : 494 + }, + { + "id" : "minecraft:deepslate", + "blockRuntimeId" : 4100 + }, + { + "id" : "minecraft:stone", + "blockRuntimeId" : 7179 + }, + { + "id" : "minecraft:stone", + "blockRuntimeId" : 7181 + }, + { + "id" : "minecraft:stone", + "blockRuntimeId" : 7183 + }, { "id" : "minecraft:polished_blackstone", - "blockRuntimeId" : 5822 + "blockRuntimeId" : 5828 }, { "id" : "minecraft:polished_deepslate", - "blockRuntimeId" : 6200 + "blockRuntimeId" : 6206 }, { "id" : "minecraft:sand", - "blockRuntimeId" : 6701 + "blockRuntimeId" : 6707 }, { "id" : "minecraft:sand", - "blockRuntimeId" : 6702 + "blockRuntimeId" : 6708 }, { "id" : "minecraft:cactus", "blockRuntimeId" : 920 }, - { - "id" : "minecraft:log", - "blockRuntimeId" : 5563 - }, - { - "id" : "minecraft:stripped_oak_log", - "blockRuntimeId" : 7315 - }, - { - "id" : "minecraft:log", - "blockRuntimeId" : 5564 - }, - { - "id" : "minecraft:stripped_spruce_log", - "blockRuntimeId" : 7318 - }, { "id" : "minecraft:log", "blockRuntimeId" : 5565 }, { - "id" : "minecraft:stripped_birch_log", - "blockRuntimeId" : 7300 + "id" : "minecraft:stripped_oak_log", + "blockRuntimeId" : 7316 }, { "id" : "minecraft:log", "blockRuntimeId" : 5566 }, + { + "id" : "minecraft:stripped_spruce_log", + "blockRuntimeId" : 7319 + }, + { + "id" : "minecraft:log", + "blockRuntimeId" : 5567 + }, + { + "id" : "minecraft:stripped_birch_log", + "blockRuntimeId" : 7301 + }, + { + "id" : "minecraft:log", + "blockRuntimeId" : 5568 + }, { "id" : "minecraft:stripped_jungle_log", - "blockRuntimeId" : 7312 + "blockRuntimeId" : 7313 }, { "id" : "minecraft:log2", - "blockRuntimeId" : 5575 + "blockRuntimeId" : 5577 }, { "id" : "minecraft:stripped_acacia_log", - "blockRuntimeId" : 7297 + "blockRuntimeId" : 7298 }, { "id" : "minecraft:log2", - "blockRuntimeId" : 5576 + "blockRuntimeId" : 5578 }, { "id" : "minecraft:stripped_dark_oak_log", - "blockRuntimeId" : 7309 + "blockRuntimeId" : 7310 }, { "id" : "minecraft:crimson_stem", - "blockRuntimeId" : 3883 + "blockRuntimeId" : 3884 }, { "id" : "minecraft:stripped_crimson_stem", - "blockRuntimeId" : 7306 + "blockRuntimeId" : 7307 }, { "id" : "minecraft:warped_stem", - "blockRuntimeId" : 7638 + "blockRuntimeId" : 7640 }, { "id" : "minecraft:stripped_warped_stem", - "blockRuntimeId" : 7324 - }, - { - "id" : "minecraft:wood", - "blockRuntimeId" : 7803 - }, - { - "id" : "minecraft:wood", - "blockRuntimeId" : 7809 - }, - { - "id" : "minecraft:wood", - "blockRuntimeId" : 7804 - }, - { - "id" : "minecraft:wood", - "blockRuntimeId" : 7810 + "blockRuntimeId" : 7325 }, { "id" : "minecraft:wood", @@ -1795,29 +1779,37 @@ "id" : "minecraft:wood", "blockRuntimeId" : 7814 }, + { + "id" : "minecraft:wood", + "blockRuntimeId" : 7809 + }, + { + "id" : "minecraft:wood", + "blockRuntimeId" : 7815 + }, + { + "id" : "minecraft:wood", + "blockRuntimeId" : 7810 + }, + { + "id" : "minecraft:wood", + "blockRuntimeId" : 7816 + }, { "id" : "minecraft:crimson_hyphae", - "blockRuntimeId" : 3835 + "blockRuntimeId" : 3836 }, { "id" : "minecraft:stripped_crimson_hyphae", - "blockRuntimeId" : 7303 + "blockRuntimeId" : 7304 }, { "id" : "minecraft:warped_hyphae", - "blockRuntimeId" : 7590 + "blockRuntimeId" : 7592 }, { "id" : "minecraft:stripped_warped_hyphae", - "blockRuntimeId" : 7321 - }, - { - "id" : "minecraft:leaves", - "blockRuntimeId" : 5409 - }, - { - "id" : "minecraft:leaves", - "blockRuntimeId" : 5410 + "blockRuntimeId" : 7322 }, { "id" : "minecraft:leaves", @@ -1828,12 +1820,20 @@ "blockRuntimeId" : 5412 }, { - "id" : "minecraft:leaves2", - "blockRuntimeId" : 5425 + "id" : "minecraft:leaves", + "blockRuntimeId" : 5413 + }, + { + "id" : "minecraft:leaves", + "blockRuntimeId" : 5414 }, { "id" : "minecraft:leaves2", - "blockRuntimeId" : 5426 + "blockRuntimeId" : 5427 + }, + { + "id" : "minecraft:leaves2", + "blockRuntimeId" : 5428 }, { "id" : "minecraft:azalea_leaves", @@ -1845,27 +1845,27 @@ }, { "id" : "minecraft:sapling", - "blockRuntimeId" : 6715 + "blockRuntimeId" : 6721 }, { "id" : "minecraft:sapling", - "blockRuntimeId" : 6716 + "blockRuntimeId" : 6722 }, { "id" : "minecraft:sapling", - "blockRuntimeId" : 6717 + "blockRuntimeId" : 6723 }, { "id" : "minecraft:sapling", - "blockRuntimeId" : 6718 + "blockRuntimeId" : 6724 }, { "id" : "minecraft:sapling", - "blockRuntimeId" : 6719 + "blockRuntimeId" : 6725 }, { "id" : "minecraft:sapling", - "blockRuntimeId" : 6720 + "blockRuntimeId" : 6726 }, { "id" : "minecraft:bee_nest", @@ -1912,7 +1912,7 @@ }, { "id" : "minecraft:melon_block", - "blockRuntimeId" : 5608 + "blockRuntimeId" : 5610 }, { "id" : "minecraft:melon_slice" @@ -1928,7 +1928,7 @@ }, { "id" : "minecraft:pumpkin", - "blockRuntimeId" : 6454 + "blockRuntimeId" : 6460 }, { "id" : "minecraft:carved_pumpkin", @@ -1936,11 +1936,19 @@ }, { "id" : "minecraft:lit_pumpkin", - "blockRuntimeId" : 5550 + "blockRuntimeId" : 5552 }, { "id" : "minecraft:honeycomb" }, + { + "id" : "minecraft:tallgrass", + "blockRuntimeId" : 7346 + }, + { + "id" : "minecraft:double_plant", + "blockRuntimeId" : 4504 + }, { "id" : "minecraft:tallgrass", "blockRuntimeId" : 7345 @@ -1949,17 +1957,17 @@ "id" : "minecraft:double_plant", "blockRuntimeId" : 4503 }, - { - "id" : "minecraft:tallgrass", - "blockRuntimeId" : 7344 - }, - { - "id" : "minecraft:double_plant", - "blockRuntimeId" : 4502 - }, { "id" : "minecraft:nether_sprouts" }, + { + "id" : "minecraft:coral", + "blockRuntimeId" : 3682 + }, + { + "id" : "minecraft:coral", + "blockRuntimeId" : 3680 + }, { "id" : "minecraft:coral", "blockRuntimeId" : 3681 @@ -1970,15 +1978,15 @@ }, { "id" : "minecraft:coral", - "blockRuntimeId" : 3680 + "blockRuntimeId" : 3683 }, { "id" : "minecraft:coral", - "blockRuntimeId" : 3678 + "blockRuntimeId" : 3687 }, { "id" : "minecraft:coral", - "blockRuntimeId" : 3682 + "blockRuntimeId" : 3685 }, { "id" : "minecraft:coral", @@ -1990,15 +1998,15 @@ }, { "id" : "minecraft:coral", - "blockRuntimeId" : 3685 + "blockRuntimeId" : 3688 }, { - "id" : "minecraft:coral", - "blockRuntimeId" : 3683 + "id" : "minecraft:coral_fan", + "blockRuntimeId" : 3702 }, { - "id" : "minecraft:coral", - "blockRuntimeId" : 3687 + "id" : "minecraft:coral_fan", + "blockRuntimeId" : 3700 }, { "id" : "minecraft:coral_fan", @@ -2010,15 +2018,15 @@ }, { "id" : "minecraft:coral_fan", - "blockRuntimeId" : 3700 + "blockRuntimeId" : 3703 }, { - "id" : "minecraft:coral_fan", - "blockRuntimeId" : 3698 + "id" : "minecraft:coral_fan_dead", + "blockRuntimeId" : 3712 }, { - "id" : "minecraft:coral_fan", - "blockRuntimeId" : 3702 + "id" : "minecraft:coral_fan_dead", + "blockRuntimeId" : 3710 }, { "id" : "minecraft:coral_fan_dead", @@ -2030,58 +2038,26 @@ }, { "id" : "minecraft:coral_fan_dead", - "blockRuntimeId" : 3710 - }, - { - "id" : "minecraft:coral_fan_dead", - "blockRuntimeId" : 3708 - }, - { - "id" : "minecraft:coral_fan_dead", - "blockRuntimeId" : 3712 + "blockRuntimeId" : 3713 }, { "id" : "minecraft:kelp" }, { "id" : "minecraft:seagrass", - "blockRuntimeId" : 6821 + "blockRuntimeId" : 6828 }, { "id" : "minecraft:crimson_roots", - "blockRuntimeId" : 3856 + "blockRuntimeId" : 3857 }, { "id" : "minecraft:warped_roots", - "blockRuntimeId" : 7611 + "blockRuntimeId" : 7613 }, { "id" : "minecraft:yellow_flower", - "blockRuntimeId" : 7937 - }, - { - "id" : "minecraft:red_flower", - "blockRuntimeId" : 6587 - }, - { - "id" : "minecraft:red_flower", - "blockRuntimeId" : 6588 - }, - { - "id" : "minecraft:red_flower", - "blockRuntimeId" : 6589 - }, - { - "id" : "minecraft:red_flower", - "blockRuntimeId" : 6590 - }, - { - "id" : "minecraft:red_flower", - "blockRuntimeId" : 6591 - }, - { - "id" : "minecraft:red_flower", - "blockRuntimeId" : 6592 + "blockRuntimeId" : 7939 }, { "id" : "minecraft:red_flower", @@ -2104,8 +2080,28 @@ "blockRuntimeId" : 6597 }, { - "id" : "minecraft:double_plant", - "blockRuntimeId" : 4500 + "id" : "minecraft:red_flower", + "blockRuntimeId" : 6598 + }, + { + "id" : "minecraft:red_flower", + "blockRuntimeId" : 6599 + }, + { + "id" : "minecraft:red_flower", + "blockRuntimeId" : 6600 + }, + { + "id" : "minecraft:red_flower", + "blockRuntimeId" : 6601 + }, + { + "id" : "minecraft:red_flower", + "blockRuntimeId" : 6602 + }, + { + "id" : "minecraft:red_flower", + "blockRuntimeId" : 6603 }, { "id" : "minecraft:double_plant", @@ -2113,15 +2109,19 @@ }, { "id" : "minecraft:double_plant", - "blockRuntimeId" : 4504 + "blockRuntimeId" : 4502 }, { "id" : "minecraft:double_plant", "blockRuntimeId" : 4505 }, + { + "id" : "minecraft:double_plant", + "blockRuntimeId" : 4506 + }, { "id" : "minecraft:wither_rose", - "blockRuntimeId" : 7802 + "blockRuntimeId" : 7804 }, { "id" : "minecraft:white_dye" @@ -2188,23 +2188,23 @@ }, { "id" : "minecraft:vine", - "blockRuntimeId" : 7498 + "blockRuntimeId" : 7500 }, { "id" : "minecraft:weeping_vines", - "blockRuntimeId" : 7752 + "blockRuntimeId" : 7754 }, { "id" : "minecraft:twisting_vines", - "blockRuntimeId" : 7426 + "blockRuntimeId" : 7427 }, { "id" : "minecraft:waterlily", - "blockRuntimeId" : 7680 + "blockRuntimeId" : 7682 }, { "id" : "minecraft:deadbush", - "blockRuntimeId" : 4098 + "blockRuntimeId" : 4099 }, { "id" : "minecraft:bamboo", @@ -2212,15 +2212,15 @@ }, { "id" : "minecraft:snow", - "blockRuntimeId" : 6908 + "blockRuntimeId" : 6909 }, { "id" : "minecraft:ice", - "blockRuntimeId" : 5125 + "blockRuntimeId" : 5127 }, { "id" : "minecraft:packed_ice", - "blockRuntimeId" : 5765 + "blockRuntimeId" : 5770 }, { "id" : "minecraft:blue_ice", @@ -2228,35 +2228,31 @@ }, { "id" : "minecraft:snow_layer", - "blockRuntimeId" : 6909 + "blockRuntimeId" : 6910 }, { "id" : "minecraft:pointed_dripstone", - "blockRuntimeId" : 5806 - }, - { - "id" : "minecraft:sculk_sensor", - "blockRuntimeId" : 6745 + "blockRuntimeId" : 5812 }, { "id" : "minecraft:dripstone_block", - "blockRuntimeId" : 4584 + "blockRuntimeId" : 4585 }, { "id" : "minecraft:moss_carpet", - "blockRuntimeId" : 5665 + "blockRuntimeId" : 5667 }, { "id" : "minecraft:moss_block", - "blockRuntimeId" : 5664 + "blockRuntimeId" : 5666 }, { "id" : "minecraft:dirt_with_roots", - "blockRuntimeId" : 4485 + "blockRuntimeId" : 4486 }, { "id" : "minecraft:hanging_roots", - "blockRuntimeId" : 5047 + "blockRuntimeId" : 5049 }, { "id" : "minecraft:big_dripleaf", @@ -2264,11 +2260,11 @@ }, { "id" : "minecraft:small_dripleaf_block", - "blockRuntimeId" : 6874 + "blockRuntimeId" : 6875 }, { "id" : "minecraft:spore_blossom", - "blockRuntimeId" : 6961 + "blockRuntimeId" : 6962 }, { "id" : "minecraft:azalea", @@ -2276,11 +2272,11 @@ }, { "id" : "minecraft:flowering_azalea", - "blockRuntimeId" : 4814 + "blockRuntimeId" : 4815 }, { "id" : "minecraft:glow_lichen", - "blockRuntimeId" : 4971 + "blockRuntimeId" : 4973 }, { "id" : "minecraft:amethyst_block", @@ -2292,23 +2288,23 @@ }, { "id" : "minecraft:amethyst_cluster", - "blockRuntimeId" : 137 + "blockRuntimeId" : 138 }, { "id" : "minecraft:large_amethyst_bud", - "blockRuntimeId" : 5366 + "blockRuntimeId" : 5369 }, { "id" : "minecraft:medium_amethyst_bud", - "blockRuntimeId" : 5602 + "blockRuntimeId" : 5605 }, { "id" : "minecraft:small_amethyst_bud", - "blockRuntimeId" : 6861 + "blockRuntimeId" : 6863 }, { "id" : "minecraft:tuff", - "blockRuntimeId" : 7413 + "blockRuntimeId" : 7414 }, { "id" : "minecraft:calcite", @@ -2347,15 +2343,15 @@ }, { "id" : "minecraft:red_mushroom", - "blockRuntimeId" : 6604 + "blockRuntimeId" : 6610 }, { "id" : "minecraft:crimson_fungus", - "blockRuntimeId" : 3834 + "blockRuntimeId" : 3835 }, { "id" : "minecraft:warped_fungus", - "blockRuntimeId" : 7589 + "blockRuntimeId" : 7591 }, { "id" : "minecraft:brown_mushroom_block", @@ -2363,7 +2359,7 @@ }, { "id" : "minecraft:red_mushroom_block", - "blockRuntimeId" : 6619 + "blockRuntimeId" : 6625 }, { "id" : "minecraft:brown_mushroom_block", @@ -2390,21 +2386,13 @@ }, { "id" : "minecraft:web", - "blockRuntimeId" : 7751 + "blockRuntimeId" : 7753 }, { "id" : "minecraft:spider_eye" }, { "id" : "minecraft:mob_spawner", - "blockRuntimeId" : 5657 - }, - { - "id" : "minecraft:monster_egg", - "blockRuntimeId" : 5658 - }, - { - "id" : "minecraft:monster_egg", "blockRuntimeId" : 5659 }, { @@ -2423,17 +2411,25 @@ "id" : "minecraft:monster_egg", "blockRuntimeId" : 5663 }, + { + "id" : "minecraft:monster_egg", + "blockRuntimeId" : 5664 + }, + { + "id" : "minecraft:monster_egg", + "blockRuntimeId" : 5665 + }, { "id" : "minecraft:infested_deepslate", - "blockRuntimeId" : 5126 + "blockRuntimeId" : 5128 }, { "id" : "minecraft:dragon_egg", - "blockRuntimeId" : 4582 + "blockRuntimeId" : 4583 }, { "id" : "minecraft:turtle_egg", - "blockRuntimeId" : 7414 + "blockRuntimeId" : 7415 }, { "id" : "minecraft:chicken_spawn_egg" @@ -2635,11 +2631,11 @@ }, { "id" : "minecraft:obsidian", - "blockRuntimeId" : 5734 + "blockRuntimeId" : 5738 }, { "id" : "minecraft:crying_obsidian", - "blockRuntimeId" : 3908 + "blockRuntimeId" : 3909 }, { "id" : "minecraft:bedrock", @@ -2647,22 +2643,22 @@ }, { "id" : "minecraft:soul_sand", - "blockRuntimeId" : 6951 + "blockRuntimeId" : 6952 }, { "id" : "minecraft:netherrack", - "blockRuntimeId" : 5703 + "blockRuntimeId" : 5707 }, { "id" : "minecraft:magma", - "blockRuntimeId" : 5601 + "blockRuntimeId" : 5603 }, { "id" : "minecraft:nether_wart" }, { "id" : "minecraft:end_stone", - "blockRuntimeId" : 4744 + "blockRuntimeId" : 4745 }, { "id" : "minecraft:chorus_flower", @@ -2678,17 +2674,13 @@ { "id" : "minecraft:popped_chorus_fruit" }, - { - "id" : "minecraft:sponge", - "blockRuntimeId" : 6959 - }, { "id" : "minecraft:sponge", "blockRuntimeId" : 6960 }, { - "id" : "minecraft:coral_block", - "blockRuntimeId" : 3688 + "id" : "minecraft:sponge", + "blockRuntimeId" : 6961 }, { "id" : "minecraft:coral_block", @@ -2726,6 +2718,10 @@ "id" : "minecraft:coral_block", "blockRuntimeId" : 3697 }, + { + "id" : "minecraft:coral_block", + "blockRuntimeId" : 3698 + }, { "id" : "minecraft:leather_helmet" }, @@ -3751,23 +3747,23 @@ }, { "id" : "minecraft:torch", - "blockRuntimeId" : 7353 + "blockRuntimeId" : 7354 }, { "id" : "minecraft:soul_torch", - "blockRuntimeId" : 6953 + "blockRuntimeId" : 6954 }, { "id" : "minecraft:sea_pickle", - "blockRuntimeId" : 6813 + "blockRuntimeId" : 6820 }, { "id" : "minecraft:lantern", - "blockRuntimeId" : 5362 + "blockRuntimeId" : 5364 }, { "id" : "minecraft:soul_lantern", - "blockRuntimeId" : 6949 + "blockRuntimeId" : 6950 }, { "id" : "minecraft:candle", @@ -3775,47 +3771,47 @@ }, { "id" : "minecraft:white_candle", - "blockRuntimeId" : 7786 + "blockRuntimeId" : 7788 }, { "id" : "minecraft:orange_candle", - "blockRuntimeId" : 5735 + "blockRuntimeId" : 5740 }, { "id" : "minecraft:magenta_candle", - "blockRuntimeId" : 5585 + "blockRuntimeId" : 5587 }, { "id" : "minecraft:light_blue_candle", - "blockRuntimeId" : 5473 + "blockRuntimeId" : 5475 }, { "id" : "minecraft:yellow_candle", - "blockRuntimeId" : 7927 + "blockRuntimeId" : 7929 }, { "id" : "minecraft:lime_candle", - "blockRuntimeId" : 5521 + "blockRuntimeId" : 5523 }, { "id" : "minecraft:pink_candle", - "blockRuntimeId" : 5766 + "blockRuntimeId" : 5772 }, { "id" : "minecraft:gray_candle", - "blockRuntimeId" : 4999 + "blockRuntimeId" : 5001 }, { "id" : "minecraft:light_gray_candle", - "blockRuntimeId" : 5489 + "blockRuntimeId" : 5491 }, { "id" : "minecraft:cyan_candle", - "blockRuntimeId" : 3920 + "blockRuntimeId" : 3921 }, { "id" : "minecraft:purple_candle", - "blockRuntimeId" : 6506 + "blockRuntimeId" : 6512 }, { "id" : "minecraft:blue_candle", @@ -3827,11 +3823,11 @@ }, { "id" : "minecraft:green_candle", - "blockRuntimeId" : 5015 + "blockRuntimeId" : 5017 }, { "id" : "minecraft:red_candle", - "blockRuntimeId" : 6577 + "blockRuntimeId" : 6583 }, { "id" : "minecraft:black_candle", @@ -3839,7 +3835,7 @@ }, { "id" : "minecraft:crafting_table", - "blockRuntimeId" : 3770 + "blockRuntimeId" : 3771 }, { "id" : "minecraft:cartography_table", @@ -3847,11 +3843,11 @@ }, { "id" : "minecraft:fletching_table", - "blockRuntimeId" : 4811 + "blockRuntimeId" : 4812 }, { "id" : "minecraft:smithing_table", - "blockRuntimeId" : 6875 + "blockRuntimeId" : 6876 }, { "id" : "minecraft:beehive", @@ -3865,7 +3861,7 @@ }, { "id" : "minecraft:furnace", - "blockRuntimeId" : 4875 + "blockRuntimeId" : 4877 }, { "id" : "minecraft:blast_furnace", @@ -3873,11 +3869,11 @@ }, { "id" : "minecraft:smoker", - "blockRuntimeId" : 6876 + "blockRuntimeId" : 6877 }, { "id" : "minecraft:respawn_anchor", - "blockRuntimeId" : 6696 + "blockRuntimeId" : 6702 }, { "id" : "minecraft:brewing_stand" @@ -3896,11 +3892,11 @@ }, { "id" : "minecraft:grindstone", - "blockRuntimeId" : 5031 + "blockRuntimeId" : 5033 }, { "id" : "minecraft:enchanting_table", - "blockRuntimeId" : 4718 + "blockRuntimeId" : 4719 }, { "id" : "minecraft:bookshelf", @@ -3908,14 +3904,14 @@ }, { "id" : "minecraft:lectern", - "blockRuntimeId" : 5433 + "blockRuntimeId" : 5435 }, { "id" : "minecraft:cauldron" }, { "id" : "minecraft:composter", - "blockRuntimeId" : 3634 + "blockRuntimeId" : 3635 }, { "id" : "minecraft:chest", @@ -3923,11 +3919,11 @@ }, { "id" : "minecraft:trapped_chest", - "blockRuntimeId" : 7375 + "blockRuntimeId" : 7376 }, { "id" : "minecraft:ender_chest", - "blockRuntimeId" : 4745 + "blockRuntimeId" : 4746 }, { "id" : "minecraft:barrel", @@ -3935,15 +3931,7 @@ }, { "id" : "minecraft:undyed_shulker_box", - "blockRuntimeId" : 7458 - }, - { - "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6826 - }, - { - "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6834 + "blockRuntimeId" : 7459 }, { "id" : "minecraft:shulker_box", @@ -3953,64 +3941,72 @@ "id" : "minecraft:shulker_box", "blockRuntimeId" : 6841 }, - { - "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6838 - }, { "id" : "minecraft:shulker_box", "blockRuntimeId" : 6840 }, { "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6827 + "blockRuntimeId" : 6848 }, { "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6830 + "blockRuntimeId" : 6845 }, { "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6831 + "blockRuntimeId" : 6847 }, { "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6839 - }, - { - "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6835 - }, - { - "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6829 + "blockRuntimeId" : 6834 }, { "id" : "minecraft:shulker_box", "blockRuntimeId" : 6837 }, + { + "id" : "minecraft:shulker_box", + "blockRuntimeId" : 6838 + }, + { + "id" : "minecraft:shulker_box", + "blockRuntimeId" : 6846 + }, + { + "id" : "minecraft:shulker_box", + "blockRuntimeId" : 6842 + }, { "id" : "minecraft:shulker_box", "blockRuntimeId" : 6836 }, { "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6828 + "blockRuntimeId" : 6844 }, { "id" : "minecraft:shulker_box", - "blockRuntimeId" : 6832 + "blockRuntimeId" : 6843 + }, + { + "id" : "minecraft:shulker_box", + "blockRuntimeId" : 6835 + }, + { + "id" : "minecraft:shulker_box", + "blockRuntimeId" : 6839 }, { "id" : "minecraft:armor_stand" }, { "id" : "minecraft:noteblock", - "blockRuntimeId" : 5713 + "blockRuntimeId" : 5717 }, { "id" : "minecraft:jukebox", - "blockRuntimeId" : 5207 + "blockRuntimeId" : 5209 }, { "id" : "minecraft:music_disc_13" @@ -4048,6 +4044,9 @@ { "id" : "minecraft:music_disc_wait" }, + { + "id" : "minecraft:music_disc_otherside" + }, { "id" : "minecraft:music_disc_pigstep" }, @@ -4056,15 +4055,15 @@ }, { "id" : "minecraft:glowstone", - "blockRuntimeId" : 4973 + "blockRuntimeId" : 4975 }, { "id" : "minecraft:redstone_lamp", - "blockRuntimeId" : 6643 + "blockRuntimeId" : 6649 }, { "id" : "minecraft:sealantern", - "blockRuntimeId" : 6824 + "blockRuntimeId" : 6831 }, { "id" : "minecraft:oak_sign" @@ -4171,15 +4170,15 @@ }, { "id" : "minecraft:conduit", - "blockRuntimeId" : 3675 + "blockRuntimeId" : 3676 }, { "id" : "minecraft:stonecutter_block", - "blockRuntimeId" : 7291 + "blockRuntimeId" : 7292 }, { "id" : "minecraft:end_portal_frame", - "blockRuntimeId" : 4730 + "blockRuntimeId" : 4731 }, { "id" : "minecraft:coal" @@ -4315,11 +4314,11 @@ }, { "id" : "minecraft:end_rod", - "blockRuntimeId" : 4738 + "blockRuntimeId" : 4739 }, { "id" : "minecraft:lightning_rod", - "blockRuntimeId" : 5515 + "blockRuntimeId" : 5517 }, { "id" : "minecraft:end_crystal" @@ -4781,15 +4780,15 @@ }, { "id" : "minecraft:rail", - "blockRuntimeId" : 6564 + "blockRuntimeId" : 6570 }, { "id" : "minecraft:golden_rail", - "blockRuntimeId" : 4976 + "blockRuntimeId" : 4978 }, { "id" : "minecraft:detector_rail", - "blockRuntimeId" : 4461 + "blockRuntimeId" : 4462 }, { "id" : "minecraft:activator_rail", @@ -4812,23 +4811,23 @@ }, { "id" : "minecraft:redstone_block", - "blockRuntimeId" : 6642 + "blockRuntimeId" : 6648 }, { "id" : "minecraft:redstone_torch", - "blockRuntimeId" : 6645 + "blockRuntimeId" : 6651 }, { "id" : "minecraft:lever", - "blockRuntimeId" : 5441 + "blockRuntimeId" : 5443 }, { "id" : "minecraft:wooden_button", - "blockRuntimeId" : 7839 + "blockRuntimeId" : 7841 }, { "id" : "minecraft:spruce_button", - "blockRuntimeId" : 6962 + "blockRuntimeId" : 6963 }, { "id" : "minecraft:birch_button", @@ -4836,42 +4835,42 @@ }, { "id" : "minecraft:jungle_button", - "blockRuntimeId" : 5208 + "blockRuntimeId" : 5210 }, { "id" : "minecraft:acacia_button" }, { "id" : "minecraft:dark_oak_button", - "blockRuntimeId" : 3936 + "blockRuntimeId" : 3937 }, { "id" : "minecraft:stone_button", - "blockRuntimeId" : 7191 + "blockRuntimeId" : 7192 }, { "id" : "minecraft:crimson_button", - "blockRuntimeId" : 3771 + "blockRuntimeId" : 3772 }, { "id" : "minecraft:warped_button", - "blockRuntimeId" : 7526 + "blockRuntimeId" : 7528 }, { "id" : "minecraft:polished_blackstone_button", - "blockRuntimeId" : 5998 + "blockRuntimeId" : 6004 }, { "id" : "minecraft:tripwire_hook", - "blockRuntimeId" : 7397 + "blockRuntimeId" : 7398 }, { "id" : "minecraft:wooden_pressure_plate", - "blockRuntimeId" : 7883 + "blockRuntimeId" : 7885 }, { "id" : "minecraft:spruce_pressure_plate", - "blockRuntimeId" : 7022 + "blockRuntimeId" : 7023 }, { "id" : "minecraft:birch_pressure_plate", @@ -4879,7 +4878,7 @@ }, { "id" : "minecraft:jungle_pressure_plate", - "blockRuntimeId" : 5268 + "blockRuntimeId" : 5270 }, { "id" : "minecraft:acacia_pressure_plate", @@ -4887,39 +4886,39 @@ }, { "id" : "minecraft:dark_oak_pressure_plate", - "blockRuntimeId" : 3996 + "blockRuntimeId" : 3997 }, { "id" : "minecraft:crimson_pressure_plate", - "blockRuntimeId" : 3840 + "blockRuntimeId" : 3841 }, { "id" : "minecraft:warped_pressure_plate", - "blockRuntimeId" : 7595 + "blockRuntimeId" : 7597 }, { "id" : "minecraft:stone_pressure_plate", - "blockRuntimeId" : 7203 + "blockRuntimeId" : 7204 }, { "id" : "minecraft:light_weighted_pressure_plate", - "blockRuntimeId" : 5499 + "blockRuntimeId" : 5501 }, { "id" : "minecraft:heavy_weighted_pressure_plate", - "blockRuntimeId" : 5095 + "blockRuntimeId" : 5097 }, { "id" : "minecraft:polished_blackstone_pressure_plate", - "blockRuntimeId" : 6012 + "blockRuntimeId" : 6018 }, { "id" : "minecraft:observer", - "blockRuntimeId" : 5722 + "blockRuntimeId" : 5726 }, { "id" : "minecraft:daylight_detector", - "blockRuntimeId" : 4066 + "blockRuntimeId" : 4067 }, { "id" : "minecraft:repeater" @@ -4932,30 +4931,30 @@ }, { "id" : "minecraft:dropper", - "blockRuntimeId" : 4588 + "blockRuntimeId" : 4589 }, { "id" : "minecraft:dispenser", - "blockRuntimeId" : 4489 + "blockRuntimeId" : 4490 }, { "id" : "minecraft:piston", - "blockRuntimeId" : 5783 + "blockRuntimeId" : 5789 }, { "id" : "minecraft:sticky_piston", - "blockRuntimeId" : 7165 + "blockRuntimeId" : 7166 }, { "id" : "minecraft:tnt", - "blockRuntimeId" : 7349 + "blockRuntimeId" : 7350 }, { "id" : "minecraft:name_tag" }, { "id" : "minecraft:loom", - "blockRuntimeId" : 5581 + "blockRuntimeId" : 5583 }, { "id" : "minecraft:banner" @@ -5046,6 +5045,9 @@ { "id" : "minecraft:piglin_banner_pattern" }, + { + "id" : "minecraft:globe_banner_pattern" + }, { "id" : "minecraft:firework_rocket", "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" @@ -5198,7 +5200,7 @@ }, { "id" : "minecraft:target", - "blockRuntimeId" : 7347 + "blockRuntimeId" : 7348 }, { "id" : "minecraft:lodestone_compass" diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_17_30.json b/core/src/main/resources/bedrock/runtime_item_states.1_18_10.json similarity index 98% rename from core/src/main/resources/bedrock/runtime_item_states.1_17_30.json rename to core/src/main/resources/bedrock/runtime_item_states.1_18_10.json index 79690e3da..5bebcaf99 100644 --- a/core/src/main/resources/bedrock/runtime_item_states.1_17_30.json +++ b/core/src/main/resources/bedrock/runtime_item_states.1_18_10.json @@ -51,6 +51,10 @@ "name" : "minecraft:air", "id" : -158 }, + { + "name" : "minecraft:allay_spawn_egg", + "id" : 631 + }, { "name" : "minecraft:allow", "id" : 210 @@ -65,7 +69,7 @@ }, { "name" : "minecraft:amethyst_shard", - "id" : 623 + "id" : 625 }, { "name" : "minecraft:ancient_debris", @@ -117,7 +121,7 @@ }, { "name" : "minecraft:balloon", - "id" : 597 + "id" : 598 }, { "name" : "minecraft:bamboo", @@ -133,7 +137,7 @@ }, { "name" : "minecraft:banner_pattern", - "id" : 627 + "id" : 635 }, { "name" : "minecraft:barrel", @@ -293,7 +297,7 @@ }, { "name" : "minecraft:bleach", - "id" : 595 + "id" : 596 }, { "name" : "minecraft:blue_candle", @@ -317,7 +321,7 @@ }, { "name" : "minecraft:boat", - "id" : 625 + "id" : 633 }, { "name" : "minecraft:bone", @@ -429,11 +433,11 @@ }, { "name" : "minecraft:camera", - "id" : 592 + "id" : 593 }, { "name" : "minecraft:campfire", - "id" : 588 + "id" : 589 }, { "name" : "minecraft:candle", @@ -493,7 +497,7 @@ }, { "name" : "minecraft:chain", - "id" : 617 + "id" : 619 }, { "name" : "minecraft:chain_command_block", @@ -575,6 +579,10 @@ "name" : "minecraft:clay_ball", "id" : 384 }, + { + "name" : "minecraft:client_request_placeholder_block", + "id" : -465 + }, { "name" : "minecraft:clock", "id" : 393 @@ -669,7 +677,7 @@ }, { "name" : "minecraft:compound", - "id" : 593 + "id" : 594 }, { "name" : "minecraft:concrete", @@ -793,7 +801,7 @@ }, { "name" : "minecraft:crimson_door", - "id" : 614 + "id" : 616 }, { "name" : "minecraft:crimson_double_slab", @@ -833,7 +841,7 @@ }, { "name" : "minecraft:crimson_sign", - "id" : 612 + "id" : 614 }, { "name" : "minecraft:crimson_slab", @@ -1169,7 +1177,7 @@ }, { "name" : "minecraft:dye", - "id" : 626 + "id" : 634 }, { "name" : "minecraft:egg", @@ -1697,7 +1705,7 @@ }, { "name" : "minecraft:end_crystal", - "id" : 629 + "id" : 637 }, { "name" : "minecraft:end_gateway", @@ -1803,6 +1811,10 @@ "name" : "minecraft:fire_charge", "id" : 509 }, + { + "name" : "minecraft:firefly_spawn_egg", + "id" : 632 + }, { "name" : "minecraft:firework_rocket", "id" : 519 @@ -1855,6 +1867,14 @@ "name" : "minecraft:frame", "id" : 513 }, + { + "name" : "minecraft:frog_egg", + "id" : -468 + }, + { + "name" : "minecraft:frog_spawn_egg", + "id" : 628 + }, { "name" : "minecraft:frosted_ice", "id" : 207 @@ -1891,13 +1911,17 @@ "name" : "minecraft:glistering_melon_slice", "id" : 434 }, + { + "name" : "minecraft:globe_banner_pattern", + "id" : 588 + }, { "name" : "minecraft:glow_berries", - "id" : 630 + "id" : 638 }, { "name" : "minecraft:glow_frame", - "id" : 621 + "id" : 623 }, { "name" : "minecraft:glow_ink_sac", @@ -1913,7 +1937,7 @@ }, { "name" : "minecraft:glow_stick", - "id" : 166 + "id" : 601 }, { "name" : "minecraft:glowingobsidian", @@ -1929,7 +1953,7 @@ }, { "name" : "minecraft:goat_horn", - "id" : 622 + "id" : 624 }, { "name" : "minecraft:goat_spawn_egg", @@ -2109,11 +2133,11 @@ }, { "name" : "minecraft:honey_bottle", - "id" : 591 + "id" : 592 }, { "name" : "minecraft:honeycomb", - "id" : 590 + "id" : 591 }, { "name" : "minecraft:honeycomb_block", @@ -2141,7 +2165,7 @@ }, { "name" : "minecraft:ice_bomb", - "id" : 594 + "id" : 595 }, { "name" : "minecraft:infested_deepslate", @@ -2569,7 +2593,7 @@ }, { "name" : "minecraft:lodestone_compass", - "id" : 600 + "id" : 602 }, { "name" : "minecraft:log", @@ -2613,7 +2637,7 @@ }, { "name" : "minecraft:medicine", - "id" : 598 + "id" : 599 }, { "name" : "minecraft:medium_amethyst_bud", @@ -2723,9 +2747,13 @@ "name" : "minecraft:music_disc_mellohi", "id" : 540 }, + { + "name" : "minecraft:music_disc_otherside", + "id" : 627 + }, { "name" : "minecraft:music_disc_pigstep", - "id" : 618 + "id" : 620 }, { "name" : "minecraft:music_disc_stal", @@ -2751,6 +2779,14 @@ "name" : "minecraft:mycelium", "id" : 110 }, + { + "name" : "minecraft:mysterious_frame", + "id" : -466 + }, + { + "name" : "minecraft:mysterious_frame_slot", + "id" : -467 + }, { "name" : "minecraft:name_tag", "id" : 548 @@ -2777,7 +2813,7 @@ }, { "name" : "minecraft:nether_sprouts", - "id" : 619 + "id" : 621 }, { "name" : "minecraft:nether_star", @@ -2797,7 +2833,7 @@ }, { "name" : "minecraft:netherite_axe", - "id" : 605 + "id" : 607 }, { "name" : "minecraft:netherite_block", @@ -2805,43 +2841,43 @@ }, { "name" : "minecraft:netherite_boots", - "id" : 610 + "id" : 612 }, { "name" : "minecraft:netherite_chestplate", - "id" : 608 + "id" : 610 }, { "name" : "minecraft:netherite_helmet", - "id" : 607 - }, - { - "name" : "minecraft:netherite_hoe", - "id" : 606 - }, - { - "name" : "minecraft:netherite_ingot", - "id" : 601 - }, - { - "name" : "minecraft:netherite_leggings", "id" : 609 }, { - "name" : "minecraft:netherite_pickaxe", - "id" : 604 + "name" : "minecraft:netherite_hoe", + "id" : 608 }, { - "name" : "minecraft:netherite_scrap", - "id" : 611 - }, - { - "name" : "minecraft:netherite_shovel", + "name" : "minecraft:netherite_ingot", "id" : 603 }, + { + "name" : "minecraft:netherite_leggings", + "id" : 611 + }, + { + "name" : "minecraft:netherite_pickaxe", + "id" : 606 + }, + { + "name" : "minecraft:netherite_scrap", + "id" : 613 + }, + { + "name" : "minecraft:netherite_shovel", + "id" : 605 + }, { "name" : "minecraft:netherite_sword", - "id" : 602 + "id" : 604 }, { "name" : "minecraft:netherrack", @@ -2887,6 +2923,10 @@ "name" : "minecraft:ocelot_spawn_egg", "id" : 451 }, + { + "name" : "minecraft:ochre_froglight", + "id" : -471 + }, { "name" : "minecraft:orange_candle", "id" : -414 @@ -2943,6 +2983,10 @@ "name" : "minecraft:parrot_spawn_egg", "id" : 478 }, + { + "name" : "minecraft:pearlescent_froglight", + "id" : -469 + }, { "name" : "minecraft:phantom_membrane", "id" : 574 @@ -3257,7 +3301,7 @@ }, { "name" : "minecraft:rapid_fertilizer", - "id" : 596 + "id" : 597 }, { "name" : "minecraft:ravager_spawn_egg", @@ -3577,7 +3621,7 @@ }, { "name" : "minecraft:soul_campfire", - "id" : 620 + "id" : 622 }, { "name" : "minecraft:soul_fire", @@ -3601,11 +3645,11 @@ }, { "name" : "minecraft:sparkler", - "id" : 599 + "id" : 600 }, { "name" : "minecraft:spawn_egg", - "id" : 628 + "id" : 636 }, { "name" : "minecraft:spider_eye", @@ -3669,7 +3713,7 @@ }, { "name" : "minecraft:spyglass", - "id" : 624 + "id" : 626 }, { "name" : "minecraft:squid_spawn_egg", @@ -3829,7 +3873,7 @@ }, { "name" : "minecraft:suspicious_stew", - "id" : 589 + "id" : 590 }, { "name" : "minecraft:sweet_berries", @@ -3839,6 +3883,14 @@ "name" : "minecraft:sweet_berry_bush", "id" : -207 }, + { + "name" : "minecraft:tadpole_bucket", + "id" : 630 + }, + { + "name" : "minecraft:tadpole_spawn_egg", + "id" : 629 + }, { "name" : "minecraft:tallgrass", "id" : 31 @@ -3943,6 +3995,10 @@ "name" : "minecraft:unpowered_repeater", "id" : 93 }, + { + "name" : "minecraft:verdant_froglight", + "id" : -470 + }, { "name" : "minecraft:vex_spawn_egg", "id" : 476 @@ -3977,7 +4033,7 @@ }, { "name" : "minecraft:warped_door", - "id" : 615 + "id" : 617 }, { "name" : "minecraft:warped_double_slab", @@ -3997,7 +4053,7 @@ }, { "name" : "minecraft:warped_fungus_on_a_stick", - "id" : 616 + "id" : 618 }, { "name" : "minecraft:warped_hyphae", @@ -4021,7 +4077,7 @@ }, { "name" : "minecraft:warped_sign", - "id" : 613 + "id" : 615 }, { "name" : "minecraft:warped_slab", diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 8c5737a39..00e2521f3 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -125,6 +125,13 @@ show-cooldown: title # Controls if coordinates are shown to players. show-coordinates: true +# Whether Bedrock players are blocked from performing their scaffolding-style bridging. +disable-bedrock-scaffolding: false + +# Whether Bedrock players can right-click outside of their inventory to replace armor in their inventory, even if the +# armor slot is already occupied (which Java Edition doesn't allow) +always-quick-change-armor: false + # If set, when a Bedrock player performs any emote, it will swap the offhand and mainhand items, just like the Java Edition keybind # There are three options this can be set to: # disabled - the default/fallback, which doesn't apply this workaround diff --git a/pom.xml b/pom.xml index db512e477..191a40704 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.geysermc geyser-parent - 2.0.0-SNAPSHOT + 2.0.1-SNAPSHOT pom Geyser Allows for players from Minecraft Bedrock Edition to join Minecraft Java Edition servers.