diff --git a/README.md b/README.md index a21a1b6c9..4a522f21f 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,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 now joined us here! -### Currently supporting Minecraft Bedrock v1.16.100 - v1.16.210 and Minecraft Java v1.16.4 - v1.16.5. +### Currently supporting Minecraft Bedrock v1.16.100 - v1.16.220 and Minecraft Java v1.16.4 - v1.16.5. ## Setting Up Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set up Geyser. diff --git a/connector/pom.xml b/connector/pom.xml index 4e244dd00..07fb8be75 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -42,8 +42,8 @@ com.github.CloudburstMC.Protocol - bedrock-v428 - 42da92f + bedrock-v431 + f8ecf54 compile diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 3cb95391d..b6c9a97fa 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -208,7 +208,7 @@ public class GeyserConnector { } } - CooldownUtils.setShowCooldown(config.isShowCooldown()); + CooldownUtils.setShowCooldown(config.getShowCooldown()); DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether SkullBlockEntityTranslator.ALLOW_CUSTOM_SKULLS = config.isAllowCustomSkulls(); diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java index 97d09f7e0..05f32ae2b 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java @@ -27,6 +27,7 @@ package org.geysermc.connector.command.defaults; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; @@ -56,6 +57,12 @@ public class DumpCommand extends GeyserCommand { @Override public void execute(GeyserSession session, CommandSender sender, String[] args) { + // Only allow the console to create dumps on Geyser Standalone + if (!sender.isConsole() && connector.getPlatformType() == PlatformType.STANDALONE) { + sender.sendMessage(LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.getLocale())); + return; + } + boolean showSensitive = false; boolean offlineDump = false; if (args.length >= 1) { diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java index b00e44b72..8ceeb9990 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java @@ -30,6 +30,7 @@ import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; import java.util.Collections; @@ -47,6 +48,7 @@ public class StopCommand extends GeyserCommand { @Override public void execute(GeyserSession session, CommandSender sender, String[] args) { if (!sender.isConsole() && connector.getPlatformType() == PlatformType.STANDALONE) { + sender.sendMessage(LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.getLocale())); return; } diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java index 226a770a6..21a891c0e 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java @@ -27,6 +27,7 @@ package org.geysermc.connector.command.defaults; import com.github.steveice10.mc.protocol.MinecraftConstants; import com.nukkitx.protocol.bedrock.BedrockPacketCodec; +import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; @@ -45,8 +46,12 @@ import java.util.Properties; public class VersionCommand extends GeyserCommand { + private final GeyserConnector connector; + public VersionCommand(GeyserConnector connector, String name, String description, String permission) { super(name, description, permission); + + this.connector = connector; } @Override @@ -61,9 +66,9 @@ public class VersionCommand extends GeyserCommand { sender.sendMessage(LanguageUtils.getPlayerLocaleString("geyser.commands.version.version", sender.getLocale(), GeyserConnector.NAME, GeyserConnector.VERSION, GeyserConnector.MINECRAFT_VERSION, bedrockVersions)); - // Disable update checking in dev mode + // Disable update checking in dev mode and for players in Geyser Standalone //noinspection ConstantConditions - changes in production - if (!GeyserConnector.VERSION.equals("DEV")) { + if (!GeyserConnector.VERSION.equals("DEV") && !(!sender.isConsole() && connector.getPlatformType() == PlatformType.STANDALONE)) { sender.sendMessage(LanguageUtils.getPlayerLocaleString("geyser.commands.version.checking", sender.getLocale())); try { Properties gitProp = new Properties(); diff --git a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java index 6052bd283..652ec1339 100644 --- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java @@ -73,7 +73,7 @@ public interface GeyserConfiguration { boolean isAllowThirdPartyEars(); - boolean isShowCooldown(); + String getShowCooldown(); boolean isShowCoordinates(); @@ -81,6 +81,8 @@ public interface GeyserConfiguration { Path getFloodgateKeyPath(); + boolean isAddNonBedrockItems(); + boolean isAboveBedrockNetherBuilding(); boolean isCacheChunks(); diff --git a/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java b/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java index 70aa3ff5d..e9adfe12b 100644 --- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java @@ -95,7 +95,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration private boolean allowThirdPartyCapes = true; @JsonProperty("show-cooldown") - private boolean showCooldown = true; + private String showCooldown = "title"; @JsonProperty("show-coordinates") private boolean showCoordinates = true; @@ -115,6 +115,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration @JsonProperty("allow-custom-skulls") private boolean allowCustomSkulls = true; + @JsonProperty("add-non-bedrock-items") + private boolean addNonBedrockItems = true; + @JsonProperty("above-bedrock-nether-building") private boolean aboveBedrockNetherBuilding = false; diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java index a898ea389..e10ad0afd 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -107,7 +107,7 @@ public class ItemFrameEntity extends Entity { if (itemData.getTag() != null) { builder.put("tag", itemData.getTag().toBuilder().build()); } - builder.putShort("Damage", itemData.getDamage()); + builder.putShort("Damage", (short) itemData.getDamage()); builder.putString("Name", itemEntry.getBedrockIdentifier()); NbtMapBuilder tag = getDefaultTag().toBuilder(); tag.put("Item", builder.build()); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java index 5fdde5272..d575f9521 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java @@ -56,9 +56,12 @@ public class LlamaEntity extends ChestedHorseEntity { // -1 means no armor if ((int) entityMetadata.getValue() != -1) { // The damage value is the dye color that Java sends us - // Always going to be a carpet so we can hardcode 171 in BlockTranslator - // The int then short conversion is required or we get a ClassCastException - equipmentPacket.setChestplate(ItemData.of(BlockTranslator.CARPET, (short) ((int) entityMetadata.getValue()), 1)); + // The item is always going to be a carpet + equipmentPacket.setChestplate(ItemData.builder() + .id(BlockTranslator.CARPET) + .damage((int) entityMetadata.getValue()) + .count(1) + .build()); } else { equipmentPacket.setChestplate(ItemData.AIR); } diff --git a/connector/src/main/java/org/geysermc/connector/inventory/GeyserItemStack.java b/connector/src/main/java/org/geysermc/connector/inventory/GeyserItemStack.java index b4e91c1d6..1cfd425d9 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/GeyserItemStack.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/GeyserItemStack.java @@ -101,6 +101,7 @@ public class GeyserItemStack { public ItemData getItemData(GeyserSession session) { ItemData itemData = ItemTranslator.translateToBedrock(session, getItemStack()); itemData.setNetId(getNetId()); + itemData.setUsingNetId(true); // Seems silly - this should probably be on the protocol level return itemData; } diff --git a/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java b/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java index 3b5af7f99..2d29ddd88 100644 --- a/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java +++ b/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java @@ -29,6 +29,7 @@ import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.v419.Bedrock_v419; import com.nukkitx.protocol.bedrock.v422.Bedrock_v422; import com.nukkitx.protocol.bedrock.v428.Bedrock_v428; +import com.nukkitx.protocol.bedrock.v431.Bedrock_v431; import java.util.ArrayList; import java.util.List; @@ -55,6 +56,7 @@ public class BedrockProtocol { .minecraftVersion("1.16.200/1.16.201") .build()); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v431.V431_CODEC); } /** diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index b073e3baf..1ae559a9b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -27,6 +27,7 @@ package org.geysermc.connector.network; import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.BedrockPacketCodec; +import com.nukkitx.protocol.bedrock.data.ExperimentData; import com.nukkitx.protocol.bedrock.data.ResourcePackType; import com.nukkitx.protocol.bedrock.packet.*; import com.nukkitx.protocol.bedrock.v428.Bedrock_v428; @@ -36,6 +37,7 @@ import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.cache.AdvancementsCache; import org.geysermc.connector.network.translators.PacketTranslatorRegistry; +import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.world.block.BlockTranslator1_16_100; import org.geysermc.connector.network.translators.world.block.BlockTranslator1_16_210; import org.geysermc.connector.utils.LanguageUtils; @@ -137,6 +139,11 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { stackPacket.getResourcePacks().add(new ResourcePackStackPacket.Entry(header.getUuid().toString(), header.getVersionString(), "")); } + if (ItemRegistry.FURNACE_MINECART_DATA != null) { + // Allow custom items to work + stackPacket.getExperiments().add(new ExperimentData("data_driven_items", true)); + } + session.sendUpstreamPacket(stackPacket); break; diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 767a61acd..029849409 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -455,6 +455,12 @@ public class GeyserSession implements CommandSender { // Set the hardcoded shield ID to the ID we just defined in StartGamePacket upstream.getSession().getHardcodedBlockingId().set(ItemRegistry.SHIELD.getBedrockId()); + if (ItemRegistry.FURNACE_MINECART_DATA != null) { + ItemComponentPacket componentPacket = new ItemComponentPacket(); + componentPacket.getItems().add(ItemRegistry.FURNACE_MINECART_DATA); + upstream.sendPacket(componentPacket); + } + ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 0, false); BiomeDefinitionListPacket biomeDefinitionListPacket = new BiomeDefinitionListPacket(); @@ -475,11 +481,10 @@ public class GeyserSession implements CommandSender { UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); attributesPacket.setRuntimeEntityId(getPlayerEntity().getGeyserId()); - List attributes = new ArrayList<>(); // Default move speed // Bedrock clients move very fast by default until they get an attribute packet correcting the speed - attributes.add(new AttributeData("minecraft:movement", 0.0f, 1024f, 0.1f, 0.1f)); - attributesPacket.setAttributes(attributes); + attributesPacket.setAttributes(Collections.singletonList( + new AttributeData("minecraft:movement", 0.0f, 1024f, 0.1f, 0.1f))); upstream.sendPacket(attributesPacket); GameRulesChangedPacket gamerulePacket = new GameRulesChangedPacket(); @@ -1145,7 +1150,7 @@ public class GeyserSession implements CommandSender { noClip = gameMode == GameMode.SPECTATOR; worldImmutable = gameMode == GameMode.ADVENTURE || gameMode == GameMode.SPECTATOR; - Set flags = new HashSet<>(); + Set flags = adventureSettingsPacket.getSettings(); if (canFly) { flags.add(AdventureSetting.MAY_FLY); } @@ -1164,7 +1169,6 @@ public class GeyserSession implements CommandSender { flags.add(AdventureSetting.AUTO_JUMP); - adventureSettingsPacket.getSettings().addAll(flags); sendUpstreamPacket(adventureSettingsPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java index 278d708f9..3d92e823c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java @@ -28,23 +28,32 @@ package org.geysermc.connector.network.translators.item; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.ToString; +import org.geysermc.connector.network.translators.world.block.BlockTranslator1_16_210; @Getter @AllArgsConstructor @ToString public class ItemEntry { - public static ItemEntry AIR = new ItemEntry("minecraft:air", "minecraft:air", 0, 0, 0, false, 64); + public static ItemEntry AIR = new ItemEntry("minecraft:air", "minecraft:air", 0, 0, 0, + BlockTranslator1_16_210.INSTANCE.getBedrockAirId(), 64); private final String javaIdentifier; private final String bedrockIdentifier; private final int javaId; private final int bedrockId; private final int bedrockData; - - private final boolean block; + /** + * The Bedrock block runtime ID to render this item with. The specific state *does* matter in how this item is rendered. + * Required since 1.16.220. + */ + private final int bedrockBlockId; private final int stackSize; + public boolean isBlock() { + return bedrockBlockId != -1; + } + @Override public boolean equals(Object obj) { return obj == this || (obj instanceof ItemEntry && ((ItemEntry) obj).getBedrockId() == this.getBedrockId() && ((ItemEntry) obj).getJavaIdentifier().equals(this.getJavaIdentifier())); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java index c865a162a..4690fb700 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java @@ -28,15 +28,21 @@ package org.geysermc.connector.network.translators.item; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.google.common.collect.ImmutableSet; import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; +import com.nukkitx.nbt.NbtType; import com.nukkitx.nbt.NbtUtils; +import com.nukkitx.protocol.bedrock.data.inventory.ComponentItemData; import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.StartGamePacket; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.network.translators.world.block.BlockTranslator1_16_210; import org.geysermc.connector.utils.FileUtils; import org.geysermc.connector.utils.LanguageUtils; @@ -55,8 +61,7 @@ public class ItemRegistry { /** * A list of all identifiers that only exist on Java. Used to prevent creative items from becoming these unintentionally. */ - private static final List JAVA_ONLY_ITEMS = Arrays.asList("minecraft:spectral_arrow", "minecraft:debug_stick", - "minecraft:knowledge_book", "minecraft:tipped_arrow", "minecraft:furnace_minecart"); + private static final Set JAVA_ONLY_ITEMS; public static final ItemData[] CREATIVE_ITEMS; @@ -107,6 +112,11 @@ public class ItemRegistry { public static int BARRIER_INDEX = 0; + /** + * Stores the properties and data of the "custom" furnace minecart item. + */ + public static final ComponentItemData FURNACE_MINECART_DATA; + public static void init() { // no-op } @@ -150,9 +160,16 @@ public class ItemRegistry { } int itemIndex = 0; + int javaFurnaceMinecartId = 0; + boolean usingFurnaceMinecart = GeyserConnector.getInstance().getConfig().isAddNonBedrockItems(); Iterator> iterator = items.fields(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); + if (usingFurnaceMinecart && entry.getKey().equals("minecraft:furnace_minecart")) { + javaFurnaceMinecartId = itemIndex; + itemIndex++; + continue; + } int bedrockId = entry.getValue().get("bedrock_id").intValue(); String bedrockIdentifier = bedrockIdToIdentifier.get(bedrockId); if (bedrockIdentifier == null) { @@ -160,54 +177,64 @@ public class ItemRegistry { } JsonNode stackSizeNode = entry.getValue().get("stack_size"); int stackSize = stackSizeNode == null ? 64 : stackSizeNode.intValue(); + + int bedrockBlockId = -1; + JsonNode blockRuntimeIdNode = entry.getValue().get("blockRuntimeId"); + if (blockRuntimeIdNode != null) { + bedrockBlockId = BlockTranslator1_16_210.INSTANCE.getBedrockBlockId(blockRuntimeIdNode.intValue()); + } + + ItemEntry itemEntry; if (entry.getValue().has("tool_type")) { if (entry.getValue().has("tool_tier")) { - ITEM_ENTRIES.put(itemIndex, new ToolItemEntry( + itemEntry = new ToolItemEntry( entry.getKey(), bedrockIdentifier, itemIndex, bedrockId, entry.getValue().get("bedrock_data").intValue(), entry.getValue().get("tool_type").textValue(), entry.getValue().get("tool_tier").textValue(), - entry.getValue().get("is_block").booleanValue(), - stackSize)); + bedrockBlockId, + stackSize); } else { - ITEM_ENTRIES.put(itemIndex, new ToolItemEntry( + itemEntry = new ToolItemEntry( entry.getKey(), bedrockIdentifier, itemIndex, bedrockId, entry.getValue().get("bedrock_data").intValue(), entry.getValue().get("tool_type").textValue(), - "", entry.getValue().get("is_block").booleanValue(), - stackSize)); + "", bedrockBlockId, + stackSize); } } else { - ITEM_ENTRIES.put(itemIndex, new ItemEntry( + itemEntry = new ItemEntry( entry.getKey(), bedrockIdentifier, itemIndex, bedrockId, entry.getValue().get("bedrock_data").intValue(), - entry.getValue().get("is_block").booleanValue(), - stackSize)); + bedrockBlockId, + stackSize); } + ITEM_ENTRIES.put(itemIndex, itemEntry); + switch (entry.getKey()) { case "minecraft:barrier": BARRIER_INDEX = itemIndex; break; case "minecraft:bamboo": - BAMBOO = ITEM_ENTRIES.get(itemIndex); + BAMBOO = itemEntry; break; case "minecraft:egg": - EGG = ITEM_ENTRIES.get(itemIndex); + EGG = itemEntry; break; case "minecraft:gold_ingot": - GOLD = ITEM_ENTRIES.get(itemIndex); + GOLD = itemEntry; break; case "minecraft:shield": - SHIELD = ITEM_ENTRIES.get(itemIndex); + SHIELD = itemEntry; break; case "minecraft:milk_bucket": - MILK_BUCKET = ITEM_ENTRIES.get(itemIndex); + MILK_BUCKET = itemEntry; break; case "minecraft:wheat": - WHEAT = ITEM_ENTRIES.get(itemIndex); + WHEAT = itemEntry; break; case "minecraft:writable_book": - WRITABLE_BOOK = ITEM_ENTRIES.get(itemIndex); + WRITABLE_BOOK = itemEntry; break; default: break; @@ -224,13 +251,16 @@ public class ItemRegistry { itemIndex++; } + itemNames.add("minecraft:furnace_minecart"); + itemNames.add("minecraft:spectral_arrow"); + if (lodestoneCompassId == 0) { throw new RuntimeException("Lodestone compass not found in item palette!"); } // Add the loadstone compass since it doesn't exist on java but we need it for item conversion ITEM_ENTRIES.put(itemIndex, new ItemEntry("minecraft:lodestone_compass", "minecraft:lodestone_compass", itemIndex, - lodestoneCompassId, 0, false, 1)); + lodestoneCompassId, 0, -1, 1)); /* Load creative items */ stream = FileUtils.getResource("bedrock/creative_items.json"); @@ -242,12 +272,70 @@ public class ItemRegistry { throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.creative"), e); } + Set javaOnlyItems = new ObjectOpenHashSet<>(); + Collections.addAll(javaOnlyItems, "minecraft:spectral_arrow", "minecraft:debug_stick", + "minecraft:knowledge_book", "minecraft:tipped_arrow"); + if (!usingFurnaceMinecart) { + javaOnlyItems.add("minecraft:furnace_minecart"); + } + JAVA_ONLY_ITEMS = ImmutableSet.copyOf(javaOnlyItems); + int netId = 1; List creativeItems = new ArrayList<>(); for (JsonNode itemNode : creativeItemEntries) { - ItemData item = getBedrockItemFromJson(itemNode); - creativeItems.add(ItemData.fromNet(netId++, item.getId(), item.getDamage(), item.getCount(), item.getTag())); + ItemData.Builder item = getBedrockItemFromJson(itemNode); + int bedrockRuntimeId = 0; + ItemEntry itemEntry = getItem(item.build()); // please + if (itemEntry.isBlock()) { + bedrockRuntimeId = itemEntry.getBedrockBlockId(); + } + creativeItems.add(item.netId(netId++).blockRuntimeId(bedrockRuntimeId).build()); } + + if (usingFurnaceMinecart) { + // Add the furnace minecart as an item + int furnaceMinecartId = ITEMS.size() + 1; + + ITEMS.add(new StartGamePacket.ItemEntry("geysermc:furnace_minecart", (short) furnaceMinecartId, true)); + ITEM_ENTRIES.put(javaFurnaceMinecartId, new ItemEntry("minecraft:furnace_minecart", "geysermc:furnace_minecart", javaFurnaceMinecartId, + furnaceMinecartId, 0, -1, 1)); + creativeItems.add(ItemData.builder() + .netId(netId) + .id(furnaceMinecartId) + .count(1).build()); + + NbtMapBuilder builder = NbtMap.builder(); + builder.putString("name", "geysermc:furnace_minecart") + .putInt("id", furnaceMinecartId); + + NbtMapBuilder componentBuilder = NbtMap.builder(); + // Conveniently, as of 1.16.200, the furnace minecart has a texture AND translation string already. + componentBuilder.putCompound("minecraft:icon", NbtMap.builder().putString("texture", "minecart_furnace").build()); + componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", "item.minecartFurnace.name").build()); + + // Indicate that the arm animation should play on rails + List useOnTag = Collections.singletonList(NbtMap.builder().putString("tags", "q.any_tag('rail')").build()); + componentBuilder.putCompound("minecraft:entity_placer", NbtMap.builder() + .putList("dispense_on", NbtType.COMPOUND, useOnTag) + .putString("entity", "minecraft:minecart") + .putList("use_on", NbtType.COMPOUND, useOnTag) + .build()); + + NbtMapBuilder itemProperties = NbtMap.builder(); + // We always want to allow offhand usage when we can - matches Java Edition + itemProperties.putBoolean("allow_off_hand", true); + itemProperties.putBoolean("hand_equipped", false); + itemProperties.putInt("max_stack_size", 1); + itemProperties.putString("creative_group", "itemGroup.name.minecart"); + itemProperties.putInt("creative_category", 4); // 4 - "Items" + + componentBuilder.putCompound("item_properties", itemProperties.build()); + builder.putCompound("components", componentBuilder.build()); + FURNACE_MINECART_DATA = new ComponentItemData("geysermc:furnace_minecart", builder.build()); + } else { + FURNACE_MINECART_DATA = null; + } + CREATIVE_ITEMS = creativeItems.toArray(new ItemData[0]); ITEM_NAMES = itemNames.toArray(new String[0]); @@ -307,11 +395,11 @@ public class ItemRegistry { } /** - * Gets a Bedrock {@link ItemData} from a {@link JsonNode} + * Gets a Bedrock {@link com.nukkitx.protocol.bedrock.data.inventory.ItemData.Builder} from a {@link JsonNode} * @param itemNode the JSON node that contains ProxyPass-compatible Bedrock item data * @return */ - public static ItemData getBedrockItemFromJson(JsonNode itemNode) { + public static ItemData.Builder getBedrockItemFromJson(JsonNode itemNode) { int count = 1; short damage = 0; NbtMap tag = null; @@ -330,6 +418,10 @@ public class ItemRegistry { e.printStackTrace(); } } - return ItemData.of(itemNode.get("id").asInt(), damage, count, tag); + return ItemData.builder() + .id(itemNode.get("id").asInt()) + .damage(damage) + .count(count) + .tag(tag); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index f1ae98faf..2cd1aad94 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -149,12 +149,15 @@ public abstract class ItemTranslator { translateDisplayProperties(session, nbt); - ItemData itemData; + ItemData.Builder builder; ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(bedrockItem.getJavaId()); if (itemStackTranslator != null) { - itemData = itemStackTranslator.translateToBedrock(itemStack, bedrockItem); + builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem); } else { - itemData = DEFAULT_TRANSLATOR.translateToBedrock(itemStack, bedrockItem); + builder = DEFAULT_TRANSLATOR.translateToBedrock(itemStack, bedrockItem); + } + if (bedrockItem.isBlock()) { + builder.blockRuntimeId(bedrockItem.getBedrockBlockId()); } if (nbt != null) { @@ -165,10 +168,11 @@ public abstract class ItemTranslator { String[] canPlace = new String[0]; canBreak = getCanModify(session, canDestroy, canBreak); canPlace = getCanModify(session, canPlaceOn, canPlace); - itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), itemData.getTag(), canPlace, canBreak); + builder.canBreak(canBreak); + builder.canPlace(canPlace); } - return itemData; + return builder.build(); } /** @@ -202,14 +206,19 @@ public abstract class ItemTranslator { } }; - public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { if (itemStack == null) { - return ItemData.AIR; + // Return, essentially, air + return ItemData.builder(); } - if (itemStack.getNbt() == null) { - return ItemData.of(itemEntry.getBedrockId(), (short) itemEntry.getBedrockData(), itemStack.getAmount()); + ItemData.Builder builder = ItemData.builder() + .id(itemEntry.getBedrockId()) + .damage(itemEntry.getBedrockData()) + .count(itemStack.getAmount()); + if (itemStack.getNbt() != null) { + builder.tag(this.translateNbtToBedrock(itemStack.getNbt())); } - return ItemData.of(itemEntry.getBedrockId(), (short) itemEntry.getBedrockData(), itemStack.getAmount(), this.translateNbtToBedrock(itemStack.getNbt())); + return builder; } public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java index d81e059e9..4e710c550 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java @@ -91,7 +91,7 @@ public enum Potion { return null; } - public static Potion getByBedrockId(short bedrockId) { + public static Potion getByBedrockId(int bedrockId) { for (Potion potion : Potion.values()) { if (potion.bedrockId == bedrockId) { return potion; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java index 110014bf5..b570df8a1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java @@ -272,7 +272,11 @@ public class RecipeRegistry { e.printStackTrace(); } } - return ItemData.of(itemEntry.getBedrockId(), damage, count, tag); + return ItemData.builder() + .id(itemEntry.getBedrockId()) + .damage(damage) + .count(count) + .tag(tag).build(); } public static void init() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/TippedArrowPotion.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/TippedArrowPotion.java index 0125dae05..5aac09790 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/TippedArrowPotion.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/TippedArrowPotion.java @@ -100,7 +100,7 @@ public enum TippedArrowPotion { return null; } - public static TippedArrowPotion getByBedrockId(short bedrockId) { + public static TippedArrowPotion getByBedrockId(int bedrockId) { for (TippedArrowPotion potion : TippedArrowPotion.values()) { if (potion.bedrockId == bedrockId) { return potion; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java index ba1753a35..2e93811c0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java @@ -32,8 +32,9 @@ public class ToolItemEntry extends ItemEntry { private final String toolType; private final String toolTier; - public ToolItemEntry(String javaIdentifier, String bedrockIdentifier, int javaId, int bedrockId, int bedrockData, String toolType, String toolTier, boolean isBlock, int stackSize) { - super(javaIdentifier, bedrockIdentifier, javaId, bedrockId, bedrockData, isBlock, stackSize); + public ToolItemEntry(String javaIdentifier, String bedrockIdentifier, int javaId, int bedrockId, int bedrockData, + String toolType, String toolTier, int bedrockBlockId, int stackSize) { + super(javaIdentifier, bedrockIdentifier, javaId, bedrockId, bedrockData, bedrockBlockId, stackSize); this.toolType = toolType; this.toolTier = toolTier; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java index a96c47f6a..b127e1928 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java @@ -153,30 +153,30 @@ public class BannerTranslator extends ItemTranslator { } @Override - public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { if (itemStack.getNbt() == null) { return super.translateToBedrock(itemStack, itemEntry); } - ItemData itemData = super.translateToBedrock(itemStack, itemEntry); + ItemData.Builder builder = super.translateToBedrock(itemStack, itemEntry); CompoundTag blockEntityTag = itemStack.getNbt().get("BlockEntityTag"); if (blockEntityTag != null && blockEntityTag.contains("Patterns")) { ListTag patterns = blockEntityTag.get("Patterns"); - NbtMapBuilder builder = itemData.getTag().toBuilder(); + 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 - builder.remove("Patterns"); - builder.putInt("Type", 1); + nbtBuilder.remove("Patterns"); + nbtBuilder.putInt("Type", 1); } else { - builder.put("Patterns", convertBannerPattern(patterns)); + nbtBuilder.put("Patterns", convertBannerPattern(patterns)); } - itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build()); + builder.tag(nbtBuilder.build()); } - return itemData; + return builder; } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java index 9e3bf7d46..08c7426fe 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java @@ -47,7 +47,7 @@ public class CompassTranslator extends ItemTranslator { } @Override - public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, itemEntry); Tag lodestoneTag = itemStack.getNbt().get("LodestoneTracked"); @@ -75,9 +75,7 @@ public class CompassTranslator extends ItemTranslator { } } - ItemData itemData = super.translateToBedrock(itemStack, itemEntry); - - return itemData; + return super.translateToBedrock(itemStack, itemEntry); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java index 20a36c9e2..9f41472fe 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java @@ -49,13 +49,17 @@ public class PotionTranslator extends ItemTranslator { } @Override - public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, itemEntry); Tag potionTag = itemStack.getNbt().get("Potion"); if (potionTag instanceof StringTag) { Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); if (potion != null) { - return ItemData.of(itemEntry.getBedrockId(), potion.getBedrockId(), itemStack.getAmount(), translateNbtToBedrock(itemStack.getNbt())); + return ItemData.builder() + .id(itemEntry.getBedrockId()) + .damage(potion.getBedrockId()) + .count(itemStack.getAmount()) + .tag(translateNbtToBedrock(itemStack.getNbt())); } GeyserConnector.getInstance().getLogger().debug("Unknown Java potion: " + potionTag.getValue()); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/TippedArrowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/TippedArrowTranslator.java index dd151dcd8..8b64732c4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/TippedArrowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/TippedArrowTranslator.java @@ -52,7 +52,7 @@ public class TippedArrowTranslator extends ItemTranslator { } @Override - public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { if (!itemEntry.getJavaIdentifier().equals("minecraft:tipped_arrow") || itemStack.getNbt() == null) { // We're only concerned about minecraft:arrow when translating Bedrock -> Java return super.translateToBedrock(itemStack, itemEntry); @@ -61,7 +61,11 @@ public class TippedArrowTranslator extends ItemTranslator { if (potionTag instanceof StringTag) { TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByJavaIdentifier(((StringTag) potionTag).getValue()); if (tippedArrowPotion != null) { - return ItemData.of(itemEntry.getBedrockId(), tippedArrowPotion.getBedrockId(), itemStack.getAmount(), translateNbtToBedrock(itemStack.getNbt())); + return ItemData.builder() + .id(itemEntry.getBedrockId()) + .damage(tippedArrowPotion.getBedrockId()) + .count(itemStack.getAmount()) + .tag(translateNbtToBedrock(itemStack.getNbt())); } GeyserConnector.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionTag.getValue()); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java index 2af803807..ae52e4221 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java @@ -55,7 +55,7 @@ public class CrossbowTranslator extends NbtItemStackTranslator { newProjectile.put(new ByteTag("Count", (byte) itemData.getCount())); newProjectile.put(new StringTag("Name", projectileEntry.getBedrockIdentifier())); - newProjectile.put(new ShortTag("Damage", itemData.getDamage())); + newProjectile.put(new ShortTag("Damage", (short) itemData.getDamage())); itemTag.put(newProjectile); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java index 7de101811..942bc7fdc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java @@ -30,8 +30,8 @@ import com.github.steveice10.mc.protocol.data.game.command.CommandParser; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDeclareCommandsPacket; import com.nukkitx.protocol.bedrock.data.command.CommandData; import com.nukkitx.protocol.bedrock.data.command.CommandEnumData; +import com.nukkitx.protocol.bedrock.data.command.CommandParam; import com.nukkitx.protocol.bedrock.data.command.CommandParamData; -import com.nukkitx.protocol.bedrock.data.command.CommandParamType; import com.nukkitx.protocol.bedrock.packet.AvailableCommandsPacket; import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -200,47 +200,47 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator=", "==", etc - return CommandParamType.OPERATOR; + return CommandParam.OPERATOR; case BLOCK_STATE: return BlockTranslator.getAllBlockIdentifiers(); @@ -261,7 +261,7 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index bf78d52c6..693bf94f3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -69,7 +69,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator params = new ArrayList<>(); String recordString = "%item." + soundEvent.name().toLowerCase(Locale.ROOT) + ".desc"; - params.add(LocaleUtils.getLocaleString(recordString, session.getLocale())); - textPacket.setParameters(params); + textPacket.setParameters(Collections.singletonList(LocaleUtils.getLocaleString(recordString, session.getLocale()))); session.sendUpstreamPacket(textPacket); } return; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java index c8af95e80..6115cb57e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java @@ -68,7 +68,7 @@ public class JavaSpawnParticleTranslator extends PacketTranslator 20) return; // 0.0 usually happens on login and causes issues with visuals; anything above 20 means a plugin like OldCombatMechanics is being used // Needs to be sent or no subtitle packet is recognized by the client SetTitlePacket titlePacket = new SetTitlePacket(); @@ -67,7 +68,11 @@ public class CooldownUtils { if (session.isClosed()) return; // Don't run scheduled tasks if the client left if (lastHitTime != session.getLastHitTime()) return; // Means another cooldown has started so there's no need to continue this one SetTitlePacket titlePacket = new SetTitlePacket(); - titlePacket.setType(SetTitlePacket.Type.SUBTITLE); + if (SHOW_COOLDOWN == CooldownType.ACTIONBAR) { + titlePacket.setType(SetTitlePacket.Type.ACTIONBAR); + } else { + titlePacket.setType(SetTitlePacket.Type.SUBTITLE); + } titlePacket.setText(getTitle(session)); titlePacket.setFadeInTime(0); titlePacket.setFadeOutTime(5); @@ -77,7 +82,11 @@ public class CooldownUtils { session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50 } else { SetTitlePacket removeTitlePacket = new SetTitlePacket(); - removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE); + if (SHOW_COOLDOWN == CooldownType.ACTIONBAR) { + removeTitlePacket.setType(SetTitlePacket.Type.ACTIONBAR); + } else { + removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE); + } removeTitlePacket.setText(" "); session.sendUpstreamPacket(removeTitlePacket); } @@ -114,4 +123,33 @@ public class CooldownUtils { } return builder.toString(); } + + @Getter + public enum CooldownType { + TITLE, + ACTIONBAR, + DISABLED; + + public static final CooldownType[] VALUES = values(); + + /** + * Convert the CooldownType string (from config) to the enum, TITLE on fail + * + * @param name CooldownType string + * + * @return The converted CooldownType + */ + public static CooldownType getByName(String name) { + if (name.equalsIgnoreCase("true")) { // Backwards config compatibility + return CooldownType.TITLE; + } + + for (CooldownType type : VALUES) { + if (type.name().equalsIgnoreCase(name)) { + return type; + } + } + return DISABLED; + } + } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java b/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java index 36eda6adc..8846e477c 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java +++ b/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java @@ -69,9 +69,9 @@ public enum FireworkColor { private static final FireworkColor[] VALUES = values(); @Getter - private byte bedrockID; + private final byte bedrockID; @Getter - private int javaID; + private final int javaID; FireworkColor(byte bedrockID, int javaID) { this.bedrockID = bedrockID; diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index ccaa20e82..d4759acaa 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -164,7 +164,10 @@ public class InventoryUtils { display.putList("Lore", NbtType.STRING, Collections.singletonList(ChatColor.RESET + ChatColor.DARK_PURPLE + description)); root.put("display", display.build()); - return ItemData.of(ItemRegistry.ITEM_ENTRIES.get(ItemRegistry.BARRIER_INDEX).getBedrockId(), (short) 0, 1, root.build()); + return ItemData.builder() + .id(ItemRegistry.ITEM_ENTRIES.get(ItemRegistry.BARRIER_INDEX).getBedrockId()) + .count(1) + .tag(root.build()).build(); } /** diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml index 7eccb249f..387dbf4a1 100644 --- a/connector/src/main/resources/config.yml +++ b/connector/src/main/resources/config.yml @@ -112,7 +112,8 @@ allow-third-party-capes: true allow-third-party-ears: false # Allow a fake cooldown indicator to be sent. Bedrock players do not see a cooldown as they still use 1.8 combat -show-cooldown: true +# Can be title, actionbar or false +show-cooldown: title # Controls if coordinates are shown to players. show-coordinates: true @@ -139,6 +140,12 @@ cache-images: 0 # Allows custom skulls to be displayed. Keeping them enabled may cause a performance decrease on older/weaker devices. allow-custom-skulls: true +# Whether to add (at this time, only) the furnace minecart as a separate item in the game, which normally does not exist in Bedrock Edition. +# This should only need to be disabled if using a proxy that does not use the "transfer packet" style of server switching. +# If this is disabled, furnace minecart items will be mapped to hopper minecart items. +# This option requires a restart of Geyser in order to change its setting. +add-non-bedrock-items: true + # Bedrock prevents building and displaying blocks above Y127 in the Nether - # enabling this config option works around that by changing the Nether dimension ID # to the End ID. The main downside to this is that the sky will resemble that of diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 216e90086..c846b8200 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 216e9008678a761b3885808f4f3d43000404381b +Subproject commit c846b8200eb8ebb37207666f7eddb83f2b636c37