> IGNORED_PACKETS = new ObjectArrayList<>();
-
- static {
- Reflections ref = GeyserConnector.getInstance().useXmlReflections() ? FileUtils.getReflections("org.geysermc.connector.network.translators") : new Reflections("org.geysermc.connector.network.translators");
-
- for (Class> clazz : ref.getTypesAnnotatedWith(Translator.class)) {
- Class> packet = clazz.getAnnotation(Translator.class).packet();
-
- GeyserConnector.getInstance().getLogger().debug("Found annotated translator: " + clazz.getCanonicalName() + " : " + packet.getSimpleName());
-
- try {
- if (Packet.class.isAssignableFrom(packet)) {
- Class extends Packet> targetPacket = (Class extends Packet>) packet;
- PacketTranslator extends Packet> translator = (PacketTranslator extends Packet>) clazz.newInstance();
-
- JAVA_TRANSLATOR.translators.put(targetPacket, translator);
- } else if (BedrockPacket.class.isAssignableFrom(packet)) {
- Class extends BedrockPacket> targetPacket = (Class extends BedrockPacket>) packet;
- PacketTranslator extends BedrockPacket> translator = (PacketTranslator extends BedrockPacket>) clazz.newInstance();
-
- BEDROCK_TRANSLATOR.translators.put(targetPacket, translator);
- } else {
- GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.invalid_target", clazz.getCanonicalName()));
- }
- } catch (InstantiationException | IllegalAccessException e) {
- GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.failed", clazz.getCanonicalName()));
- }
- }
-
- IGNORED_PACKETS.add(ServerUpdateLightPacket.class); // Light is handled on Bedrock for us
- IGNORED_PACKETS.add(ServerPlayerListDataPacket.class); // Cant be implemented in bedrock
- }
-
- private PacketTranslatorRegistry() {
- }
-
- public static void init() {
- // no-op
- }
-
- @SuppressWarnings("unchecked")
- public boolean translate(Class extends P> clazz, P packet, GeyserSession session) {
- if (!session.getUpstream().isClosed() && !session.isClosed()) {
- try {
- if (translators.containsKey(clazz)) {
- ((PacketTranslator
) translators.get(clazz)).translate(packet, session);
- return true;
- } else {
- if (!IGNORED_PACKETS.contains(clazz))
- GeyserConnector.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet));
- }
- } catch (Throwable ex) {
- GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.packet.failed", packet.getClass().getSimpleName()), ex);
- ex.printStackTrace();
- }
- }
- return false;
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java
deleted file mode 100644
index 3e40ddd6f..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
-
-import com.nukkitx.math.vector.Vector3i;
-import com.nukkitx.protocol.bedrock.packet.BlockPickRequestPacket;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.network.translators.world.block.BlockTranslator;
-import org.geysermc.connector.utils.InventoryUtils;
-
-@Translator(packet = BlockPickRequestPacket.class)
-public class BedrockBlockPickRequestTranslator extends PacketTranslator {
-
- @Override
- public void translate(BlockPickRequestPacket packet, GeyserSession session) {
- Vector3i vector = packet.getBlockPosition();
- int blockToPick = session.getConnector().getWorldManager().getBlockAt(session, vector.getX(), vector.getY(), vector.getZ());
-
- // Block is air - chunk caching is probably off
- if (blockToPick == BlockTranslator.JAVA_AIR_ID) {
- return;
- }
-
- String targetIdentifier = BlockTranslator.getJavaIdBlockMap().inverse().get(blockToPick).split("\\[")[0];
- InventoryUtils.findOrCreatePickedBlock(session, targetIdentifier);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java
deleted file mode 100644
index 00905f6d9..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
-
-import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCloseWindowPacket;
-import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.utils.InventoryUtils;
-
-@Translator(packet = ContainerClosePacket.class)
-public class BedrockContainerCloseTranslator extends PacketTranslator {
-
- @Override
- public void translate(ContainerClosePacket packet, GeyserSession session) {
- session.setLastWindowCloseTime(0);
- byte windowId = packet.getId();
- Inventory openInventory = session.getInventoryCache().getOpenInventory();
- if (windowId == -1) { //player inventory or crafting table
- if (openInventory != null) {
- windowId = (byte) openInventory.getId();
- } else {
- windowId = 0;
- }
- }
-
- if (windowId == 0 || (openInventory != null && openInventory.getId() == windowId)) {
- ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(windowId);
- session.getDownstream().getSession().send(closeWindowPacket);
- InventoryUtils.closeInventory(session, windowId);
- }
-
- //Client wants close confirmation
- session.sendUpstreamPacket(packet);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockEntityPickRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockEntityPickRequestTranslator.java
deleted file mode 100644
index 4aa044ee4..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockEntityPickRequestTranslator.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
-
-import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
-import com.nukkitx.protocol.bedrock.data.entity.EntityData;
-import com.nukkitx.protocol.bedrock.packet.EntityPickRequestPacket;
-import org.geysermc.connector.entity.Entity;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.network.translators.item.ItemEntry;
-import org.geysermc.connector.network.translators.item.ItemRegistry;
-import org.geysermc.connector.utils.InventoryUtils;
-
-/**
- * Called when the Bedrock user uses the pick block button on an entity
- */
-@Translator(packet = EntityPickRequestPacket.class)
-public class BedrockEntityPickRequestTranslator extends PacketTranslator {
-
- @Override
- public void translate(EntityPickRequestPacket packet, GeyserSession session) {
- if (session.getGameMode() != GameMode.CREATIVE) return; // Apparently Java behavior
- Entity entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId());
- if (entity == null) return;
-
- // Get the corresponding item
- String itemName;
- switch (entity.getEntityType()) {
- case BOAT:
- // Include type of boat in the name
- int variant = entity.getMetadata().getInt(EntityData.VARIANT);
- String typeOfBoat;
- switch (variant) {
- case 1:
- typeOfBoat = "spruce";
- break;
- case 2:
- typeOfBoat = "birch";
- break;
- case 3:
- typeOfBoat = "jungle";
- break;
- case 4:
- typeOfBoat = "acacia";
- break;
- case 5:
- typeOfBoat = "dark_oak";
- break;
- default:
- typeOfBoat = "oak";
- break;
- }
- itemName = typeOfBoat + "_boat";
- break;
- case LEASH_KNOT:
- itemName = "lead";
- break;
- case MINECART_CHEST:
- case MINECART_COMMAND_BLOCK:
- case MINECART_FURNACE:
- case MINECART_HOPPER:
- case MINECART_TNT:
- // Move MINECART to the end of the name
- itemName = entity.getEntityType().toString().toLowerCase().replace("minecart_", "") + "_minecart";
- break;
- case MINECART_SPAWNER:
- // Turns into a normal minecart
- itemName = "minecart";
- break;
- case ARMOR_STAND:
- case END_CRYSTAL:
- case ITEM_FRAME:
- case MINECART:
- case PAINTING:
- // No spawn egg, just an item
- itemName = entity.getEntityType().toString().toLowerCase();
- break;
- default:
- itemName = entity.getEntityType().toString().toLowerCase() + "_spawn_egg";
- break;
- }
-
- String fullItemName = "minecraft:" + itemName;
- ItemEntry entry = ItemRegistry.getItemEntry(fullItemName);
- // Verify it is, indeed, an item
- if (entry == null) return;
-
- InventoryUtils.findOrCreatePickedBlock(session, fullItemName);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java
deleted file mode 100644
index 5b0fbb222..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
-
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
-import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
-import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
-import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction;
-import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
-import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket;
-import com.nukkitx.math.vector.Vector3f;
-import com.nukkitx.math.vector.Vector3i;
-import com.nukkitx.protocol.bedrock.data.LevelEventType;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
-import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
-import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
-import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
-import org.geysermc.connector.entity.CommandBlockMinecartEntity;
-import org.geysermc.connector.entity.Entity;
-import org.geysermc.connector.entity.ItemFrameEntity;
-import org.geysermc.connector.entity.living.merchant.AbstractMerchantEntity;
-import org.geysermc.connector.entity.type.EntityType;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
-import org.geysermc.connector.network.translators.item.ItemEntry;
-import org.geysermc.connector.network.translators.item.ItemRegistry;
-import org.geysermc.connector.network.translators.sound.EntitySoundInteractionHandler;
-import org.geysermc.connector.network.translators.world.block.BlockTranslator;
-import org.geysermc.connector.utils.BlockUtils;
-import org.geysermc.connector.utils.InventoryUtils;
-
-import java.util.concurrent.TimeUnit;
-
-@Translator(packet = InventoryTransactionPacket.class)
-public class BedrockInventoryTransactionTranslator extends PacketTranslator {
-
- @Override
- public void translate(InventoryTransactionPacket packet, GeyserSession session) {
- switch (packet.getTransactionType()) {
- case NORMAL:
- Inventory inventory = session.getInventoryCache().getOpenInventory();
- if (inventory == null) inventory = session.getInventory();
- InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType()).translateActions(session, inventory, packet.getActions());
- break;
- case INVENTORY_MISMATCH:
- Inventory inv = session.getInventoryCache().getOpenInventory();
- if (inv == null) inv = session.getInventory();
- InventoryTranslator.INVENTORY_TRANSLATORS.get(inv.getWindowType()).updateInventory(session, inv);
- InventoryUtils.updateCursor(session);
- break;
- case ITEM_USE:
- switch (packet.getActionType()) {
- case 0:
- // 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 &&
- packet.getBlockPosition().distanceSquared(session.getLastInteractionPosition()) < 0.00001;
- session.setLastInteractionPosition(packet.getBlockPosition());
- if (hasAlreadyClicked) {
- break;
- } else {
- // Only update the interaction time if it's valid - that way holding down still works.
- session.setLastInteractionTime(System.currentTimeMillis());
- }
-
- // Bedrock sends block interact code for a Java entity so we send entity code back to Java
- if (BlockTranslator.isItemFrame(packet.getBlockRuntimeId()) &&
- session.getEntityCache().getEntityByJavaId(ItemFrameEntity.getItemFrameEntityId(session, packet.getBlockPosition())) != null) {
- Vector3f vector = packet.getClickPosition();
- ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) ItemFrameEntity.getItemFrameEntityId(session, packet.getBlockPosition()),
- InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
- ClientPlayerInteractEntityPacket interactAtPacket = new ClientPlayerInteractEntityPacket((int) ItemFrameEntity.getItemFrameEntityId(session, packet.getBlockPosition()),
- InteractAction.INTERACT_AT, vector.getX(), vector.getY(), vector.getZ(), Hand.MAIN_HAND, session.isSneaking());
- session.sendDownstreamPacket(interactPacket);
- session.sendDownstreamPacket(interactAtPacket);
- break;
- }
-
- ClientPlayerPlaceBlockPacket blockPacket = new ClientPlayerPlaceBlockPacket(
- new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()),
- BlockFace.values()[packet.getBlockFace()],
- Hand.MAIN_HAND,
- packet.getClickPosition().getX(), packet.getClickPosition().getY(), packet.getClickPosition().getZ(),
- false);
- session.sendDownstreamPacket(blockPacket);
-
- // Otherwise boats will not be able to be placed in survival and buckets won't work on mobile
- if (packet.getItemInHand() != null && ItemRegistry.BOATS.contains(packet.getItemInHand().getId())) {
- ClientPlayerUseItemPacket itemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
- session.sendDownstreamPacket(itemPacket);
- }
- // Check actions, otherwise buckets may be activated when block inventories are accessed
- else if (packet.getItemInHand() != null && ItemRegistry.BUCKETS.contains(packet.getItemInHand().getId())) {
- // Let the server decide if the bucket item should change, not the client, and revert the changes the client made
- InventorySlotPacket slotPacket = new InventorySlotPacket();
- slotPacket.setContainerId(ContainerId.INVENTORY);
- slotPacket.setSlot(packet.getHotbarSlot());
- slotPacket.setItem(packet.getItemInHand());
- session.sendUpstreamPacket(slotPacket);
- // Delay the interaction in case the client doesn't intend to actually use the bucket
- // See BedrockActionTranslator.java
- session.setBucketScheduledFuture(session.getConnector().getGeneralThreadPool().schedule(() -> {
- ClientPlayerUseItemPacket itemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
- session.sendDownstreamPacket(itemPacket);
- }, 5, TimeUnit.MILLISECONDS));
- }
-
- if (packet.getActions().isEmpty()) {
- if (session.getOpPermissionLevel() >= 2 && session.getGameMode() == GameMode.CREATIVE) {
- // Otherwise insufficient permissions
- int blockState = BlockTranslator.getJavaBlockState(packet.getBlockRuntimeId());
- String blockName = BlockTranslator.getJavaIdBlockMap().inverse().getOrDefault(blockState, "");
- // In the future this can be used for structure blocks too, however not all elements
- // are available in each GUI
- if (blockName.contains("jigsaw")) {
- ContainerOpenPacket openPacket = new ContainerOpenPacket();
- openPacket.setBlockPosition(packet.getBlockPosition());
- openPacket.setId((byte) 1);
- openPacket.setType(ContainerType.JIGSAW_EDITOR);
- openPacket.setUniqueEntityId(-1);
- session.sendUpstreamPacket(openPacket);
- }
- }
- }
-
- Vector3i blockPos = BlockUtils.getBlockPosition(packet.getBlockPosition(), packet.getBlockFace());
- ItemEntry handItem = ItemRegistry.getItem(packet.getItemInHand());
- if (handItem.isBlock()) {
- session.setLastBlockPlacePosition(blockPos);
- session.setLastBlockPlacedId(handItem.getJavaIdentifier());
- }
- session.setInteracting(true);
- break;
- case 1:
- ItemStack shieldSlot = session.getInventory().getItem(session.getInventory().getHeldItemSlot() + 36);
- // Handled in Entity.java
- if (shieldSlot != null && shieldSlot.getId() == ItemRegistry.SHIELD.getJavaId()) {
- break;
- }
-
- // Handled in ITEM_USE if the item is not milk
- if (packet.getItemInHand() != null && ItemRegistry.BUCKETS.contains(packet.getItemInHand().getId()) &&
- packet.getItemInHand().getId() != ItemRegistry.MILK_BUCKET.getBedrockId()) {
- break;
- }
-
- ClientPlayerUseItemPacket useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
- session.sendDownstreamPacket(useItemPacket);
- break;
- case 2:
- int blockState = session.getConnector().getWorldManager().getBlockAt(session, packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ());
- double blockHardness = BlockTranslator.JAVA_RUNTIME_ID_TO_HARDNESS.get(blockState);
- if (session.getGameMode() == GameMode.CREATIVE || (session.getConnector().getConfig().isCacheChunks() && blockHardness == 0)) {
- session.setLastBlockPlacedId(null);
- session.setLastBlockPlacePosition(null);
-
- LevelEventPacket blockBreakPacket = new LevelEventPacket();
- blockBreakPacket.setType(LevelEventType.PARTICLE_DESTROY_BLOCK);
- blockBreakPacket.setPosition(packet.getBlockPosition().toFloat());
- blockBreakPacket.setData(BlockTranslator.getBedrockBlockId(blockState));
- session.sendUpstreamPacket(blockBreakPacket);
- }
-
- long frameEntityId = ItemFrameEntity.getItemFrameEntityId(session, packet.getBlockPosition());
- if (frameEntityId != -1 && session.getEntityCache().getEntityByJavaId(frameEntityId) != null) {
- ClientPlayerInteractEntityPacket attackPacket = new ClientPlayerInteractEntityPacket((int) frameEntityId, InteractAction.ATTACK, session.isSneaking());
- session.sendDownstreamPacket(attackPacket);
- break;
- }
-
- PlayerAction action = session.getGameMode() == GameMode.CREATIVE ? PlayerAction.START_DIGGING : PlayerAction.FINISH_DIGGING;
- Position pos = new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ());
- ClientPlayerActionPacket breakPacket = new ClientPlayerActionPacket(action, pos, BlockFace.values()[packet.getBlockFace()]);
- session.sendDownstreamPacket(breakPacket);
- break;
- }
- break;
- case ITEM_RELEASE:
- if (packet.getActionType() == 0) {
- // Followed to the Minecraft Protocol specification outlined at wiki.vg
- ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(0,0,0),
- BlockFace.DOWN);
- session.sendDownstreamPacket(releaseItemPacket);
- }
- break;
- case ITEM_USE_ON_ENTITY:
- Entity entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId());
- if (entity == null)
- return;
-
- //https://wiki.vg/Protocol#Interact_Entity
- switch (packet.getActionType()) {
- case 0: //Interact
- if (entity instanceof CommandBlockMinecartEntity) {
- // The UI is handled client-side on Java Edition
- // Ensure OP permission level and gamemode is appropriate
- if (session.getOpPermissionLevel() < 2 || session.getGameMode() != GameMode.CREATIVE) return;
- ContainerOpenPacket openPacket = new ContainerOpenPacket();
- openPacket.setBlockPosition(Vector3i.ZERO);
- openPacket.setId((byte) 1);
- openPacket.setType(ContainerType.COMMAND_BLOCK);
- openPacket.setUniqueEntityId(entity.getGeyserId());
- session.sendUpstreamPacket(openPacket);
- break;
- }
- Vector3f vector = packet.getClickPosition();
- ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
- InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
- ClientPlayerInteractEntityPacket interactAtPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
- InteractAction.INTERACT_AT, vector.getX(), vector.getY(), vector.getZ(), Hand.MAIN_HAND, session.isSneaking());
- session.sendDownstreamPacket(interactPacket);
- session.sendDownstreamPacket(interactAtPacket);
-
- EntitySoundInteractionHandler.handleEntityInteraction(session, vector, entity);
-
- if (entity instanceof AbstractMerchantEntity) {
- session.setLastInteractedVillagerEid(packet.getRuntimeEntityId());
- }
- break;
- case 1: //Attack
- if (entity.getEntityType() == EntityType.ENDER_DRAGON) {
- // Redirects the attack to its body entity, this only happens when
- // attacking the underbelly of the ender dragon
- ClientPlayerInteractEntityPacket attackPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId() + 3,
- InteractAction.ATTACK, session.isSneaking());
- session.sendDownstreamPacket(attackPacket);
- } else {
- ClientPlayerInteractEntityPacket attackPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
- InteractAction.ATTACK, session.isSneaking());
- session.sendDownstreamPacket(attackPacket);
- }
- break;
- }
- break;
- }
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMobEquipmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMobEquipmentTranslator.java
deleted file mode 100644
index a220e389f..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMobEquipmentTranslator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
-
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerChangeHeldItemPacket;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
-import com.nukkitx.protocol.bedrock.packet.MobEquipmentPacket;
-import org.geysermc.connector.utils.CooldownUtils;
-
-@Translator(packet = MobEquipmentPacket.class)
-public class BedrockMobEquipmentTranslator extends PacketTranslator {
-
- @Override
- public void translate(MobEquipmentPacket packet, GeyserSession session) {
- if (!session.isSpawned() || packet.getHotbarSlot() > 8 ||
- packet.getContainerId() != ContainerId.INVENTORY || session.getInventory().getHeldItemSlot() == packet.getHotbarSlot()) {
- // For the last condition - Don't update the slot if the slot is the same - not Java Edition behavior and messes with plugins such as Grief Prevention
- return;
- }
-
- session.getInventory().setHeldItemSlot(packet.getHotbarSlot());
-
- ClientPlayerChangeHeldItemPacket changeHeldItemPacket = new ClientPlayerChangeHeldItemPacket(packet.getHotbarSlot());
- session.sendDownstreamPacket(changeHeldItemPacket);
-
- // Java sends a cooldown indicator whenever you switch an item
- CooldownUtils.sendCooldown(session);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMoveEntityAbsoluteTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMoveEntityAbsoluteTranslator.java
deleted file mode 100644
index 26d7f1d46..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMoveEntityAbsoluteTranslator.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
-
-import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientVehicleMovePacket;
-import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
-// Used for horses
-@Translator(packet = MoveEntityAbsolutePacket.class)
-public class BedrockMoveEntityAbsoluteTranslator extends PacketTranslator {
-
- @Override
- public void translate(MoveEntityAbsolutePacket packet, GeyserSession session) {
-
- ClientVehicleMovePacket clientVehicleMovePacket = new ClientVehicleMovePacket(
- packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ(),
- packet.getRotation().getY() - 90, packet.getRotation().getX()
- );
- session.sendDownstreamPacket(clientVehicleMovePacket);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockNetworkStackLatencyTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockNetworkStackLatencyTranslator.java
deleted file mode 100644
index d480b526f..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockNetworkStackLatencyTranslator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
-
-import com.github.steveice10.mc.protocol.packet.ingame.client.ClientKeepAlivePacket;
-import com.nukkitx.protocol.bedrock.packet.NetworkStackLatencyPacket;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
-/**
- * Used to send the keep alive packet back to the server
- */
-@Translator(packet = NetworkStackLatencyPacket.class)
-public class BedrockNetworkStackLatencyTranslator extends PacketTranslator {
-
- @Override
- public void translate(NetworkStackLatencyPacket packet, GeyserSession session) {
- // The client sends a timestamp back but it's rounded and therefore unreliable when we need the exact number
- ClientKeepAlivePacket keepAlivePacket = new ClientKeepAlivePacket(session.getLastKeepAliveTimestamp());
- session.sendDownstreamPacket(keepAlivePacket);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInputTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInputTranslator.java
deleted file mode 100644
index 2bd46c7ce..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInputTranslator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
-
-import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientSteerVehiclePacket;
-import com.nukkitx.protocol.bedrock.packet.PlayerInputPacket;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
-// Makes minecarts respond to player input
-@Translator(packet = PlayerInputPacket.class)
-public class BedrockPlayerInputTranslator extends PacketTranslator {
-
- @Override
- public void translate(PlayerInputPacket packet, GeyserSession session) {
- ClientSteerVehiclePacket clientSteerVehiclePacket = new ClientSteerVehiclePacket(
- packet.getInputMotion().getX(), packet.getInputMotion().getY(), packet.isJumping(), packet.isSneaking()
- );
-
- session.sendDownstreamPacket(clientSteerVehiclePacket);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/BedrockEntityEventTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/BedrockEntityEventTranslator.java
deleted file mode 100644
index 18fd6614e..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/BedrockEntityEventTranslator.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock.entity;
-
-import com.github.steveice10.mc.protocol.data.game.window.VillagerTrade;
-import com.github.steveice10.mc.protocol.data.game.window.WindowType;
-import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientSelectTradePacket;
-import com.nukkitx.protocol.bedrock.data.entity.EntityData;
-import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
-import org.geysermc.connector.entity.Entity;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
-@Translator(packet = EntityEventPacket.class)
-public class BedrockEntityEventTranslator extends PacketTranslator {
-
- @Override
- public void translate(EntityEventPacket packet, GeyserSession session) {
- switch (packet.getType()) {
- // Resend the packet so we get the eating sounds
- case EATING_ITEM:
- session.sendUpstreamPacket(packet);
- return;
- case COMPLETE_TRADE:
- ClientSelectTradePacket selectTradePacket = new ClientSelectTradePacket(packet.getData());
- session.getDownstream().getSession().send(selectTradePacket);
-
- Entity villager = session.getPlayerEntity();
- Inventory openInventory = session.getInventoryCache().getOpenInventory();
- if (openInventory != null && openInventory.getWindowType() == WindowType.MERCHANT) {
- VillagerTrade[] trades = session.getVillagerTrades();
- if (trades != null && packet.getData() >= 0 && packet.getData() < trades.length) {
- VillagerTrade trade = session.getVillagerTrades()[packet.getData()];
- openInventory.setItem(2, trade.getOutput());
- villager.getMetadata().put(EntityData.TRADE_XP, trade.getXp() + villager.getMetadata().getInt(EntityData.TRADE_XP));
- villager.updateBedrockMetadata(session);
- }
- }
- return;
- }
- session.getConnector().getLogger().debug("Did not translate incoming EntityEventPacket: " + packet.toString());
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockActionTranslator.java
deleted file mode 100644
index e3bcbce9f..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockActionTranslator.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock.entity.player;
-
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
-import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
-import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState;
-import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerAbilitiesPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket;
-import com.nukkitx.math.vector.Vector3i;
-import com.nukkitx.protocol.bedrock.data.LevelEventType;
-import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
-import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
-import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
-import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
-import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
-import org.geysermc.connector.entity.Entity;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.network.translators.world.block.BlockTranslator;
-import org.geysermc.connector.utils.BlockUtils;
-
-import java.util.concurrent.TimeUnit;
-
-@Translator(packet = PlayerActionPacket.class)
-public class BedrockActionTranslator extends PacketTranslator {
-
- @Override
- public void translate(PlayerActionPacket packet, GeyserSession session) {
- Entity entity = session.getPlayerEntity();
- if (entity == null)
- return;
-
- Vector3i vector = packet.getBlockPosition();
- Position position = new Position(vector.getX(), vector.getY(), vector.getZ());
-
- switch (packet.getAction()) {
- case RESPAWN:
- // Respawn process is finished and the server and client are both OK with respawning.
- EntityEventPacket eventPacket = new EntityEventPacket();
- eventPacket.setRuntimeEntityId(entity.getGeyserId());
- eventPacket.setType(EntityEventType.RESPAWN);
- eventPacket.setData(0);
- session.sendUpstreamPacket(eventPacket);
- // Resend attributes or else in rare cases the user can think they're not dead when they are, upon joining the server
- entity.updateBedrockAttributes(session);
- break;
- case START_SWIMMING:
- ClientPlayerStatePacket startSwimPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.START_SPRINTING);
- session.sendDownstreamPacket(startSwimPacket);
- break;
- case STOP_SWIMMING:
- ClientPlayerStatePacket stopSwimPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.STOP_SPRINTING);
- session.sendDownstreamPacket(stopSwimPacket);
- break;
- case START_GLIDE:
- // Otherwise gliding will not work in creative
- ClientPlayerAbilitiesPacket playerAbilitiesPacket = new ClientPlayerAbilitiesPacket(false);
- session.sendDownstreamPacket(playerAbilitiesPacket);
- case STOP_GLIDE:
- ClientPlayerStatePacket glidePacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.START_ELYTRA_FLYING);
- session.sendDownstreamPacket(glidePacket);
- break;
- case START_SNEAK:
- ClientPlayerStatePacket startSneakPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.START_SNEAKING);
- session.sendDownstreamPacket(startSneakPacket);
- session.setSneaking(true);
- break;
- case STOP_SNEAK:
- ClientPlayerStatePacket stopSneakPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.STOP_SNEAKING);
- session.sendDownstreamPacket(stopSneakPacket);
- session.setSneaking(false);
- break;
- case START_SPRINT:
- ClientPlayerStatePacket startSprintPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.START_SPRINTING);
- session.sendDownstreamPacket(startSprintPacket);
- session.setSprinting(true);
- break;
- case STOP_SPRINT:
- ClientPlayerStatePacket stopSprintPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.STOP_SPRINTING);
- session.sendDownstreamPacket(stopSprintPacket);
- session.setSprinting(false);
- break;
- case DROP_ITEM:
- ClientPlayerActionPacket dropItemPacket = new ClientPlayerActionPacket(PlayerAction.DROP_ITEM, position, BlockFace.values()[packet.getFace()]);
- session.sendDownstreamPacket(dropItemPacket);
- break;
- case STOP_SLEEP:
- ClientPlayerStatePacket stopSleepingPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.LEAVE_BED);
- session.sendDownstreamPacket(stopSleepingPacket);
- break;
- case BLOCK_INTERACT:
- // Client means to interact with a block; cancel bucket interaction, if any
- if (session.getBucketScheduledFuture() != null) {
- session.getBucketScheduledFuture().cancel(true);
- session.setBucketScheduledFuture(null);
- }
- // Otherwise handled in BedrockInventoryTransactionTranslator
- break;
- case START_BREAK:
- if (session.getConnector().getConfig().isCacheChunks()) {
- // Account for fire - the client likes to hit the block behind.
- Vector3i fireBlockPos = BlockUtils.getBlockPosition(packet.getBlockPosition(), packet.getFace());
- int blockUp = session.getConnector().getWorldManager().getBlockAt(session, fireBlockPos);
- String identifier = BlockTranslator.getJavaIdBlockMap().inverse().get(blockUp);
- if (identifier.startsWith("minecraft:fire") || identifier.startsWith("minecraft:soul_fire")) {
- ClientPlayerActionPacket startBreakingPacket = new ClientPlayerActionPacket(PlayerAction.START_DIGGING, new Position(fireBlockPos.getX(),
- fireBlockPos.getY(), fireBlockPos.getZ()), BlockFace.values()[packet.getFace()]);
- session.sendDownstreamPacket(startBreakingPacket);
- break;
- }
- }
- ClientPlayerActionPacket startBreakingPacket = new ClientPlayerActionPacket(PlayerAction.START_DIGGING, new Position(packet.getBlockPosition().getX(),
- packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()), BlockFace.values()[packet.getFace()]);
- session.sendDownstreamPacket(startBreakingPacket);
- break;
- case CONTINUE_BREAK:
- LevelEventPacket continueBreakPacket = new LevelEventPacket();
- continueBreakPacket.setType(LevelEventType.PARTICLE_CRACK_BLOCK);
- continueBreakPacket.setData(BlockTranslator.getBedrockBlockId(session.getBreakingBlock()));
- continueBreakPacket.setPosition(packet.getBlockPosition().toFloat());
- session.sendUpstreamPacket(continueBreakPacket);
- break;
- case ABORT_BREAK:
- ClientPlayerActionPacket abortBreakingPacket = new ClientPlayerActionPacket(PlayerAction.CANCEL_DIGGING, new Position(packet.getBlockPosition().getX(),
- packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()), BlockFace.DOWN);
- session.sendDownstreamPacket(abortBreakingPacket);
- break;
- case STOP_BREAK:
- // Handled in BedrockInventoryTransactionTranslator
- break;
- case DIMENSION_CHANGE_SUCCESS:
- if (session.getPendingDimSwitches().decrementAndGet() == 0) {
- //sometimes the client doesn't feel like loading
- PlayStatusPacket spawnPacket = new PlayStatusPacket();
- spawnPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
- session.sendUpstreamPacket(spawnPacket);
- entity.updateBedrockAttributes(session);
- session.getEntityCache().updateBossBars();
- }
- break;
- case JUMP:
- session.setJumping(true);
- session.getConnector().getGeneralThreadPool().schedule(() -> {
- session.setJumping(false);
- }, 1, TimeUnit.SECONDS);
- break;
- }
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockEmoteTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockEmoteTranslator.java
deleted file mode 100644
index 813c5594c..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockEmoteTranslator.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock.entity.player;
-
-import com.nukkitx.protocol.bedrock.packet.EmotePacket;
-import org.geysermc.connector.entity.Entity;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
-@Translator(packet = EmotePacket.class)
-public class BedrockEmoteTranslator extends PacketTranslator {
-
- @Override
- public void translate(EmotePacket packet, GeyserSession session) {
- long javaId = session.getPlayerEntity().getEntityId();
- for (GeyserSession otherSession : session.getConnector().getPlayers()) {
- if (otherSession != session) {
- if (otherSession.isClosed()) continue;
- Entity otherEntity = otherSession.getEntityCache().getEntityByJavaId(javaId);
- if (otherEntity == null) continue;
- packet.setRuntimeEntityId(otherEntity.getGeyserId());
- otherSession.sendUpstreamPacket(packet);
- }
- }
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockInteractTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockInteractTranslator.java
deleted file mode 100644
index 6c03cd033..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockInteractTranslator.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock.entity.player;
-
-import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
-import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction;
-import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket;
-import com.nukkitx.protocol.bedrock.data.entity.EntityData;
-import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap;
-import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
-import com.nukkitx.protocol.bedrock.packet.InteractPacket;
-import lombok.Getter;
-import org.geysermc.connector.entity.Entity;
-import org.geysermc.connector.entity.type.EntityType;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.network.translators.item.ItemEntry;
-import org.geysermc.connector.network.translators.item.ItemRegistry;
-
-import java.util.Arrays;
-import java.util.List;
-
-@Translator(packet = InteractPacket.class)
-public class BedrockInteractTranslator extends PacketTranslator {
-
- /**
- * A list of all foods a horse/donkey can eat on Java Edition.
- * Used to display interactive tag if needed.
- */
- private static final List DONKEY_AND_HORSE_FOODS = Arrays.asList("golden_apple", "enchanted_golden_apple",
- "golden_carrot", "sugar", "apple", "wheat", "hay_block");
-
- /**
- * A list of all flowers. Used for feeding bees.
- */
- private static final List FLOWERS = Arrays.asList("dandelion", "poppy", "blue_orchid", "allium", "azure_bluet",
- "red_tulip", "pink_tulip", "white_tulip", "orange_tulip", "cornflower", "lily_of_the_valley", "wither_rose",
- "sunflower", "lilac", "rose_bush", "peony");
-
- /**
- * All entity types that can be leashed on Java Edition
- */
- private static final List LEASHABLE_MOB_TYPES = Arrays.asList(EntityType.BEE, EntityType.CAT, EntityType.CHICKEN,
- EntityType.COW, EntityType.DOLPHIN, EntityType.DONKEY, EntityType.FOX, EntityType.HOGLIN, EntityType.HORSE, EntityType.SKELETON_HORSE,
- EntityType.ZOMBIE_HORSE, EntityType.IRON_GOLEM, EntityType.LLAMA, EntityType.TRADER_LLAMA, EntityType.MOOSHROOM,
- EntityType.MULE, EntityType.OCELOT, EntityType.PARROT, EntityType.PIG, EntityType.POLAR_BEAR, EntityType.RABBIT,
- EntityType.SHEEP, EntityType.SNOW_GOLEM, EntityType.STRIDER, EntityType.WOLF, EntityType.ZOGLIN);
-
- private static final List SADDLEABLE_WHEN_TAMED_MOB_TYPES = Arrays.asList(EntityType.DONKEY, EntityType.HORSE,
- EntityType.ZOMBIE_HORSE, EntityType.MULE);
- /**
- * A list of all foods a wolf can eat on Java Edition.
- * Used to display interactive tag if needed.
- */
- private static final List WOLF_FOODS = Arrays.asList("pufferfish", "tropical_fish", "chicken", "cooked_chicken",
- "porkchop", "beef", "rabbit", "cooked_porkchop", "cooked_beef", "rotten_flesh", "mutton", "cooked_mutton",
- "cooked_rabbit");
-
- @Override
- public void translate(InteractPacket packet, GeyserSession session) {
- Entity entity;
- if (packet.getRuntimeEntityId() == session.getPlayerEntity().getGeyserId()) {
- //Player is not in entity cache
- entity = session.getPlayerEntity();
- } else {
- entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId());
- }
- if (entity == null)
- return;
-
- switch (packet.getAction()) {
- case INTERACT:
- if (session.getInventory().getItem(session.getInventory().getHeldItemSlot() + 36).getId() == ItemRegistry.SHIELD.getJavaId()) {
- break;
- }
- ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
- InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
- session.sendDownstreamPacket(interactPacket);
- break;
- case DAMAGE:
- ClientPlayerInteractEntityPacket attackPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
- InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking());
- session.sendDownstreamPacket(attackPacket);
- break;
- case LEAVE_VEHICLE:
- ClientPlayerStatePacket sneakPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.START_SNEAKING);
- session.sendDownstreamPacket(sneakPacket);
- session.setRidingVehicleEntity(null);
- break;
- case MOUSEOVER:
- // Handle the buttons for mobile - "Mount", etc; and the suggestions for console - "ZL: Mount", etc
- if (packet.getRuntimeEntityId() != 0) {
- Entity interactEntity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId());
- if (interactEntity == null)
- return;
- EntityDataMap entityMetadata = interactEntity.getMetadata();
- ItemEntry itemEntry = session.getInventory().getItemInHand() == null ? ItemEntry.AIR : ItemRegistry.getItem(session.getInventory().getItemInHand());
- String javaIdentifierStripped = itemEntry.getJavaIdentifier().replace("minecraft:", "");
-
- // TODO - in the future, update these in the metadata? So the client doesn't have to wiggle their cursor around for it to happen
- // TODO - also, might be good to abstract out the eating thing. I know there will need to be food tracked for https://github.com/GeyserMC/Geyser/issues/1005 but not all food is breeding food
- InteractiveTag interactiveTag = InteractiveTag.NONE;
- if (entityMetadata.getLong(EntityData.LEASH_HOLDER_EID) == session.getPlayerEntity().getGeyserId()) {
- // Unleash the entity
- interactiveTag = InteractiveTag.REMOVE_LEASH;
- } else if (javaIdentifierStripped.equals("saddle") && !entityMetadata.getFlags().getFlag(EntityFlag.SADDLED) &&
- ((SADDLEABLE_WHEN_TAMED_MOB_TYPES.contains(interactEntity.getEntityType()) && entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) ||
- interactEntity.getEntityType() == EntityType.PIG || interactEntity.getEntityType() == EntityType.STRIDER)) {
- // Entity can be saddled and the conditions meet (entity can be saddled and, if needed, is tamed)
- interactiveTag = InteractiveTag.SADDLE;
- } else if (javaIdentifierStripped.equals("name_tag") && session.getInventory().getItemInHand().getNbt() != null &&
- session.getInventory().getItemInHand().getNbt().contains("display")) {
- // Holding a named name tag
- interactiveTag = InteractiveTag.NAME;
- } else if (javaIdentifierStripped.equals("lead") && LEASHABLE_MOB_TYPES.contains(interactEntity.getEntityType()) &&
- entityMetadata.getLong(EntityData.LEASH_HOLDER_EID) == -1L) {
- // Holding a leash and the mob is leashable for sure
- // (Plugins can change this behavior so that's something to look into in the far far future)
- interactiveTag = InteractiveTag.LEASH;
- } else {
- switch (interactEntity.getEntityType()) {
- case BEE:
- if (FLOWERS.contains(javaIdentifierStripped)) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case BOAT:
- interactiveTag = InteractiveTag.BOARD_BOAT;
- break;
- case CAT:
- if (javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon")) {
- interactiveTag = InteractiveTag.FEED;
- } else if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) &&
- entityMetadata.getLong(EntityData.OWNER_EID) == session.getPlayerEntity().getGeyserId()) {
- // Tamed and owned by player - can sit/stand
- interactiveTag = entityMetadata.getFlags().getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
- break;
- }
- break;
- case CHICKEN:
- if (javaIdentifierStripped.contains("seeds")) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case MOOSHROOM:
- // Shear the mooshroom
- if (javaIdentifierStripped.equals("shears")) {
- interactiveTag = InteractiveTag.MOOSHROOM_SHEAR;
- break;
- }
- // Bowls are acceptable here
- else if (javaIdentifierStripped.equals("bowl")) {
- interactiveTag = InteractiveTag.MOOSHROOM_MILK_STEW;
- break;
- }
- // Fall down to COW as this works on mooshrooms
- case COW:
- if (javaIdentifierStripped.equals("wheat")) {
- interactiveTag = InteractiveTag.FEED;
- } else if (javaIdentifierStripped.equals("bucket")) {
- // Milk the cow
- interactiveTag = InteractiveTag.MILK;
- }
- break;
- case CREEPER:
- if (javaIdentifierStripped.equals("flint_and_steel")) {
- // Today I learned that you can ignite a creeper with flint and steel! Huh.
- interactiveTag = InteractiveTag.IGNITE_CREEPER;
- }
- break;
- case DONKEY:
- case LLAMA:
- case MULE:
- if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) && !entityMetadata.getFlags().getFlag(EntityFlag.CHESTED)
- && javaIdentifierStripped.equals("chest")) {
- // Can attach a chest
- interactiveTag = InteractiveTag.ATTACH_CHEST;
- break;
- }
- // Intentional fall-through
- case HORSE:
- case SKELETON_HORSE:
- case TRADER_LLAMA:
- case ZOMBIE_HORSE:
- // have another switch statement as, while these share mount attributes they don't share food
- switch (interactEntity.getEntityType()) {
- case LLAMA:
- case TRADER_LLAMA:
- if (javaIdentifierStripped.equals("wheat") || javaIdentifierStripped.equals("hay_block")) {
- interactiveTag = InteractiveTag.FEED;
- break;
- }
- case DONKEY:
- case HORSE:
- // Undead can't eat
- if (DONKEY_AND_HORSE_FOODS.contains(javaIdentifierStripped)) {
- interactiveTag = InteractiveTag.FEED;
- break;
- }
- }
- if (!entityMetadata.getFlags().getFlag(EntityFlag.BABY)) {
- // Can't ride a baby
- if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) {
- interactiveTag = InteractiveTag.RIDE_HORSE;
- } else if (!entityMetadata.getFlags().getFlag(EntityFlag.TAMED) && itemEntry.equals(ItemEntry.AIR)) {
- // Can't hide an untamed entity without having your hand empty
- interactiveTag = InteractiveTag.MOUNT;
- }
- }
- break;
- case FOX:
- if (javaIdentifierStripped.equals("sweet_berries")) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case HOGLIN:
- if (javaIdentifierStripped.equals("crimson_fungus")) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case MINECART:
- interactiveTag = InteractiveTag.RIDE_MINECART;
- break;
- case MINECART_CHEST:
- case MINECART_COMMAND_BLOCK:
- case MINECART_HOPPER:
- interactiveTag = InteractiveTag.OPEN_CONTAINER;
- break;
- case OCELOT:
- if (javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon")) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case PANDA:
- if (javaIdentifierStripped.equals("bamboo")) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case PARROT:
- if (javaIdentifierStripped.contains("seeds") || javaIdentifierStripped.equals("cookie")) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case PIG:
- if (javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot")) {
- interactiveTag = InteractiveTag.FEED;
- } else if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
- interactiveTag = InteractiveTag.MOUNT;
- }
- break;
- case PIGLIN:
- if (!entityMetadata.getFlags().getFlag(EntityFlag.BABY) && javaIdentifierStripped.equals("gold_ingot")) {
- interactiveTag = InteractiveTag.BARTER;
- }
- break;
- case RABBIT:
- if (javaIdentifierStripped.equals("dandelion") || javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("golden_carrot")) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case SHEEP:
- if (javaIdentifierStripped.equals("wheat")) {
- interactiveTag = InteractiveTag.FEED;
- } else if (!entityMetadata.getFlags().getFlag(EntityFlag.SHEARED)) {
- if (javaIdentifierStripped.equals("shears")) {
- // Shear the sheep
- interactiveTag = InteractiveTag.SHEAR;
- } else if (javaIdentifierStripped.contains("_dye")) {
- // Dye the sheep
- interactiveTag = InteractiveTag.DYE;
- }
- }
- break;
- case STRIDER:
- if (javaIdentifierStripped.equals("warped_fungus")) {
- interactiveTag = InteractiveTag.FEED;
- } else if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
- interactiveTag = InteractiveTag.RIDE_STRIDER;
- }
- break;
- case TURTLE:
- if (javaIdentifierStripped.equals("seagrass")) {
- interactiveTag = InteractiveTag.FEED;
- }
- break;
- case VILLAGER:
- if (entityMetadata.getInt(EntityData.VARIANT) != 14 && entityMetadata.getInt(EntityData.VARIANT) != 0
- && entityMetadata.getFloat(EntityData.SCALE) >= 0.75f) { // Not a nitwit, has a profession and is not a baby
- interactiveTag = InteractiveTag.TRADE;
- }
- break;
- case WANDERING_TRADER:
- interactiveTag = InteractiveTag.TRADE; // Since you can always trade with a wandering villager, presumably.
- break;
- case WOLF:
- if (javaIdentifierStripped.equals("bone") && !entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) {
- // Bone and untamed - can tame
- interactiveTag = InteractiveTag.TAME;
- } else if (WOLF_FOODS.contains(javaIdentifierStripped)) {
- // Compatible food in hand - feed
- // Sometimes just sits/stands when the wolf isn't hungry - there doesn't appear to be a way to fix this
- interactiveTag = InteractiveTag.FEED;
- } else if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) &&
- entityMetadata.getLong(EntityData.OWNER_EID) == session.getPlayerEntity().getGeyserId()) {
- // Tamed and owned by player - can sit/stand
- interactiveTag = entityMetadata.getFlags().getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
- }
- break;
- case ZOMBIE_VILLAGER:
- // We can't guarantee the existence of the weakness effect so we just always show it.
- if (javaIdentifierStripped.equals("golden_apple")) {
- interactiveTag = InteractiveTag.CURE;
- }
- break;
- default:
- break;
- }
- }
- session.getPlayerEntity().getMetadata().put(EntityData.INTERACTIVE_TAG, interactiveTag.getValue());
- session.getPlayerEntity().updateBedrockMetadata(session);
- } else {
- if (!session.getPlayerEntity().getMetadata().getString(EntityData.INTERACTIVE_TAG).isEmpty()) {
- // No interactive tag should be sent
- session.getPlayerEntity().getMetadata().remove(EntityData.INTERACTIVE_TAG);
- session.getPlayerEntity().updateBedrockMetadata(session);
- }
- }
- break;
- case OPEN_INVENTORY:
- if (!session.getInventory().isOpen()) {
- ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
- containerOpenPacket.setId((byte) 0);
- containerOpenPacket.setType(ContainerType.INVENTORY);
- containerOpenPacket.setUniqueEntityId(-1);
- containerOpenPacket.setBlockPosition(entity.getPosition().toInt());
- session.sendUpstreamPacket(containerOpenPacket);
- session.getInventory().setOpen(true);
- }
- break;
- }
- }
-
- /**
- * All interactive tags in enum form. For potential API usage.
- */
- public enum InteractiveTag {
- NONE(true),
- IGNITE_CREEPER("creeper"),
- EDIT,
- LEAVE_BOAT("exit.boat"),
- FEED,
- FISH("fishing"),
- MILK,
- MOOSHROOM_SHEAR("mooshear"),
- MOOSHROOM_MILK_STEW("moostew"),
- BOARD_BOAT("ride.boat"),
- RIDE_MINECART("ride.minecart"),
- RIDE_HORSE("ride.horse"),
- RIDE_STRIDER("ride.strider"),
- SHEAR,
- SIT,
- STAND,
- TALK,
- TAME,
- DYE,
- CURE,
- OPEN_CONTAINER("opencontainer"),
- CREATE_MAP("createMap"),
- TAKE_PICTURE("takepicture"),
- SADDLE,
- MOUNT,
- BOOST,
- WRITE,
- LEASH,
- REMOVE_LEASH("unleash"),
- NAME,
- ATTACH_CHEST("attachchest"),
- TRADE,
- POSE_ARMOR_STAND("armorstand.pose"),
- EQUIP_ARMOR_STAND("armorstand.equip"),
- READ,
- WAKE_VILLAGER("wakevillager"),
- BARTER;
-
- /**
- * The full string that should be passed on to the client.
- */
- @Getter
- private final String value;
-
- InteractiveTag(boolean isNone) {
- this.value = "";
- }
-
- InteractiveTag(String value) {
- this.value = "action.interact." + value;
- }
-
- InteractiveTag() {
- this.value = "action.interact." + name().toLowerCase();
- }
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java
deleted file mode 100644
index c5988bf0b..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.bedrock.entity.player;
-
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
-import com.nukkitx.math.vector.Vector3d;
-import com.nukkitx.math.vector.Vector3f;
-import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
-import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
-import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
-import org.geysermc.connector.common.ChatColor;
-import org.geysermc.connector.entity.Entity;
-import org.geysermc.connector.entity.PlayerEntity;
-import org.geysermc.connector.entity.type.EntityType;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
-import java.util.concurrent.TimeUnit;
-
-@Translator(packet = MovePlayerPacket.class)
-public class BedrockMovePlayerTranslator extends PacketTranslator {
-
- @Override
- public void translate(MovePlayerPacket packet, GeyserSession session) {
- PlayerEntity entity = session.getPlayerEntity();
- if (entity == null || !session.isSpawned() || session.getPendingDimSwitches().get() > 0) return;
-
- if (!session.getUpstream().isInitialized()) {
- MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket();
- moveEntityBack.setRuntimeEntityId(entity.getGeyserId());
- moveEntityBack.setPosition(entity.getPosition());
- moveEntityBack.setRotation(entity.getBedrockRotation());
- moveEntityBack.setTeleported(true);
- moveEntityBack.setOnGround(true);
- session.sendUpstreamPacketImmediately(moveEntityBack);
- return;
- }
-
- if (session.getMovementSendIfIdle() != null) {
- session.getMovementSendIfIdle().cancel(true);
- }
-
- Vector3d position = adjustBedrockPosition(packet.getPosition(), packet.isOnGround());
-
- if(!session.confirmTeleport(position)){
- return;
- }
-
- if (!isValidMove(session, packet.getMode(), entity.getPosition(), packet.getPosition())) {
- session.getConnector().getLogger().debug("Recalculating position...");
- recalculatePosition(session, entity, entity.getPosition());
- return;
- }
-
- ClientPlayerPositionRotationPacket playerPositionRotationPacket = new ClientPlayerPositionRotationPacket(
- packet.isOnGround(), position.getX(), position.getY(), position.getZ(), packet.getRotation().getY(), packet.getRotation().getX()
- );
-
- // head yaw, pitch, head yaw
- Vector3f rotation = Vector3f.from(packet.getRotation().getY(), packet.getRotation().getX(), packet.getRotation().getY());
- entity.setPosition(packet.getPosition().sub(0, EntityType.PLAYER.getOffset(), 0));
- entity.setRotation(rotation);
- entity.setOnGround(packet.isOnGround());
- // Move parrots to match if applicable
- if (entity.getLeftParrot() != null) {
- entity.getLeftParrot().moveAbsolute(session, entity.getPosition(), entity.getRotation(), true, false);
- }
- if (entity.getRightParrot() != null) {
- entity.getRightParrot().moveAbsolute(session, entity.getPosition(), entity.getRotation(), true, false);
- }
-
- /*
- boolean colliding = false;
- Position position = new Position((int) packet.getPosition().getX(),
- (int) Math.ceil(javaY * 2) / 2, (int) packet.getPosition().getZ());
-
- BlockEntry block = session.getChunkCache().getBlockAt(position);
- if (!block.getJavaIdentifier().contains("air"))
- colliding = true;
-
- if (!colliding)
- */
- session.sendDownstreamPacket(playerPositionRotationPacket);
-
- // Schedule a position send loop if the player is idle
- session.setMovementSendIfIdle(session.getConnector().getGeneralThreadPool().schedule(() -> sendPositionIfIdle(session),
- 3, TimeUnit.SECONDS));
- }
-
- /**
- * Adjust the Bedrock position before sending to the Java server to account for inaccuracies in movement between
- * the two versions.
- *
- * @param position the current Bedrock position of the client
- * @param onGround whether the Bedrock player is on the ground
- * @return the position to send to the Java server.
- */
- private Vector3d adjustBedrockPosition(Vector3f position, boolean onGround) {
- // We need to parse the float as a string since casting a float to a double causes us to
- // lose precision and thus, causes players to get stuck when walking near walls
- double javaY = position.getY() - EntityType.PLAYER.getOffset();
- if (onGround) javaY = Math.ceil(javaY * 2) / 2;
-
- return Vector3d.from(Double.parseDouble(Float.toString(position.getX())), javaY,
- Double.parseDouble(Float.toString(position.getZ())));
- }
-
- public boolean isValidMove(GeyserSession session, MovePlayerPacket.Mode mode, Vector3f currentPosition, Vector3f newPosition) {
- if (mode != MovePlayerPacket.Mode.NORMAL)
- return true;
-
- double xRange = newPosition.getX() - currentPosition.getX();
- double yRange = newPosition.getY() - currentPosition.getY();
- double zRange = newPosition.getZ() - currentPosition.getZ();
-
- if (xRange < 0)
- xRange = -xRange;
- if (yRange < 0)
- yRange = -yRange;
- if (zRange < 0)
- zRange = -zRange;
-
- if ((xRange + yRange + zRange) > 100) {
- session.getConnector().getLogger().debug(ChatColor.RED + session.getName() + " moved too quickly." +
- " current position: " + currentPosition + ", new position: " + newPosition);
-
- return false;
- }
-
- return true;
- }
-
- public void recalculatePosition(GeyserSession session, Entity entity, Vector3f currentPosition) {
- // Gravity might need to be reset...
- SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
- entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
- entityDataPacket.getMetadata().putAll(entity.getMetadata());
- session.sendUpstreamPacket(entityDataPacket);
-
- MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
- movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());
- movePlayerPacket.setPosition(entity.getPosition());
- movePlayerPacket.setRotation(entity.getBedrockRotation());
- movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN);
- session.sendUpstreamPacket(movePlayerPacket);
- }
-
- private void sendPositionIfIdle(GeyserSession session) {
- if (session.isClosed()) return;
- PlayerEntity entity = session.getPlayerEntity();
- // Recalculate in case something else changed position
- Vector3d position = adjustBedrockPosition(entity.getPosition(), entity.isOnGround());
- ClientPlayerPositionPacket packet = new ClientPlayerPositionPacket(session.getPlayerEntity().isOnGround(),
- position.getX(), position.getY(), position.getZ());
- session.sendDownstreamPacket(packet);
- session.setMovementSendIfIdle(session.getConnector().getGeneralThreadPool().schedule(() -> sendPositionIfIdle(session),
- 3, TimeUnit.SECONDS));
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/chat/MessageTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/chat/MessageTranslator.java
deleted file mode 100644
index b7e6838e4..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/chat/MessageTranslator.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.chat;
-
-import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
-import com.github.steveice10.mc.protocol.data.message.style.ChatColor;
-import com.github.steveice10.mc.protocol.data.message.style.ChatFormat;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.renderer.TranslatableComponentRenderer;
-import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
-import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
-import net.kyori.adventure.translation.TranslationRegistry;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.utils.LanguageUtils;
-
-import java.util.*;
-
-public class MessageTranslator {
-
- // These are used for handling the translations of the messages
- private static final TranslationRegistry REGISTRY = new MinecraftTranslationRegistry();
- private static final TranslatableComponentRenderer RENDERER = TranslatableComponentRenderer.usingTranslationSource(REGISTRY);
-
- // Store team colors for player names
- private static final Map TEAM_COLORS = new HashMap<>();
-
- static {
- TEAM_COLORS.put(TeamColor.BLACK, getColor(ChatColor.BLACK));
- TEAM_COLORS.put(TeamColor.DARK_BLUE, getColor(ChatColor.DARK_BLUE));
- TEAM_COLORS.put(TeamColor.DARK_GREEN, getColor(ChatColor.DARK_GREEN));
- TEAM_COLORS.put(TeamColor.DARK_AQUA, getColor(ChatColor.DARK_AQUA));
- TEAM_COLORS.put(TeamColor.DARK_RED, getColor(ChatColor.DARK_RED));
- TEAM_COLORS.put(TeamColor.DARK_PURPLE, getColor(ChatColor.DARK_PURPLE));
- TEAM_COLORS.put(TeamColor.GOLD, getColor(ChatColor.GOLD));
- TEAM_COLORS.put(TeamColor.GRAY, getColor(ChatColor.GRAY));
- TEAM_COLORS.put(TeamColor.DARK_GRAY, getColor(ChatColor.DARK_GRAY));
- TEAM_COLORS.put(TeamColor.BLUE, getColor(ChatColor.BLUE));
- TEAM_COLORS.put(TeamColor.GREEN, getColor(ChatColor.GREEN));
- TEAM_COLORS.put(TeamColor.AQUA, getColor(ChatColor.AQUA));
- TEAM_COLORS.put(TeamColor.RED, getColor(ChatColor.RED));
- TEAM_COLORS.put(TeamColor.LIGHT_PURPLE, getColor(ChatColor.LIGHT_PURPLE));
- TEAM_COLORS.put(TeamColor.YELLOW, getColor(ChatColor.YELLOW));
- TEAM_COLORS.put(TeamColor.WHITE, getColor(ChatColor.WHITE));
- TEAM_COLORS.put(TeamColor.OBFUSCATED, getFormat(ChatFormat.OBFUSCATED));
- TEAM_COLORS.put(TeamColor.BOLD, getFormat(ChatFormat.BOLD));
- TEAM_COLORS.put(TeamColor.STRIKETHROUGH, getFormat(ChatFormat.STRIKETHROUGH));
- TEAM_COLORS.put(TeamColor.ITALIC, getFormat(ChatFormat.ITALIC));
- }
-
- /**
- * Convert a Java message to the legacy format ready for bedrock
- *
- * @param message Java message
- * @param locale Locale to use for translation strings
- * @return Parsed and formatted message for bedrock
- */
- public static String convertMessage(String message, String locale) {
- Component component = GsonComponentSerializer.gson().deserialize(message);
-
- // Get a Locale from the given locale string
- Locale localeCode = Locale.forLanguageTag(locale.replace('_', '-'));
- component = RENDERER.render(component, localeCode);
-
- String legacy = LegacyComponentSerializer.legacySection().serialize(component);
-
- // Strip strikethrough and underline as they are not supported on bedrock
- legacy = legacy.replaceAll("\u00a7[mn]", "");
-
- // Make color codes reset formatting like Java
- // See https://minecraft.gamepedia.com/Formatting_codes#Usage
- legacy = legacy.replaceAll("\u00a7([0-9a-f])", "\u00a7r\u00a7$1");
- legacy = legacy.replaceAll("\u00a7r\u00a7r", "\u00a7r");
-
- return legacy;
- }
-
- public static String convertMessage(String message) {
- return convertMessage(message, LanguageUtils.getDefaultLocale());
- }
-
- /**
- * Verifies the message is valid JSON in case it's plaintext. Works around GsonComponentSeraializer not using lenient mode.
- * See https://wiki.vg/Chat for messages sent in lenient mode, and for a description on leniency.
- *
- * @param message Potentially lenient JSON message
- * @param locale Locale to use for translation strings
- * @return Bedrock formatted message
- */
- public static String convertMessageLenient(String message, String locale) {
- if (isMessage(message)) {
- return convertMessage(message, locale);
- } else {
- String convertedMessage = convertMessage(convertToJavaMessage(message), locale);
-
- // We have to do this since Adventure strips the starting reset character
- if (message.startsWith(getColor(ChatColor.RESET)) && !convertedMessage.startsWith(getColor(ChatColor.RESET))) {
- convertedMessage = getColor(ChatColor.RESET) + convertedMessage;
- }
-
- return convertedMessage;
- }
- }
-
- public static String convertMessageLenient(String message) {
- return convertMessageLenient(message, LanguageUtils.getDefaultLocale());
- }
-
- /**
- * Convert a Bedrock message string back to a format Java can understand
- *
- * @param message Message to convert
- * @return The formatted JSON string
- */
- public static String convertToJavaMessage(String message) {
- Component component = LegacyComponentSerializer.legacySection().deserialize(message);
- return GsonComponentSerializer.gson().serialize(component);
- }
-
- /**
- * Checks if the given text string is a JSON message
- *
- * @param text String to test
- * @return True if its a valid message JSON string, false if not
- */
- public static boolean isMessage(String text) {
- if (text.trim().isEmpty()) {
- return false;
- }
-
- try {
- GsonComponentSerializer.gson().deserialize(text);
- } catch (Exception ex) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Convert a {@link ChatColor} into a string for inserting into messages
- *
- * @param color {@link ChatColor} to convert
- * @return The converted color string
- */
- private static String getColor(String color) {
- String base = "\u00a7";
- switch (color) {
- case ChatColor.BLACK:
- base += "0";
- break;
- case ChatColor.DARK_BLUE:
- base += "1";
- break;
- case ChatColor.DARK_GREEN:
- base += "2";
- break;
- case ChatColor.DARK_AQUA:
- base += "3";
- break;
- case ChatColor.DARK_RED:
- base += "4";
- break;
- case ChatColor.DARK_PURPLE:
- base += "5";
- break;
- case ChatColor.GOLD:
- base += "6";
- break;
- case ChatColor.GRAY:
- base += "7";
- break;
- case ChatColor.DARK_GRAY:
- base += "8";
- break;
- case ChatColor.BLUE:
- base += "9";
- break;
- case ChatColor.GREEN:
- base += "a";
- break;
- case ChatColor.AQUA:
- base += "b";
- break;
- case ChatColor.RED:
- base += "c";
- break;
- case ChatColor.LIGHT_PURPLE:
- base += "d";
- break;
- case ChatColor.YELLOW:
- base += "e";
- break;
- case ChatColor.WHITE:
- base += "f";
- break;
- case ChatColor.RESET:
- base += "r";
- break;
- default:
- return "";
- }
-
- return base;
- }
-
- /**
- * Convert a {@link ChatFormat} into a string for inserting into messages
- *
- * @param format {@link ChatFormat} to convert
- * @return The converted chat formatting string
- */
- private static String getFormat(ChatFormat format) {
- StringBuilder str = new StringBuilder();
- String base = "\u00a7";
- switch (format) {
- case OBFUSCATED:
- base += "k";
- break;
- case BOLD:
- base += "l";
- break;
- case STRIKETHROUGH:
- base += "m";
- break;
- case UNDERLINED:
- base += "n";
- break;
- case ITALIC:
- base += "o";
- break;
- default:
- return "";
- }
-
- str.append(base);
-
- return str.toString();
- }
-
- /**
- * Convert a team color to a chat color
- *
- * @param teamColor
- * @return The chat color character
- */
- public static String toChatColor(TeamColor teamColor) {
- return TEAM_COLORS.getOrDefault(teamColor, "");
- }
-
- /**
- * Checks if the given message is over 256 characters (Java edition server chat limit) and sends a message to the user if it is
- *
- * @param message Message to check
- * @param session {@link GeyserSession} for the user
- * @return True if the message is too long, false if not
- */
- public static boolean isTooLong(String message, GeyserSession session) {
- if (message.length() > 256) {
- session.sendMessage(LanguageUtils.getPlayerLocaleString("geyser.chat.too_long", session.getLocale(), message.length()));
- return true;
- }
-
- return false;
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/effect/EffectRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/effect/EffectRegistry.java
deleted file mode 100644
index 75cab1521..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/effect/EffectRegistry.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.effect;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.github.steveice10.mc.protocol.data.game.world.effect.SoundEffect;
-import com.github.steveice10.mc.protocol.data.game.world.particle.ParticleType;
-import com.nukkitx.protocol.bedrock.data.LevelEventType;
-import com.nukkitx.protocol.bedrock.data.SoundEvent;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
-import lombok.NonNull;
-import org.geysermc.connector.GeyserConnector;
-import org.geysermc.connector.utils.FileUtils;
-
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Registry for particles and effects.
- */
-public class EffectRegistry {
-
- public static final Map SOUND_EFFECTS = new HashMap<>();
- public static final Int2ObjectMap RECORDS = new Int2ObjectOpenHashMap<>();
-
- /**
- * Java particle type to Bedrock particle ID
- * Used for area effect clouds.
- */
- private static final Object2IntMap PARTICLE_TO_ID = new Object2IntOpenHashMap<>();
- /**
- * Java particle type to Bedrock level event
- */
- private static final Map PARTICLE_TO_LEVEL_EVENT = new HashMap<>();
- /**
- * Java particle type to Bedrock namespaced string ID
- */
- private static final Map PARTICLE_TO_STRING = new HashMap<>();
-
- public static void init() {
- // no-op
- }
-
- static {
- /* Load particles */
- InputStream particleStream = FileUtils.getResource("mappings/particles.json");
- JsonNode particleEntries;
- try {
- particleEntries = GeyserConnector.JSON_MAPPER.readTree(particleStream);
- } catch (Exception e) {
- throw new AssertionError("Unable to load particle map", e);
- }
-
- Iterator> particlesIterator = particleEntries.fields();
- try {
- while (particlesIterator.hasNext()) {
- Map.Entry entry = particlesIterator.next();
- JsonNode bedrockId = entry.getValue().get("bedrockId");
- JsonNode bedrockIdNumeric = entry.getValue().get("bedrockNumericId");
- JsonNode eventType = entry.getValue().get("eventType");
- if (bedrockIdNumeric != null) {
- PARTICLE_TO_ID.put(ParticleType.valueOf(entry.getKey().toUpperCase()), bedrockIdNumeric.asInt());
- }
- if (bedrockId != null) {
- PARTICLE_TO_STRING.put(ParticleType.valueOf(entry.getKey().toUpperCase()), bedrockId.asText());
- }
- if (eventType != null) {
- PARTICLE_TO_LEVEL_EVENT.put(ParticleType.valueOf(entry.getKey().toUpperCase()), LevelEventType.valueOf(eventType.asText().toUpperCase()));
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- /* Load effects */
- InputStream effectsStream = FileUtils.getResource("mappings/effects.json");
- JsonNode effects;
- try {
- effects = GeyserConnector.JSON_MAPPER.readTree(effectsStream);
- } catch (Exception e) {
- throw new AssertionError("Unable to load effects mappings", e);
- }
-
- Iterator> effectsIterator = effects.fields();
- while (effectsIterator.hasNext()) {
- Map.Entry entry = effectsIterator.next();
- JsonNode node = entry.getValue();
- try {
- String type = node.get("type").asText();
- SoundEffect javaEffect = null;
- Effect effect = null;
- switch (type) {
- case "soundLevel": {
- javaEffect = SoundEffect.valueOf(entry.getKey());
- LevelEventType levelEventType = LevelEventType.valueOf(node.get("name").asText());
- int data = node.has("data") ? node.get("data").intValue() : 0;
- effect = new SoundLevelEffect(levelEventType, data);
- break;
- }
- case "soundEvent": {
- javaEffect = SoundEffect.valueOf(entry.getKey());
- SoundEvent soundEvent = SoundEvent.valueOf(node.get("name").asText());
- String identifier = node.has("identifier") ? node.get("identifier").asText() : "";
- int extraData = node.has("extraData") ? node.get("extraData").intValue() : -1;
- effect = new SoundEventEffect(soundEvent, identifier, extraData);
- break;
- }
- case "playSound": {
- javaEffect = SoundEffect.valueOf(entry.getKey());
- String name = node.get("name").asText();
- float volume = node.has("volume") ? node.get("volume").floatValue() : 1.0f;
- boolean pitchSub = node.has("pitch_sub") ? node.get("pitch_sub").booleanValue() : false;
- float pitchMul = node.has("pitch_mul") ? node.get("pitch_mul").floatValue() : 1.0f;
- float pitchAdd = node.has("pitch_add") ? node.get("pitch_add").floatValue() : 0.0f;
- boolean relative = node.has("relative") ? node.get("relative").booleanValue() : true;
- effect = new PlaySoundEffect(name, volume, pitchSub, pitchMul, pitchAdd, relative);
- break;
- }
- case "record": {
- JsonNode records = entry.getValue().get("records");
- Iterator> recordsIterator = records.fields();
- while (recordsIterator.hasNext()) {
- Map.Entry recordEntry = recordsIterator.next();
- RECORDS.put(Integer.parseInt(recordEntry.getKey()), SoundEvent.valueOf(recordEntry.getValue().asText()));
- }
- break;
- }
- }
- if (javaEffect != null) {
- SOUND_EFFECTS.put(javaEffect, effect);
- }
- } catch (Exception e) {
- GeyserConnector.getInstance().getLogger().warning("Failed to map sound effect " + entry.getKey() + " : " + e.toString());
- }
- }
- }
-
- /**
- * @param type the Java particle to search for
- * @return the Bedrock integer ID of the particle, or -1 if it does not exist
- */
- public static int getParticleId(@NonNull ParticleType type) {
- return PARTICLE_TO_ID.getOrDefault(type, -1);
- }
-
- /**
- * @param type the Java particle to search for
- * @return the level event equivalent Bedrock particle
- */
- public static LevelEventType getParticleLevelEventType(@NonNull ParticleType type) {
- return PARTICLE_TO_LEVEL_EVENT.getOrDefault(type, null);
- }
-
- /**
- * @param type the Java particle to search for
- * @return the namespaced ID equivalent for Bedrock
- */
- public static String getParticleString(@NonNull ParticleType type) {
- return PARTICLE_TO_STRING.getOrDefault(type, null);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/effect/PlaySoundEffect.java b/connector/src/main/java/org/geysermc/connector/network/translators/effect/PlaySoundEffect.java
deleted file mode 100644
index c82bca332..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/effect/PlaySoundEffect.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.effect;
-
-import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerPlayEffectPacket;
-import com.nukkitx.math.vector.Vector3f;
-import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
-import lombok.Value;
-import org.geysermc.connector.network.session.GeyserSession;
-
-import java.util.Random;
-import java.util.concurrent.ThreadLocalRandom;
-
-@Value
-public class PlaySoundEffect implements Effect {
- /**
- * Bedrock playsound identifier
- */
- String name;
-
- /**
- * Volume of the sound
- */
- float volume;
-
- /**
- * If true, the initial value used for random pitch is the difference between two random floats.
- * If false, it is a single random float
- */
- boolean pitchSub;
-
- /**
- * Multiplier for random pitch value
- */
- float pitchMul;
-
- /**
- * Constant addition to random pitch value after multiplier
- */
- float pitchAdd;
-
- /**
- * True if the sound is meant to be played in 3d space
- */
- boolean relative;
-
- @Override
- public void handleEffectPacket(GeyserSession session, ServerPlayEffectPacket packet) {
- Random rand = ThreadLocalRandom.current();
- PlaySoundPacket playSoundPacket = new PlaySoundPacket();
- playSoundPacket.setSound(name);
- playSoundPacket.setPosition(!relative ? session.getPlayerEntity().getPosition() : Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()).add(0.5f, 0.5f, 0.5f));
- playSoundPacket.setVolume(volume);
- playSoundPacket.setPitch((pitchSub ? (rand.nextFloat() - rand.nextFloat()) : rand.nextFloat()) * pitchMul + pitchAdd); //replicates java client randomness
- session.sendUpstreamPacket(playSoundPacket);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/effect/SoundEventEffect.java b/connector/src/main/java/org/geysermc/connector/network/translators/effect/SoundEventEffect.java
deleted file mode 100644
index 77641e37f..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/effect/SoundEventEffect.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.effect;
-
-import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerPlayEffectPacket;
-import com.nukkitx.math.vector.Vector3f;
-import com.nukkitx.protocol.bedrock.data.SoundEvent;
-import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
-import lombok.Value;
-import org.geysermc.connector.network.session.GeyserSession;
-
-@Value
-public class SoundEventEffect implements Effect {
- /**
- * Bedrock sound event
- */
- SoundEvent soundEvent;
-
- /**
- * Entity identifier. Usually an empty string
- */
- String identifier;
-
- /**
- * Extra data. Usually -1
- */
- int extraData;
-
- @Override
- public void handleEffectPacket(GeyserSession session, ServerPlayEffectPacket packet) {
- LevelSoundEventPacket levelSoundEvent = new LevelSoundEventPacket();
- levelSoundEvent.setSound(soundEvent);
- levelSoundEvent.setIdentifier(identifier);
- levelSoundEvent.setExtraData(extraData);
- levelSoundEvent.setRelativeVolumeDisabled(packet.isBroadcast());
- levelSoundEvent.setPosition(Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()).add(0.5f, 0.5f, 0.5f));
- levelSoundEvent.setBabySound(false);
- session.sendUpstreamPacket(levelSoundEvent);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java
deleted file mode 100644
index ab266faef..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory;
-
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket;
-import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
-import com.google.gson.JsonSyntaxException;
-import com.nukkitx.nbt.NbtMap;
-import com.nukkitx.protocol.bedrock.data.inventory.*;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
-import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class AnvilInventoryTranslator extends BlockInventoryTranslator {
- public AnvilInventoryTranslator() {
- super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL, new CursorInventoryUpdater());
- }
-
- @Override
- public int bedrockSlotToJava(InventoryActionData action) {
- if (action.getSource().getContainerId() == ContainerId.UI) {
- switch (action.getSlot()) {
- case 1:
- return 0;
- case 2:
- return 1;
- case 50:
- return 2;
- }
- }
- if (action.getSource().getContainerId() == ContainerId.ANVIL_RESULT) {
- return 2;
- }
- return super.bedrockSlotToJava(action);
- }
-
- @Override
- public int javaSlotToBedrock(int slot) {
- switch (slot) {
- case 0:
- return 1;
- case 1:
- return 2;
- case 2:
- return 50;
- }
- return super.javaSlotToBedrock(slot);
- }
-
- @Override
- public SlotType getSlotType(int javaSlot) {
- if (javaSlot == 2)
- return SlotType.OUTPUT;
- return SlotType.NORMAL;
- }
-
- @Override
- public void translateActions(GeyserSession session, Inventory inventory, List actions) {
- InventoryActionData anvilResult = null;
- InventoryActionData anvilInput = null;
- for (InventoryActionData action : actions) {
- if (action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL) {
- //useless packet
- return;
- } else if (action.getSource().getContainerId() == ContainerId.ANVIL_RESULT) {
- anvilResult = action;
- } else if (bedrockSlotToJava(action) == 0) {
- anvilInput = action;
- }
- }
- ItemData itemName = null;
- if (anvilResult != null) {
- itemName = anvilResult.getFromItem();
- } else if (anvilInput != null) {
- itemName = anvilInput.getToItem();
- }
- if (itemName != null) {
- String rename;
- NbtMap tag = itemName.getTag();
- if (tag != null && tag.containsKey("display")) {
- String name = tag.getCompound("display").getString("Name");
- try {
- Component component = GsonComponentSerializer.gson().deserialize(name);
- rename = LegacyComponentSerializer.legacySection().serialize(component);
- } catch (JsonSyntaxException e) {
- rename = name;
- }
- } else {
- rename = "";
- }
- ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename);
- session.sendDownstreamPacket(renameItemPacket);
- }
- if (anvilResult != null) {
- //Strip unnecessary actions
- List strippedActions = actions.stream()
- .filter(action -> action.getSource().getContainerId() == ContainerId.ANVIL_RESULT
- || (action.getSource().getType() == InventorySource.Type.CONTAINER
- && !(action.getSource().getContainerId() == ContainerId.UI && action.getSlot() != 0)))
- .collect(Collectors.toList());
- super.translateActions(session, inventory, strippedActions);
- return;
- }
-
- super.translateActions(session, inventory, actions);
- }
-
- @Override
- public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
- if (slot == 0) {
- ItemStack item = inventory.getItem(slot);
- if (item != null) {
- String rename;
- CompoundTag tag = item.getNbt();
- if (tag != null) {
- CompoundTag displayTag = tag.get("display");
- if (displayTag != null && displayTag.contains("Name")) {
- String itemName = displayTag.get("Name").getValue().toString();
- try {
- Component component = GsonComponentSerializer.gson().deserialize(itemName);
- rename = LegacyComponentSerializer.legacySection().serialize(component);
- } catch (JsonSyntaxException e) {
- rename = itemName;
- }
- } else {
- rename = "";
- }
- } else {
- rename = "";
- }
- ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename);
- session.sendDownstreamPacket(renameItemPacket);
- }
- }
- super.updateSlot(session, inventory, slot);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java
deleted file mode 100644
index b260565b8..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory;
-
-import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
-import com.nukkitx.protocol.bedrock.data.inventory.InventorySource;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
-import org.geysermc.connector.utils.InventoryUtils;
-
-import java.util.List;
-
-public class CraftingInventoryTranslator extends BlockInventoryTranslator {
- public CraftingInventoryTranslator() {
- super(10, "minecraft:crafting_table", ContainerType.WORKBENCH, new CursorInventoryUpdater());
- }
-
- @Override
- public int bedrockSlotToJava(InventoryActionData action) {
- if (action.getSlot() == 50) {
- // Slot 50 is used for crafting with a controller.
- return 0;
- }
-
- if (action.getSource().getContainerId() == ContainerId.UI) {
- int slotnum = action.getSlot();
- if (slotnum >= 32 && 42 >= slotnum) {
- return slotnum - 31;
- }
- }
- return super.bedrockSlotToJava(action);
- }
-
- @Override
- public int javaSlotToBedrock(int slot) {
- if (slot < size) {
- return slot == 0 ? 50 : slot + 31;
- }
- return super.javaSlotToBedrock(slot);
- }
-
- @Override
- public SlotType getSlotType(int javaSlot) {
- if (javaSlot == 0)
- return SlotType.OUTPUT;
- return SlotType.NORMAL;
- }
-
- @Override
- public void translateActions(GeyserSession session, Inventory inventory, List actions) {
- if (session.getGameMode() == GameMode.CREATIVE) {
- for (InventoryActionData action : actions) {
- if (action.getSource().getType() == InventorySource.Type.CREATIVE) {
- updateInventory(session, inventory);
- InventoryUtils.updateCursor(session);
- return;
- }
- }
- }
- super.translateActions(session, inventory, actions);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java
deleted file mode 100644
index 20a47fd02..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory;
-
-import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientClickWindowButtonPacket;
-import com.nukkitx.nbt.NbtMap;
-import com.nukkitx.nbt.NbtMapBuilder;
-import com.nukkitx.nbt.NbtType;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
-import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
-import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket;
-import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
-import org.geysermc.connector.common.ChatColor;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
-import org.geysermc.connector.network.translators.item.ItemRegistry;
-import org.geysermc.connector.network.translators.item.ItemTranslator;
-import org.geysermc.connector.utils.InventoryUtils;
-import org.geysermc.connector.utils.LocaleUtils;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A temporary reconstruction of the enchantment table UI until our inventory rewrite is complete.
- * The enchantment table on Bedrock without server authoritative inventories doesn't tell us which button is pressed
- * when selecting an enchantment.
- */
-public class EnchantmentInventoryTranslator extends BlockInventoryTranslator {
-
- private static final int DYE_ID = ItemRegistry.getItemEntry("minecraft:lapis_lazuli").getBedrockId();
- private static final int ENCHANTED_BOOK_ID = ItemRegistry.getItemEntry("minecraft:enchanted_book").getBedrockId();
-
- public EnchantmentInventoryTranslator(InventoryUpdater updater) {
- super(2, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, updater);
- }
-
- @Override
- public void translateActions(GeyserSession session, Inventory inventory, List actions) {
- for (InventoryActionData action : actions) {
- if (action.getSource().getContainerId() == inventory.getId()) {
- // This is the hopper UI
- switch (action.getSlot()) {
- case 1:
- // Don't allow the slot to be put through if the item isn't lapis
- if ((action.getToItem().getId() != DYE_ID) && action.getToItem() != ItemData.AIR) {
- updateInventory(session, inventory);
- InventoryUtils.updateCursor(session);
- return;
- }
- break;
- case 2:
- case 3:
- case 4:
- // The books here act as buttons
- ClientClickWindowButtonPacket packet = new ClientClickWindowButtonPacket(inventory.getId(), action.getSlot() - 2);
- session.sendDownstreamPacket(packet);
- updateInventory(session, inventory);
- InventoryUtils.updateCursor(session);
- return;
- default:
- break;
- }
- }
- }
-
- super.translateActions(session, inventory, actions);
- }
-
- @Override
- public void updateInventory(GeyserSession session, Inventory inventory) {
- super.updateInventory(session, inventory);
- ItemData[] items = new ItemData[5];
- items[0] = ItemTranslator.translateToBedrock(session, inventory.getItem(0));
- items[1] = ItemTranslator.translateToBedrock(session, inventory.getItem(1));
- for (int i = 0; i < 3; i++) {
- items[i + 2] = session.getEnchantmentSlotData()[i].getItem() != null ? session.getEnchantmentSlotData()[i].getItem() : createEnchantmentBook();
- }
-
- InventoryContentPacket contentPacket = new InventoryContentPacket();
- contentPacket.setContainerId(inventory.getId());
- contentPacket.setContents(items);
- session.sendUpstreamPacket(contentPacket);
- }
-
- @Override
- public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) {
- int bookSlotToUpdate;
- switch (key) {
- case 0:
- case 1:
- case 2:
- // Experience required
- bookSlotToUpdate = key;
- session.getEnchantmentSlotData()[bookSlotToUpdate].setExperienceRequired(value);
- break;
- case 4:
- case 5:
- case 6:
- // Enchantment name
- bookSlotToUpdate = key - 4;
- if (value != -1) {
- session.getEnchantmentSlotData()[bookSlotToUpdate].setEnchantmentType(EnchantmentTableEnchantments.values()[value - 1]);
- } else {
- // -1 means no enchantment specified
- session.getEnchantmentSlotData()[bookSlotToUpdate].setEnchantmentType(null);
- }
- break;
- case 7:
- case 8:
- case 9:
- // Enchantment level
- bookSlotToUpdate = key - 7;
- session.getEnchantmentSlotData()[bookSlotToUpdate].setEnchantmentLevel(value);
- break;
- default:
- return;
- }
- updateEnchantmentBook(session, inventory, bookSlotToUpdate);
- }
-
- @Override
- public void openInventory(GeyserSession session, Inventory inventory) {
- super.openInventory(session, inventory);
- for (int i = 0; i < session.getEnchantmentSlotData().length; i++) {
- session.getEnchantmentSlotData()[i] = new EnchantmentSlotData();
- }
- }
-
- @Override
- public void closeInventory(GeyserSession session, Inventory inventory) {
- super.closeInventory(session, inventory);
- Arrays.fill(session.getEnchantmentSlotData(), null);
- }
-
- private ItemData createEnchantmentBook() {
- NbtMapBuilder root = NbtMap.builder();
- NbtMapBuilder display = NbtMap.builder();
-
- display.putString("Name", ChatColor.RESET + "No Enchantment");
-
- root.put("display", display.build());
- return ItemData.of(ENCHANTED_BOOK_ID, (short) 0, 1, root.build());
- }
-
- private void updateEnchantmentBook(GeyserSession session, Inventory inventory, int slot) {
- NbtMapBuilder root = NbtMap.builder();
- NbtMapBuilder display = NbtMap.builder();
- EnchantmentSlotData data = session.getEnchantmentSlotData()[slot];
- if (data.getEnchantmentType() != null) {
- display.putString("Name", ChatColor.ITALIC + data.getEnchantmentType().toString(session) +
- (data.getEnchantmentLevel() != -1 ? " " + toRomanNumeral(session, data.getEnchantmentLevel()) : "") + "?");
- } else {
- display.putString("Name", ChatColor.RESET + "No Enchantment");
- }
-
- display.putList("Lore", NbtType.STRING, Collections.singletonList(ChatColor.DARK_GRAY + data.getExperienceRequired() + "xp"));
- root.put("display", display.build());
- ItemData book = ItemData.of(ENCHANTED_BOOK_ID, (short) 0, 1, root.build());
-
- InventorySlotPacket slotPacket = new InventorySlotPacket();
- slotPacket.setContainerId(inventory.getId());
- slotPacket.setSlot(slot + 2);
- slotPacket.setItem(book);
- session.sendUpstreamPacket(slotPacket);
- data.setItem(book);
- }
-
- private String toRomanNumeral(GeyserSession session, int level) {
- return LocaleUtils.getLocaleString("enchantment.level." + level,
- session.getLocale());
- }
-
- /**
- * Stores the data of each slot in an enchantment table
- */
- @NoArgsConstructor
- @Getter
- @Setter
- @ToString
- public static class EnchantmentSlotData {
- private EnchantmentTableEnchantments enchantmentType = null;
- private int enchantmentLevel = 0;
- private int experienceRequired = 0;
- private ItemData item;
- }
-
- /**
- * Classifies enchantments by Java order
- */
- public enum EnchantmentTableEnchantments {
- PROTECTION,
- FIRE_PROTECTION,
- FEATHER_FALLING,
- BLAST_PROTECTION,
- PROJECTILE_PROTECTION,
- RESPIRATION,
- AQUA_AFFINITY,
- THORNS,
- DEPTH_STRIDER,
- FROST_WALKER,
- BINDING_CURSE,
- SHARPNESS,
- SMITE,
- BANE_OF_ARTHROPODS,
- KNOCKBACK,
- FIRE_ASPECT,
- LOOTING,
- SWEEPING,
- EFFICIENCY,
- SILK_TOUCH,
- UNBREAKING,
- FORTUNE,
- POWER,
- PUNCH,
- FLAME,
- INFINITY,
- LUCK_OF_THE_SEA,
- LURE,
- LOYALTY,
- IMPALING,
- RIPTIDE,
- CHANNELING,
- MENDING,
- VANISHING_CURSE, // After this is not documented
- MULTISHOT,
- PIERCING,
- QUICK_CHARGE,
- SOUL_SPEED;
-
- public String toString(GeyserSession session) {
- return LocaleUtils.getLocaleString("enchantment.minecraft." + this.toString().toLowerCase(),
- session.getLocale());
- }
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java
deleted file mode 100644
index 4b4a12465..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory;
-
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
-import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
-
-public class GrindstoneInventoryTranslator extends BlockInventoryTranslator {
-
- public GrindstoneInventoryTranslator() {
- super(3, "minecraft:grindstone[face=floor,facing=north]", ContainerType.GRINDSTONE, new CursorInventoryUpdater());
- }
-
- @Override
- public int bedrockSlotToJava(InventoryActionData action) {
- final int slot = super.bedrockSlotToJava(action);
- if (action.getSource().getContainerId() == ContainerId.UI) {
- switch (slot) {
- case 16:
- return 0;
- case 17:
- return 1;
- case 50:
- return 2;
- default:
- return slot;
- }
- } return slot;
- }
-
- @Override
- public int javaSlotToBedrock(int slot) {
- switch (slot) {
- case 0:
- return 16;
- case 1:
- return 17;
- case 2:
- return 50;
- }
- return super.javaSlotToBedrock(slot);
- }
-
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java
deleted file mode 100644
index 3016871f0..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory;
-
-import com.github.steveice10.mc.protocol.data.game.window.WindowType;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
-import lombok.AllArgsConstructor;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater;
-import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@AllArgsConstructor
-public abstract class InventoryTranslator {
-
- public static final Map INVENTORY_TRANSLATORS = new HashMap() {
- {
- put(null, new PlayerInventoryTranslator()); //player inventory
- put(WindowType.GENERIC_9X1, new SingleChestInventoryTranslator(9));
- put(WindowType.GENERIC_9X2, new SingleChestInventoryTranslator(18));
- put(WindowType.GENERIC_9X3, new SingleChestInventoryTranslator(27));
- put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36));
- put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45));
- put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54));
- put(WindowType.BREWING_STAND, new BrewingInventoryTranslator());
- put(WindowType.ANVIL, new AnvilInventoryTranslator());
- put(WindowType.CRAFTING, new CraftingInventoryTranslator());
- //put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator()); //FIXME
- put(WindowType.MERCHANT, new MerchantInventoryTranslator());
- //put(WindowType.SMITHING, new SmithingInventoryTranslator()); //TODO for server authoritative inventories
-
- InventoryTranslator furnace = new FurnaceInventoryTranslator();
- put(WindowType.FURNACE, furnace);
- put(WindowType.BLAST_FURNACE, furnace);
- put(WindowType.SMOKER, furnace);
-
- InventoryUpdater containerUpdater = new ContainerInventoryUpdater();
- put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator(containerUpdater)); //TODO
- put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER, containerUpdater));
- put(WindowType.HOPPER, new BlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, containerUpdater));
- put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, "minecraft:shulker_box[facing=north]", ContainerType.CONTAINER, containerUpdater));
- //put(WindowType.BEACON, new BlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO
- }
- };
-
- public final int size;
-
- public abstract void prepareInventory(GeyserSession session, Inventory inventory);
- public abstract void openInventory(GeyserSession session, Inventory inventory);
- public abstract void closeInventory(GeyserSession session, Inventory inventory);
- public abstract void updateProperty(GeyserSession session, Inventory inventory, int key, int value);
- public abstract void updateInventory(GeyserSession session, Inventory inventory);
- public abstract void updateSlot(GeyserSession session, Inventory inventory, int slot);
- public abstract int bedrockSlotToJava(InventoryActionData action);
- public abstract int javaSlotToBedrock(int slot);
- public abstract SlotType getSlotType(int javaSlot);
- public abstract void translateActions(GeyserSession session, Inventory inventory, List actions);
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/MerchantInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/MerchantInventoryTranslator.java
deleted file mode 100644
index 25fdae688..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/MerchantInventoryTranslator.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory;
-
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
-import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
-import com.nukkitx.protocol.bedrock.data.inventory.InventorySource;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
-import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
-
-import java.util.List;
-
-public class MerchantInventoryTranslator extends BaseInventoryTranslator {
-
- private final InventoryUpdater updater;
-
- public MerchantInventoryTranslator() {
- super(3);
- this.updater = new CursorInventoryUpdater();
- }
-
- @Override
- public int javaSlotToBedrock(int slot) {
- switch (slot) {
- case 0:
- return 4;
- case 1:
- return 5;
- case 2:
- return 50;
- }
- return super.javaSlotToBedrock(slot);
- }
-
- @Override
- public int bedrockSlotToJava(InventoryActionData action) {
- switch (action.getSource().getContainerId()) {
- case ContainerId.UI:
- switch (action.getSlot()) {
- case 4:
- return 0;
- case 5:
- return 1;
- case 50:
- return 2;
- }
- break;
- case -28: // Trading 1?
- return 0;
- case -29: // Trading 2?
- return 1;
- case -30: // Trading Output?
- return 2;
- }
- return super.bedrockSlotToJava(action);
- }
-
- @Override
- public SlotType getSlotType(int javaSlot) {
- if (javaSlot == 2) {
- return SlotType.OUTPUT;
- }
- return SlotType.NORMAL;
- }
-
- @Override
- public void prepareInventory(GeyserSession session, Inventory inventory) {
-
- }
-
- @Override
- public void openInventory(GeyserSession session, Inventory inventory) {
-
- }
-
- @Override
- public void closeInventory(GeyserSession session, Inventory inventory) {
- session.setLastInteractedVillagerEid(-1);
- session.setVillagerTrades(null);
- }
-
- @Override
- public void updateInventory(GeyserSession session, Inventory inventory) {
- updater.updateInventory(this, session, inventory);
- }
-
- @Override
- public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
- updater.updateSlot(this, session, inventory, slot);
- }
-
- @Override
- public void translateActions(GeyserSession session, Inventory inventory, List actions) {
- if (actions.stream().anyMatch(a -> a.getSource().getContainerId() == -31)) {
- return;
- }
-
- super.translateActions(session, inventory, actions);
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java
deleted file mode 100644
index 7d7673c4e..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.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.packet.ingame.client.window.ClientCreativeInventoryActionPacket;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
-import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
-import com.nukkitx.protocol.bedrock.data.inventory.InventorySource;
-import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
-import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket;
-import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.action.InventoryActionDataTranslator;
-import org.geysermc.connector.network.translators.item.ItemTranslator;
-import org.geysermc.connector.utils.InventoryUtils;
-import org.geysermc.connector.utils.LanguageUtils;
-
-import java.util.List;
-
-public class PlayerInventoryTranslator extends InventoryTranslator {
- private static final ItemData UNUSUABLE_CRAFTING_SPACE_BLOCK = InventoryUtils.createUnusableSpaceBlock(LanguageUtils.getLocaleStringLog("geyser.inventory.unusable_item.creative"));
-
- public PlayerInventoryTranslator() {
- super(46);
- }
-
- @Override
- public void updateInventory(GeyserSession session, Inventory inventory) {
- updateCraftingGrid(session, inventory);
-
- InventoryContentPacket inventoryContentPacket = new InventoryContentPacket();
- inventoryContentPacket.setContainerId(ContainerId.INVENTORY);
- ItemData[] contents = new ItemData[36];
- // Inventory
- for (int i = 9; i < 36; i++) {
- contents[i] = ItemTranslator.translateToBedrock(session, inventory.getItem(i));
- }
- // Hotbar
- for (int i = 36; i < 45; i++) {
- contents[i - 36] = ItemTranslator.translateToBedrock(session, inventory.getItem(i));
- }
- inventoryContentPacket.setContents(contents);
- session.sendUpstreamPacket(inventoryContentPacket);
-
- // Armor
- InventoryContentPacket armorContentPacket = new InventoryContentPacket();
- armorContentPacket.setContainerId(ContainerId.ARMOR);
- contents = new ItemData[4];
- for (int i = 5; i < 9; i++) {
- contents[i - 5] = ItemTranslator.translateToBedrock(session, inventory.getItem(i));
- }
- armorContentPacket.setContents(contents);
- session.sendUpstreamPacket(armorContentPacket);
-
- // Offhand
- InventoryContentPacket offhandPacket = new InventoryContentPacket();
- offhandPacket.setContainerId(ContainerId.OFFHAND);
- offhandPacket.setContents(new ItemData[]{ItemTranslator.translateToBedrock(session, inventory.getItem(45))});
- session.sendUpstreamPacket(offhandPacket);
- }
-
- /**
- * Update the crafting grid for the player to hide/show the barriers in the creative inventory
- * @param session Session of the player
- * @param inventory Inventory of the player
- */
- public static void updateCraftingGrid(GeyserSession session, Inventory inventory) {
- // Crafting grid
- for (int i = 1; i < 5; i++) {
- InventorySlotPacket slotPacket = new InventorySlotPacket();
- slotPacket.setContainerId(ContainerId.UI);
- slotPacket.setSlot(i + 27);
-
- if (session.getGameMode() == GameMode.CREATIVE) {
- slotPacket.setItem(UNUSUABLE_CRAFTING_SPACE_BLOCK);
- }else{
- slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(i)));
- }
-
- session.sendUpstreamPacket(slotPacket);
- }
- }
-
- @Override
- public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
- if (slot >= 1 && slot <= 44) {
- InventorySlotPacket slotPacket = new InventorySlotPacket();
- if (slot >= 9) {
- slotPacket.setContainerId(ContainerId.INVENTORY);
- if (slot >= 36) {
- slotPacket.setSlot(slot - 36);
- } else {
- slotPacket.setSlot(slot);
- }
- } else if (slot >= 5) {
- slotPacket.setContainerId(ContainerId.ARMOR);
- slotPacket.setSlot(slot - 5);
- } else {
- slotPacket.setContainerId(ContainerId.UI);
- slotPacket.setSlot(slot + 27);
- }
- slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(slot)));
- session.sendUpstreamPacket(slotPacket);
- } else if (slot == 45) {
- InventoryContentPacket offhandPacket = new InventoryContentPacket();
- offhandPacket.setContainerId(ContainerId.OFFHAND);
- offhandPacket.setContents(new ItemData[]{ItemTranslator.translateToBedrock(session, inventory.getItem(slot))});
- session.sendUpstreamPacket(offhandPacket);
- }
- }
-
- @Override
- public int bedrockSlotToJava(InventoryActionData action) {
- int slotnum = action.getSlot();
- switch (action.getSource().getContainerId()) {
- case ContainerId.INVENTORY:
- // Inventory
- if (slotnum >= 9 && slotnum <= 35) {
- return slotnum;
- }
- // Hotbar
- if (slotnum >= 0 && slotnum <= 8) {
- return slotnum + 36;
- }
- break;
- case ContainerId.ARMOR:
- if (slotnum >= 0 && slotnum <= 3) {
- return slotnum + 5;
- }
- break;
- case ContainerId.OFFHAND:
- return 45;
- case ContainerId.UI:
- if (slotnum >= 28 && 31 >= slotnum) {
- return slotnum - 27;
- }
- break;
- case ContainerId.CRAFTING_RESULT:
- return 0;
- }
- return slotnum;
- }
-
- @Override
- public int javaSlotToBedrock(int slot) {
- return slot;
- }
-
- @Override
- public SlotType getSlotType(int javaSlot) {
- if (javaSlot == 0)
- return SlotType.OUTPUT;
- return SlotType.NORMAL;
- }
-
- @Override
- public void translateActions(GeyserSession session, Inventory inventory, List actions) {
- if (session.getGameMode() == GameMode.CREATIVE) {
- //crafting grid is not visible in creative mode in java edition
- for (InventoryActionData action : actions) {
- if (action.getSource().getContainerId() == ContainerId.UI && (action.getSlot() >= 28 && 31 >= action.getSlot())) {
- updateInventory(session, inventory);
- InventoryUtils.updateCursor(session);
- return;
- }
- }
-
- ItemStack javaItem;
- for (InventoryActionData action : actions) {
- switch (action.getSource().getContainerId()) {
- case ContainerId.INVENTORY:
- case ContainerId.ARMOR:
- case ContainerId.OFFHAND:
- int javaSlot = bedrockSlotToJava(action);
- if (action.getToItem().getId() == 0) {
- javaItem = new ItemStack(-1, 0, null);
- } else {
- javaItem = ItemTranslator.translateToJava(action.getToItem());
- }
- ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, javaItem);
- session.sendDownstreamPacket(creativePacket);
- inventory.setItem(javaSlot, javaItem);
- break;
- case ContainerId.UI:
- if (action.getSlot() == 0) {
- session.getInventory().setCursor(ItemTranslator.translateToJava(action.getToItem()));
- }
- break;
- case ContainerId.NONE:
- if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION
- && action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) {
- javaItem = ItemTranslator.translateToJava(action.getToItem());
- ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, javaItem);
- session.sendDownstreamPacket(creativeDropPacket);
- }
- break;
- }
- }
- return;
- }
-
- InventoryActionDataTranslator.translate(this, session, inventory, actions);
- }
-
- @Override
- public void prepareInventory(GeyserSession session, Inventory inventory) {
- }
-
- @Override
- public void openInventory(GeyserSession session, Inventory inventory) {
- }
-
- @Override
- public void closeInventory(GeyserSession session, Inventory inventory) {
- }
-
- @Override
- public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) {
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SmithingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SmithingInventoryTranslator.java
deleted file mode 100644
index f7f0acd8c..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SmithingInventoryTranslator.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory;
-
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
-import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
-
-public class SmithingInventoryTranslator extends BlockInventoryTranslator {
-
- public SmithingInventoryTranslator() {
- super(3, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, new CursorInventoryUpdater());
- }
-
- @Override
- public int bedrockSlotToJava(InventoryActionData action) {
- final int slot = super.bedrockSlotToJava(action);
- if (action.getSource().getContainerId() == ContainerId.UI) {
- switch (slot) {
- case 51:
- return 0;
- case 52:
- return 1;
- case 50:
- return 2;
- default:
- return slot;
- }
- } return slot;
- }
-
- @Override
- public int javaSlotToBedrock(int slot) {
- switch (slot) {
- case 0:
- return 51;
- case 1:
- return 52;
- case 2:
- return 50;
- }
- return super.javaSlotToBedrock(slot);
- }
-
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/Click.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/Click.java
deleted file mode 100644
index 1fdfa3640..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/Click.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory.action;
-
-import com.github.steveice10.mc.protocol.data.game.window.ClickItemParam;
-import com.github.steveice10.mc.protocol.data.game.window.WindowActionParam;
-import lombok.AllArgsConstructor;
-
-@AllArgsConstructor
-enum Click {
- LEFT(ClickItemParam.LEFT_CLICK),
- RIGHT(ClickItemParam.RIGHT_CLICK);
-
- public final WindowActionParam actionParam;
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java
deleted file mode 100644
index a9c1eddca..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory.action;
-
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.mc.protocol.data.game.window.WindowAction;
-import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientConfirmTransactionPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.inventory.PlayerInventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
-import org.geysermc.connector.network.translators.inventory.SlotType;
-import org.geysermc.connector.utils.InventoryUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-
-class ClickPlan {
- private final List plan = new ArrayList<>();
-
- public void add(Click click, int slot) {
- plan.add(new ClickAction(click, slot));
- }
-
- public void execute(GeyserSession session, InventoryTranslator translator, Inventory inventory, boolean refresh) {
- PlayerInventory playerInventory = session.getInventory();
- ListIterator planIter = plan.listIterator();
- while (planIter.hasNext()) {
- final ClickAction action = planIter.next();
- final ItemStack cursorItem = playerInventory.getCursor();
- final ItemStack clickedItem = inventory.getItem(action.slot);
- final short actionId = (short) inventory.getTransactionId().getAndIncrement();
-
- //TODO: stop relying on refreshing the inventory for crafting to work properly
- if (translator.getSlotType(action.slot) != SlotType.NORMAL)
- refresh = true;
-
- ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(),
- actionId, action.slot, !planIter.hasNext() && refresh ? InventoryUtils.REFRESH_ITEM : clickedItem,
- WindowAction.CLICK_ITEM, action.click.actionParam);
-
- if (translator.getSlotType(action.slot) == SlotType.OUTPUT) {
- if (cursorItem == null && clickedItem != null) {
- playerInventory.setCursor(clickedItem);
- } else if (InventoryUtils.canStack(cursorItem, clickedItem)) {
- playerInventory.setCursor(new ItemStack(cursorItem.getId(),
- cursorItem.getAmount() + clickedItem.getAmount(), cursorItem.getNbt()));
- }
- } else {
- switch (action.click) {
- case LEFT:
- if (!InventoryUtils.canStack(cursorItem, clickedItem)) {
- playerInventory.setCursor(clickedItem);
- inventory.setItem(action.slot, cursorItem);
- } else {
- playerInventory.setCursor(null);
- inventory.setItem(action.slot, new ItemStack(clickedItem.getId(),
- clickedItem.getAmount() + cursorItem.getAmount(), clickedItem.getNbt()));
- }
- break;
- case RIGHT:
- if (cursorItem == null && clickedItem != null) {
- ItemStack halfItem = new ItemStack(clickedItem.getId(),
- clickedItem.getAmount() / 2, clickedItem.getNbt());
- inventory.setItem(action.slot, halfItem);
- playerInventory.setCursor(new ItemStack(clickedItem.getId(),
- clickedItem.getAmount() - halfItem.getAmount(), clickedItem.getNbt()));
- } else if (cursorItem != null && clickedItem == null) {
- playerInventory.setCursor(new ItemStack(cursorItem.getId(),
- cursorItem.getAmount() - 1, cursorItem.getNbt()));
- inventory.setItem(action.slot, new ItemStack(cursorItem.getId(),
- 1, cursorItem.getNbt()));
- } else if (InventoryUtils.canStack(cursorItem, clickedItem)) {
- playerInventory.setCursor(new ItemStack(cursorItem.getId(),
- cursorItem.getAmount() - 1, cursorItem.getNbt()));
- inventory.setItem(action.slot, new ItemStack(clickedItem.getId(),
- clickedItem.getAmount() + 1, clickedItem.getNbt()));
- }
- break;
- }
- }
- session.sendDownstreamPacket(clickPacket);
- session.sendDownstreamPacket(new ClientConfirmTransactionPacket(inventory.getId(), actionId, true));
- }
-
- /*if (refresh) {
- translator.updateInventory(session, inventory);
- InventoryUtils.updateCursor(session);
- }*/
- }
-
- private static class ClickAction {
- final Click click;
- final int slot;
- ClickAction(Click click, int slot) {
- this.click = click;
- this.slot = slot;
- }
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java
deleted file mode 100644
index 96cbd61fb..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory.action;
-
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
-import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
-import com.github.steveice10.mc.protocol.data.game.window.*;
-import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
-import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
-import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
-import com.nukkitx.protocol.bedrock.data.inventory.InventorySource;
-import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
-import org.geysermc.connector.network.translators.inventory.SlotType;
-import org.geysermc.connector.network.translators.item.ItemTranslator;
-import org.geysermc.connector.utils.InventoryUtils;
-
-import java.util.*;
-
-public class InventoryActionDataTranslator {
- public static void translate(InventoryTranslator translator, GeyserSession session, Inventory inventory, List actions) {
- if (actions.size() != 2)
- return;
-
- InventoryActionData worldAction = null;
- InventoryActionData cursorAction = null;
- InventoryActionData containerAction = null;
- boolean refresh = false;
- for (InventoryActionData action : actions) {
- if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT) {
- return;
- } else if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION) {
- worldAction = action;
- } else if (action.getSource().getContainerId() == ContainerId.UI && action.getSlot() == 0) {
- cursorAction = action;
- ItemData translatedCursor = ItemTranslator.translateToBedrock(session, session.getInventory().getCursor());
- if (!translatedCursor.equals(action.getFromItem())) {
- refresh = true;
- }
- } else {
- containerAction = action;
- ItemData translatedItem = ItemTranslator.translateToBedrock(session, inventory.getItem(translator.bedrockSlotToJava(action)));
- if (!translatedItem.equals(action.getFromItem())) {
- refresh = true;
- }
- }
- }
-
- final int craftSlot = session.getCraftSlot();
- session.setCraftSlot(0);
-
- if (worldAction != null) {
- InventoryActionData sourceAction;
- if (cursorAction != null) {
- sourceAction = cursorAction;
- } else {
- sourceAction = containerAction;
- }
-
- if (sourceAction != null) {
- if (worldAction.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) {
- //quick dropping from hotbar?
- if (session.getInventoryCache().getOpenInventory() == null && sourceAction.getSource().getContainerId() == ContainerId.INVENTORY) {
- int heldSlot = session.getInventory().getHeldItemSlot();
- if (sourceAction.getSlot() == heldSlot) {
- ClientPlayerActionPacket actionPacket = new ClientPlayerActionPacket(
- sourceAction.getToItem().getCount() == 0 ? PlayerAction.DROP_ITEM_STACK : PlayerAction.DROP_ITEM,
- new Position(0, 0, 0), BlockFace.DOWN);
- session.sendDownstreamPacket(actionPacket);
- ItemStack item = session.getInventory().getItem(heldSlot);
- if (item != null) {
- session.getInventory().setItem(heldSlot, new ItemStack(item.getId(), item.getAmount() - 1, item.getNbt()));
- }
- return;
- }
- }
- int dropAmount = sourceAction.getFromItem().getCount() - sourceAction.getToItem().getCount();
- if (sourceAction != cursorAction) { //dropping directly from inventory
- int javaSlot = translator.bedrockSlotToJava(sourceAction);
- if (dropAmount == sourceAction.getFromItem().getCount()) {
- ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(),
- inventory.getTransactionId().getAndIncrement(),
- javaSlot, null, WindowAction.DROP_ITEM,
- DropItemParam.DROP_SELECTED_STACK);
- session.sendDownstreamPacket(dropPacket);
- } else {
- for (int i = 0; i < dropAmount; i++) {
- ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(),
- inventory.getTransactionId().getAndIncrement(),
- javaSlot, null, WindowAction.DROP_ITEM,
- DropItemParam.DROP_FROM_SELECTED);
- session.sendDownstreamPacket(dropPacket);
- }
- }
- ItemStack item = inventory.getItem(javaSlot);
- if (item != null) {
- inventory.setItem(javaSlot, new ItemStack(item.getId(), item.getAmount() - dropAmount, item.getNbt()));
- }
- return;
- } else { //clicking outside of inventory
- ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
- -999, null, WindowAction.CLICK_ITEM,
- dropAmount > 1 ? ClickItemParam.LEFT_CLICK : ClickItemParam.RIGHT_CLICK);
- session.sendDownstreamPacket(dropPacket);
- ItemStack cursor = session.getInventory().getCursor();
- if (cursor != null) {
- session.getInventory().setCursor(new ItemStack(cursor.getId(), dropAmount > 1 ? 0 : cursor.getAmount() - 1, cursor.getNbt()));
- }
- return;
- }
- }
- }
- } else if (cursorAction != null && containerAction != null) {
- //left/right click
- ClickPlan plan = new ClickPlan();
- int javaSlot = translator.bedrockSlotToJava(containerAction);
- if (cursorAction.getFromItem().equals(containerAction.getToItem())
- && containerAction.getFromItem().equals(cursorAction.getToItem())
- && !InventoryUtils.canStack(cursorAction.getFromItem(), containerAction.getFromItem())) { //simple swap
- plan.add(Click.LEFT, javaSlot);
- } else if (cursorAction.getFromItem().getCount() > cursorAction.getToItem().getCount()) { //release
- if (cursorAction.getToItem().getCount() == 0) {
- plan.add(Click.LEFT, javaSlot);
- } else {
- int difference = cursorAction.getFromItem().getCount() - cursorAction.getToItem().getCount();
- for (int i = 0; i < difference; i++) {
- plan.add(Click.RIGHT, javaSlot);
- }
- }
- } else { //pickup
- if (cursorAction.getFromItem().getCount() == 0) {
- if (containerAction.getToItem().getCount() == 0) { //pickup all
- plan.add(Click.LEFT, javaSlot);
- } else { //pickup some
- if (translator.getSlotType(javaSlot) == SlotType.FURNACE_OUTPUT
- || containerAction.getToItem().getCount() == containerAction.getFromItem().getCount() / 2) { //right click
- plan.add(Click.RIGHT, javaSlot);
- } else {
- plan.add(Click.LEFT, javaSlot);
- int difference = containerAction.getFromItem().getCount() - cursorAction.getToItem().getCount();
- for (int i = 0; i < difference; i++) {
- plan.add(Click.RIGHT, javaSlot);
- }
- }
- }
- } else { //pickup into non-empty cursor
- if (translator.getSlotType(javaSlot) == SlotType.FURNACE_OUTPUT) {
- if (containerAction.getToItem().getCount() == 0) {
- plan.add(Click.LEFT, javaSlot);
- } else {
- ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(),
- inventory.getTransactionId().getAndIncrement(),
- javaSlot, InventoryUtils.REFRESH_ITEM, WindowAction.SHIFT_CLICK_ITEM,
- ShiftClickItemParam.LEFT_CLICK);
- session.sendDownstreamPacket(shiftClickPacket);
- translator.updateInventory(session, inventory);
- return;
- }
- } else if (translator.getSlotType(javaSlot) == SlotType.OUTPUT) {
- plan.add(Click.LEFT, javaSlot);
- } else {
- int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot), false);
- if (cursorSlot != -1) {
- plan.add(Click.LEFT, cursorSlot);
- } else {
- translator.updateInventory(session, inventory);
- InventoryUtils.updateCursor(session);
- return;
- }
- plan.add(Click.LEFT, javaSlot);
- int difference = cursorAction.getToItem().getCount() - cursorAction.getFromItem().getCount();
- for (int i = 0; i < difference; i++) {
- plan.add(Click.RIGHT, cursorSlot);
- }
- plan.add(Click.LEFT, javaSlot);
- plan.add(Click.LEFT, cursorSlot);
- }
- }
- }
- plan.execute(session, translator, inventory, refresh);
- return;
- } else {
- ClickPlan plan = new ClickPlan();
- InventoryActionData fromAction;
- InventoryActionData toAction;
- if (actions.get(0).getFromItem().getCount() >= actions.get(0).getToItem().getCount()) {
- fromAction = actions.get(0);
- toAction = actions.get(1);
- } else {
- fromAction = actions.get(1);
- toAction = actions.get(0);
- }
- int fromSlot = translator.bedrockSlotToJava(fromAction);
- int toSlot = translator.bedrockSlotToJava(toAction);
-
- if (translator.getSlotType(fromSlot) == SlotType.OUTPUT) {
- if ((craftSlot != 0 && craftSlot != -2) && (inventory.getItem(toSlot) == null
- || InventoryUtils.canStack(session.getInventory().getCursor(), inventory.getItem(toSlot)))) {
- if (fromAction.getToItem().getCount() == 0) {
- refresh = true;
- plan.add(Click.LEFT, toSlot);
- if (craftSlot != -1) {
- plan.add(Click.LEFT, craftSlot);
- }
- } else {
- int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount();
- for (int i = 0; i < difference; i++) {
- plan.add(Click.RIGHT, toSlot);
- }
- session.setCraftSlot(craftSlot);
- }
- plan.execute(session, translator, inventory, refresh);
- return;
- } else {
- session.setCraftSlot(-2);
- }
- }
-
- int cursorSlot = -1;
- if (session.getInventory().getCursor() != null) { //move cursor contents to a temporary slot
- cursorSlot = findTempSlot(inventory,
- session.getInventory().getCursor(),
- Arrays.asList(fromSlot, toSlot),
- translator.getSlotType(fromSlot) == SlotType.OUTPUT);
- if (cursorSlot != -1) {
- plan.add(Click.LEFT, cursorSlot);
- } else {
- translator.updateInventory(session, inventory);
- InventoryUtils.updateCursor(session);
- return;
- }
- }
- if ((fromAction.getFromItem().equals(toAction.getToItem()) && !InventoryUtils.canStack(fromAction.getFromItem(), toAction.getFromItem()))
- || fromAction.getToItem().getId() == 0) { //slot swap
- plan.add(Click.LEFT, fromSlot);
- plan.add(Click.LEFT, toSlot);
- if (fromAction.getToItem().getId() != 0) {
- plan.add(Click.LEFT, fromSlot);
- }
- } else if (InventoryUtils.canStack(fromAction.getFromItem(), toAction.getToItem())) { //partial item move
- if (translator.getSlotType(fromSlot) == SlotType.FURNACE_OUTPUT) {
- ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(),
- inventory.getTransactionId().getAndIncrement(),
- fromSlot, InventoryUtils.REFRESH_ITEM, WindowAction.SHIFT_CLICK_ITEM,
- ShiftClickItemParam.LEFT_CLICK);
- session.sendDownstreamPacket(shiftClickPacket);
- translator.updateInventory(session, inventory);
- return;
- } else if (translator.getSlotType(fromSlot) == SlotType.OUTPUT) {
- session.setCraftSlot(cursorSlot);
- plan.add(Click.LEFT, fromSlot);
- int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount();
- for (int i = 0; i < difference; i++) {
- plan.add(Click.RIGHT, toSlot);
- }
- //client will send additional packets later to finish transferring crafting output
- //translator will know how to handle this using the craftSlot variable
- } else {
- plan.add(Click.LEFT, fromSlot);
- int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount();
- for (int i = 0; i < difference; i++) {
- plan.add(Click.RIGHT, toSlot);
- }
- plan.add(Click.LEFT, fromSlot);
- }
- }
- if (cursorSlot != -1) {
- plan.add(Click.LEFT, cursorSlot);
- }
- plan.execute(session, translator, inventory, refresh);
- return;
- }
-
- translator.updateInventory(session, inventory);
- InventoryUtils.updateCursor(session);
- }
-
- private static int findTempSlot(Inventory inventory, ItemStack item, List slotBlacklist, boolean emptyOnly) {
- /*try and find a slot that can temporarily store the given item
- only look in the main inventory and hotbar
- only slots that are empty or contain a different type of item are valid*/
- int offset = inventory.getId() == 0 ? 1 : 0; //offhand is not a viable slot (some servers disable it)
- List itemBlacklist = new ArrayList<>(slotBlacklist.size() + 1);
- itemBlacklist.add(item);
- for (int slot : slotBlacklist) {
- ItemStack blacklistItem = inventory.getItem(slot);
- if (blacklistItem != null)
- itemBlacklist.add(blacklistItem);
- }
- for (int i = inventory.getSize() - (36 + offset); i < inventory.getSize() - offset; i++) {
- ItemStack testItem = inventory.getItem(i);
- boolean acceptable = true;
- if (testItem != null) {
- if (emptyOnly) {
- continue;
- }
- for (ItemStack blacklistItem : itemBlacklist) {
- if (InventoryUtils.canStack(testItem, blacklistItem)) {
- acceptable = false;
- break;
- }
- }
- }
- if (acceptable && !slotBlacklist.contains(i))
- return i;
- }
- //could not find a viable temp slot
- return -1;
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java
deleted file mode 100644
index 6afdb25dd..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.inventory.holder;
-
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
-import com.nukkitx.math.vector.Vector3i;
-import com.nukkitx.nbt.NbtMap;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
-import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
-import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
-import lombok.AllArgsConstructor;
-import org.geysermc.connector.inventory.Inventory;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
-import org.geysermc.connector.network.translators.world.block.BlockTranslator;
-
-@AllArgsConstructor
-public class BlockInventoryHolder extends InventoryHolder {
- private final int blockId;
- private final ContainerType containerType;
-
- @Override
- public void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
- Vector3i position = session.getPlayerEntity().getPosition().toInt();
- position = position.add(Vector3i.UP);
- UpdateBlockPacket blockPacket = new UpdateBlockPacket();
- blockPacket.setDataLayer(0);
- blockPacket.setBlockPosition(position);
- blockPacket.setRuntimeId(blockId);
- blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
- session.sendUpstreamPacket(blockPacket);
- inventory.setHolderPosition(position);
-
- NbtMap tag = NbtMap.builder()
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ())
- .putString("CustomName", inventory.getTitle()).build();
- BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
- dataPacket.setData(tag);
- dataPacket.setBlockPosition(position);
- session.sendUpstreamPacket(dataPacket);
- }
-
- @Override
- public void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
- ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
- containerOpenPacket.setId((byte) inventory.getId());
- containerOpenPacket.setType(containerType);
- containerOpenPacket.setBlockPosition(inventory.getHolderPosition());
- containerOpenPacket.setUniqueEntityId(inventory.getHolderId());
- session.sendUpstreamPacket(containerOpenPacket);
- }
-
- @Override
- public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
- Vector3i holderPos = inventory.getHolderPosition();
- Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ());
- int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ());
- UpdateBlockPacket blockPacket = new UpdateBlockPacket();
- blockPacket.setDataLayer(0);
- blockPacket.setBlockPosition(holderPos);
- blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock));
- session.sendUpstreamPacket(blockPacket);
- }
-}
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
deleted file mode 100644
index a4a2fb750..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.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.nukkitx.nbt.NbtMap;
-import com.nukkitx.nbt.NbtUtils;
-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 org.geysermc.connector.GeyserConnector;
-import org.geysermc.connector.utils.FileUtils;
-import org.geysermc.connector.utils.LanguageUtils;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.*;
-
-/**
- * Registry for anything item related.
- */
-public class ItemRegistry {
-
- private static final Map JAVA_IDENTIFIER_MAP = new HashMap<>();
-
- public static final ItemData[] CREATIVE_ITEMS;
-
- public static final List ITEMS = new ArrayList<>();
- public static final Int2ObjectMap ITEM_ENTRIES = new Int2ObjectOpenHashMap<>();
-
- /**
- * Bamboo item entry, used in PandaEntity.java
- */
- public static ItemEntry BAMBOO;
- /**
- * Boat item entries, used in BedrockInventoryTransactionTranslator.java
- */
- public static IntList BOATS = new IntArrayList();
- /**
- * Bucket item entries (excluding the milk bucket), used in BedrockInventoryTransactionTranslator.java
- */
- public static IntList BUCKETS = new IntArrayList();
- /**
- * Empty item bucket, used in BedrockInventoryTransactionTranslator.java
- */
- public static ItemEntry MILK_BUCKET;
- /**
- * Egg item entry, used in JavaEntityStatusTranslator.java
- */
- public static ItemEntry EGG;
- /**
- * Gold item entry, used in PiglinEntity.java
- */
- public static ItemEntry GOLD;
- /**
- * Shield item entry, used in Entity.java and LivingEntity.java
- */
- public static ItemEntry SHIELD;
- /**
- * Wheat item entry, used in AbstractHorseEntity.java
- */
- public static ItemEntry WHEAT;
-
- public static int BARRIER_INDEX = 0;
-
- public static void init() {
- // no-op
- }
-
- static {
- /* Load item palette */
- InputStream stream = FileUtils.getResource("bedrock/runtime_item_states.json");
-
- TypeReference> itemEntriesType = new TypeReference>() {
- };
-
- // Used to get the Bedrock namespaced ID (in instances where there are small differences)
- Int2ObjectMap bedrockIdToIdentifier = new Int2ObjectOpenHashMap<>();
-
- List itemEntries;
- try {
- itemEntries = GeyserConnector.JSON_MAPPER.readValue(stream, itemEntriesType);
- } catch (Exception e) {
- throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_bedrock"), e);
- }
-
- int lodestoneCompassId = 0;
-
- for (JsonNode entry : itemEntries) {
- ITEMS.add(new StartGamePacket.ItemEntry(entry.get("name").textValue(), (short) entry.get("id").intValue()));
- bedrockIdToIdentifier.put(entry.get("id").intValue(), entry.get("name").textValue());
- if (entry.get("name").textValue().equals("minecraft:lodestone_compass")) {
- lodestoneCompassId = entry.get("id").intValue();
- }
- }
-
- stream = FileUtils.getResource("mappings/items.json");
-
- JsonNode items;
- try {
- items = GeyserConnector.JSON_MAPPER.readTree(stream);
- } catch (Exception e) {
- throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e);
- }
-
- int itemIndex = 0;
- Iterator> iterator = items.fields();
- while (iterator.hasNext()) {
- Map.Entry entry = iterator.next();
- int bedrockId = entry.getValue().get("bedrock_id").intValue();
- String bedrockIdentifier = bedrockIdToIdentifier.get(bedrockId);
- if (bedrockIdentifier == null) {
- throw new RuntimeException("Missing Bedrock ID in mappings!: " + bedrockId);
- }
- if (entry.getValue().has("tool_type")) {
- if (entry.getValue().has("tool_tier")) {
- ITEM_ENTRIES.put(itemIndex, 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") != null && entry.getValue().get("is_block").booleanValue()));
- } else {
- ITEM_ENTRIES.put(itemIndex, 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()));
- }
- } else {
- ITEM_ENTRIES.put(itemIndex, new ItemEntry(
- entry.getKey(), bedrockIdentifier, itemIndex, bedrockId,
- entry.getValue().get("bedrock_data").intValue(),
- entry.getValue().get("is_block") != null && entry.getValue().get("is_block").booleanValue()));
- }
- switch (entry.getKey()) {
- case "minecraft:barrier":
- BARRIER_INDEX = itemIndex;
- break;
- case "minecraft:bamboo":
- BAMBOO = ITEM_ENTRIES.get(itemIndex);
- break;
- case "minecraft:egg":
- EGG = ITEM_ENTRIES.get(itemIndex);
- break;
- case "minecraft:gold_ingot":
- GOLD = ITEM_ENTRIES.get(itemIndex);
- break;
- case "minecraft:shield":
- SHIELD = ITEM_ENTRIES.get(itemIndex);
- break;
- case "minecraft:milk_bucket":
- MILK_BUCKET = ITEM_ENTRIES.get(itemIndex);
- break;
- case "minecraft:wheat":
- WHEAT = ITEM_ENTRIES.get(itemIndex);
- break;
- default:
- break;
- }
-
- if (entry.getKey().contains("boat")) {
- BOATS.add(entry.getValue().get("bedrock_id").intValue());
- } else if (entry.getKey().contains("bucket") && !entry.getKey().contains("milk")) {
- BUCKETS.add(entry.getValue().get("bedrock_id").intValue());
- }
-
- itemIndex++;
- }
-
- 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));
-
- /* Load creative items */
- stream = FileUtils.getResource("bedrock/creative_items.json");
-
- JsonNode creativeItemEntries;
- try {
- creativeItemEntries = GeyserConnector.JSON_MAPPER.readTree(stream).get("items");
- } catch (Exception e) {
- throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.creative"), e);
- }
-
- 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()));
- }
- CREATIVE_ITEMS = creativeItems.toArray(new ItemData[0]);
- }
-
- /**
- * Gets an {@link ItemEntry} from the given {@link ItemStack}.
- *
- * @param stack the item stack
- * @return an item entry from the given item stack
- */
- public static ItemEntry getItem(ItemStack stack) {
- return ITEM_ENTRIES.get(stack.getId());
- }
-
- /**
- * Gets an {@link ItemEntry} from the given {@link ItemData}.
- *
- * @param data the item data
- * @return an item entry from the given item data
- */
- public static ItemEntry getItem(ItemData data) {
- for (ItemEntry itemEntry : ITEM_ENTRIES.values()) {
- if (itemEntry.getBedrockId() == data.getId() && (itemEntry.getBedrockData() == data.getDamage() ||
- // Make exceptions for potions and tipped arrows, whose damage values can vary
- (itemEntry.getJavaIdentifier().endsWith("potion") || itemEntry.getJavaIdentifier().equals("minecraft:arrow")))) {
- return itemEntry;
- }
- }
-
- // This will hide the message when the player clicks with an empty hand
- if (data.getId() != 0 && data.getDamage() != 0) {
- GeyserConnector.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getId() + ":" + data.getDamage());
- }
- return ItemEntry.AIR;
- }
-
- /**
- * Gets an {@link ItemEntry} from the given Minecraft: Java Edition
- * block state identifier.
- *
- * @param javaIdentifier the block state identifier
- * @return an item entry from the given java edition identifier
- */
- public static ItemEntry getItemEntry(String javaIdentifier) {
- return JAVA_IDENTIFIER_MAP.computeIfAbsent(javaIdentifier, key -> {
- for (ItemEntry entry : ITEM_ENTRIES.values()) {
- if (entry.getJavaIdentifier().equals(key)) {
- return entry;
- }
- }
- return null;
- });
- }
-
- /**
- * Gets a Bedrock {@link ItemData} from a {@link JsonNode}
- * @param itemNode the JSON node that contains ProxyPass-compatible Bedrock item data
- * @return
- */
- public static ItemData getBedrockItemFromJson(JsonNode itemNode) {
- int count = 1;
- short damage = 0;
- NbtMap tag = null;
- if (itemNode.has("damage")) {
- damage = itemNode.get("damage").numberValue().shortValue();
- }
- if (itemNode.has("count")) {
- count = itemNode.get("count").asInt();
- }
- if (itemNode.has("nbt_b64")) {
- byte[] bytes = Base64.getDecoder().decode(itemNode.get("nbt_b64").asText());
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- try {
- tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return ItemData.of(itemNode.get("id").asInt(), damage, count, tag);
- }
-}
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
deleted file mode 100644
index 411c0295b..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.item;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
-import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
-import it.unimi.dsi.fastutil.objects.ObjectArrayList;
-import org.geysermc.connector.GeyserConnector;
-import org.geysermc.connector.utils.FileUtils;
-import org.geysermc.connector.utils.LanguageUtils;
-
-import java.io.InputStream;
-import java.util.*;
-
-/**
- * Manages any recipe-related storing
- */
-public class RecipeRegistry {
-
- /**
- * A list of all possible leather armor dyeing recipes.
- * Created manually.
- */
- public static final List LEATHER_DYEING_RECIPES = new ObjectArrayList<>();
- /**
- * A list of all possible firework rocket recipes, including the base rocket.
- * Obtained from a ProxyPass dump of protocol v407
- */
- public static final List FIREWORK_ROCKET_RECIPES = new ObjectArrayList<>();
- /**
- * A list of all possible firework star recipes.
- * Obtained from a ProxyPass dump of protocol v407
- */
- public static final List FIREWORK_STAR_RECIPES = new ObjectArrayList<>();
- /**
- * A list of all possible shulker box dyeing options.
- * Obtained from a ProxyPass dump of protocol v407
- */
- public static final List SHULKER_BOX_DYEING_RECIPES = new ObjectArrayList<>();
- /**
- * A list of all possible suspicious stew recipes.
- * Obtained from a ProxyPass dump of protocol v407
- */
- public static final List SUSPICIOUS_STEW_RECIPES = new ObjectArrayList<>();
- /**
- * A list of all possible tipped arrow recipes.
- * Obtained from a ProxyPass dump of protocol v407
- */
- public static final List TIPPED_ARROW_RECIPES = new ObjectArrayList<>();
-
- // TODO: These are the other "multi" UUIDs that supposedly enable various recipes. Find out what each enables.
- // 442d85ed-8272-4543-a6f1-418f90ded05d 8b36268c-1829-483c-a0f1-993b7156a8f2 602234e4-cac1-4353-8bb7-b1ebff70024b 98c84b38-1085-46bd-b1ce-dd38c159e6cc
- // d81aaeaf-e172-4440-9225-868df030d27b b5c5d105-75a2-4076-af2b-923ea2bf4bf0 00000000-0000-0000-0000-000000000002 85939755-ba10-4d9d-a4cc-efb7a8e943c4
- // d392b075-4ba1-40ae-8789-af868d56f6ce aecd2294-4b94-434b-8667-4499bb2c9327
- /**
- * Recipe data that, when sent to the client, enables book cloning
- */
- public static final CraftingData BOOK_CLONING_RECIPE_DATA = CraftingData.fromMulti(UUID.fromString("d1ca6b84-338e-4f2f-9c6b-76cc8b4bd98d"));
- /**
- * Recipe data that, when sent to the client, enables tool repairing in a crafting table
- */
- public static final CraftingData TOOL_REPAIRING_RECIPE_DATA = CraftingData.fromMulti(UUID.fromString("00000000-0000-0000-0000-000000000001"));
-
- static {
- // Get all recipes that are not directly sent from a Java server
- InputStream stream = FileUtils.getResource("mappings/recipes.json");
-
- JsonNode items;
- try {
- items = GeyserConnector.JSON_MAPPER.readTree(stream);
- } catch (Exception e) {
- throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e);
- }
-
- for (JsonNode entry: items.get("leather_armor")) {
- // This won't be perfect, as we can't possibly send every leather input for every kind of color
- // But it does display the correct output from a base leather armor, and besides visuals everything works fine
- LEATHER_DYEING_RECIPES.add(getCraftingDataFromJsonNode(entry));
- }
- for (JsonNode entry : items.get("firework_rockets")) {
- FIREWORK_ROCKET_RECIPES.add(getCraftingDataFromJsonNode(entry));
- }
- for (JsonNode entry : items.get("firework_stars")) {
- FIREWORK_STAR_RECIPES.add(getCraftingDataFromJsonNode(entry));
- }
- for (JsonNode entry : items.get("shulker_boxes")) {
- SHULKER_BOX_DYEING_RECIPES.add(getCraftingDataFromJsonNode(entry));
- }
- for (JsonNode entry : items.get("suspicious_stew")) {
- SUSPICIOUS_STEW_RECIPES.add(getCraftingDataFromJsonNode(entry));
- }
- for (JsonNode entry : items.get("tipped_arrows")) {
- TIPPED_ARROW_RECIPES.add(getCraftingDataFromJsonNode(entry));
- }
- }
-
- /**
- * Computes a Bedrock crafting recipe from the given JSON data.
- * @param node the JSON data to compute
- * @return the {@link CraftingData} to send to the Bedrock client.
- */
- private static CraftingData getCraftingDataFromJsonNode(JsonNode node) {
- ItemData output = ItemRegistry.getBedrockItemFromJson(node.get("output").get(0));
- UUID uuid = UUID.randomUUID();
- if (node.get("type").asInt() == 1) {
- // Shaped recipe
- List shape = new ArrayList<>();
- // Get the shape of the recipe
- for (JsonNode chars : node.get("shape")) {
- shape.add(chars.asText());
- }
-
- // In recipes.json each recipe is mapped by a letter
- Map letterToRecipe = new HashMap<>();
- Iterator> iterator = node.get("input").fields();
- while (iterator.hasNext()) {
- Map.Entry entry = iterator.next();
- letterToRecipe.put(entry.getKey(), ItemRegistry.getBedrockItemFromJson(entry.getValue()));
- }
-
- ItemData[] inputs = new ItemData[shape.size() * shape.get(0).length()];
- int i = 0;
- // Create a linear array of items from the "cube" of the shape
- for (int j = 0; i < shape.size() * shape.get(0).length(); j++) {
- for (char c : shape.get(j).toCharArray()) {
- ItemData data = letterToRecipe.getOrDefault(String.valueOf(c), ItemData.AIR);
- inputs[i] = data;
- i++;
- }
- }
-
- return CraftingData.fromShaped(uuid.toString(), shape.get(0).length(), shape.size(),
- inputs, new ItemData[]{output}, uuid, "crafting_table", 0);
- }
- List inputs = new ObjectArrayList<>();
- for (JsonNode entry : node.get("input")) {
- inputs.add(ItemRegistry.getBedrockItemFromJson(entry));
- }
- if (node.get("type").asInt() == 5) {
- // Shulker box
- return CraftingData.fromShulkerBox(uuid.toString(),
- inputs.toArray(new ItemData[0]), new ItemData[]{output}, uuid, "crafting_table", 0);
- }
- return CraftingData.fromShapeless(uuid.toString(),
- inputs.toArray(new ItemData[0]), new ItemData[]{output}, uuid, "crafting_table", 0);
- }
-
- public static void init() {
- // no-op
- }
-}
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
deleted file mode 100644
index dde577005..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.item;
-
-import lombok.Getter;
-
-@Getter
-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) {
- super(javaIdentifier, bedrockIdentifier, javaId, bedrockId, bedrockData, isBlock);
- this.toolType = toolType;
- this.toolTier = toolTier;
- }
-}
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
deleted file mode 100644
index 92ec67dd4..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.item.translators;
-
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.opennbt.tag.builtin.*;
-import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
-import org.geysermc.connector.network.translators.ItemRemapper;
-import org.geysermc.connector.network.translators.item.ItemEntry;
-import org.geysermc.connector.network.translators.item.ItemRegistry;
-import org.geysermc.connector.network.translators.item.ItemTranslator;
-import org.geysermc.connector.utils.LoadstoneTracker;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-@ItemRemapper
-public class CompassTranslator extends ItemTranslator {
-
- private final List appliedItems;
-
- public CompassTranslator() {
- appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("compass")).collect(Collectors.toList());
- }
-
- @Override
- public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) {
- if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, itemEntry);
-
- Tag lodestoneTag = itemStack.getNbt().get("LodestoneTracked");
- if (lodestoneTag instanceof ByteTag) {
- // Get the fake lodestonecompass entry
- itemEntry = ItemRegistry.getItemEntry("minecraft:lodestone_compass");
-
- // Get the loadstone pos
- CompoundTag loadstonePos = itemStack.getNbt().get("LodestonePos");
- if (loadstonePos != null) {
- // Get all info needed for tracking
- int x = ((IntTag) loadstonePos.get("X")).getValue();
- int y = ((IntTag) loadstonePos.get("Y")).getValue();
- int z = ((IntTag) loadstonePos.get("Z")).getValue();
- String dim = ((StringTag) itemStack.getNbt().get("LodestoneDimension")).getValue();
-
- // Store the info
- int trackID = LoadstoneTracker.store(x, y, z, dim);
-
- // Set the bedrock tracking id
- itemStack.getNbt().put(new IntTag("trackingHandle", trackID));
- } else {
- // The loadstone was removed just set the tracking id to 0
- itemStack.getNbt().put(new IntTag("trackingHandle", 0));
- }
- }
-
- ItemData itemData = super.translateToBedrock(itemStack, itemEntry);
-
- return itemData;
- }
-
- @Override
- public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) {
- boolean isLoadstone = false;
- if (itemEntry.getBedrockIdentifier().equals("minecraft:lodestone_compass")) {
- // Revert the entry back to the compass
- itemEntry = ItemRegistry.getItemEntry("minecraft:compass");
-
- isLoadstone = true;
- }
-
- ItemStack itemStack = super.translateToJava(itemData, itemEntry);
-
- if (isLoadstone) {
- // Get the tracking id
- int trackingID = ((IntTag) itemStack.getNbt().get("trackingHandle")).getValue();
-
- // Fetch the tracking info from the id
- LoadstoneTracker.LoadstonePos pos = LoadstoneTracker.getPos(trackingID);
- if (pos != null) {
- // Build the new NBT data for the fetched tracking info
- itemStack.getNbt().put(new StringTag("LodestoneDimension", pos.getDimension()));
-
- CompoundTag posTag = new CompoundTag("LodestonePos");
- posTag.put(new IntTag("X", pos.getX()));
- posTag.put(new IntTag("Y", pos.getY()));
- posTag.put(new IntTag("Z", pos.getZ()));
-
- itemStack.getNbt().put(posTag);
- }
- }
-
- return itemStack;
- }
-
- @Override
- public List getAppliedItems() {
- return appliedItems;
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java
deleted file mode 100644
index 3fd9df8a0..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.item.translators.nbt;
-
-import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
-import com.github.steveice10.opennbt.tag.builtin.ListTag;
-import com.github.steveice10.opennbt.tag.builtin.StringTag;
-import com.github.steveice10.opennbt.tag.builtin.Tag;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.TextComponent;
-import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
-import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.ItemRemapper;
-import org.geysermc.connector.network.translators.item.ItemEntry;
-import org.geysermc.connector.network.translators.item.NbtItemStackTranslator;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@ItemRemapper(priority = -1)
-public class BasicItemTranslator extends NbtItemStackTranslator {
-
- @Override
- public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemEntry itemEntry) {
- if (!itemTag.contains("display")) {
- return;
- }
- CompoundTag displayTag = itemTag.get("display");
- if (displayTag.contains("Name")) {
- StringTag nameTag = displayTag.get("Name");
- try {
- displayTag.put(new StringTag("Name", toBedrockMessage(nameTag)));
- } catch (Exception ex) {
- }
- }
-
- if (displayTag.contains("Lore")) {
- ListTag loreTag = displayTag.get("Lore");
- List lore = new ArrayList<>();
- for (Tag tag : loreTag.getValue()) {
- if (!(tag instanceof StringTag)) return;
- try {
- lore.add(new StringTag("", toBedrockMessage((StringTag) tag)));
- } catch (Exception ex) {
- }
- }
- displayTag.put(new ListTag("Lore", lore));
- }
- }
-
- @Override
- public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) {
- if (!itemTag.contains("display")) {
- return;
- }
- CompoundTag displayTag = itemTag.get("display");
- if (displayTag.contains("Name")) {
- StringTag nameTag = displayTag.get("Name");
- displayTag.put(new StringTag("Name", toJavaMessage(nameTag)));
- }
-
- if (displayTag.contains("Lore")) {
- ListTag loreTag = displayTag.get("Lore");
- List lore = new ArrayList<>();
- for (Tag tag : loreTag.getValue()) {
- if (!(tag instanceof StringTag)) return;
- lore.add(new StringTag("", "§r" + toJavaMessage((StringTag) tag)));
- }
- displayTag.put(new ListTag("Lore", lore));
- }
- }
-
- private String toJavaMessage(StringTag tag) {
- String message = tag.getValue();
- if (message == null) return null;
- if (message.startsWith("§r")) {
- message = message.replaceFirst("§r", "");
- }
- Component component = Component.text(message);
- return GsonComponentSerializer.gson().serialize(component);
- }
-
- private String toBedrockMessage(StringTag tag) {
- String message = tag.getValue();
- if (message == null) return null;
- TextComponent component = (TextComponent) GsonComponentSerializer.gson().deserialize(message);
- String legacy = LegacyComponentSerializer.legacySection().serialize(component);
- if (hasFormatting(LegacyComponentSerializer.legacySection().deserialize(legacy))) {
- return "§r" + legacy;
- }
- return legacy;
- }
-
- private boolean hasFormatting(Component component) {
- if (component.hasStyling()) return true;
- for (Component child : component.children()) {
- if (hasFormatting(child)) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java
deleted file mode 100644
index 3b453ea18..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.item.translators.nbt;
-
-import com.github.steveice10.opennbt.tag.builtin.*;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.ItemRemapper;
-import org.geysermc.connector.network.translators.item.ItemEntry;
-import org.geysermc.connector.network.translators.item.NbtItemStackTranslator;
-import org.geysermc.connector.utils.FireworkColor;
-import org.geysermc.connector.utils.MathUtils;
-
-@ItemRemapper
-public class FireworkTranslator extends NbtItemStackTranslator {
-
- @Override
- public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemEntry itemEntry) {
- if (!itemTag.contains("Fireworks")) {
- return;
- }
-
- CompoundTag fireworks = itemTag.get("Fireworks");
- if (fireworks.get("Flight") != null) {
- fireworks.put(new ByteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue())));
- }
-
- ListTag explosions = fireworks.get("Explosions");
- if (explosions == null) {
- return;
- }
- for (Tag effect : explosions.getValue()) {
- CompoundTag effectData = (CompoundTag) effect;
-
- CompoundTag newEffectData = new CompoundTag("");
-
- if (effectData.get("Type") != null) {
- newEffectData.put(new ByteTag("FireworkType", MathUtils.convertByte(effectData.get("Type").getValue())));
- }
-
- if (effectData.get("Colors") != null) {
- int[] oldColors = (int[]) effectData.get("Colors").getValue();
- byte[] colors = new byte[oldColors.length];
-
- int i = 0;
- for (int color : oldColors) {
- colors[i++] = FireworkColor.fromJavaID(color).getBedrockID();
- }
-
- newEffectData.put(new ByteArrayTag("FireworkColor", colors));
- }
-
- if (effectData.get("FadeColors") != null) {
- int[] oldColors = (int[]) effectData.get("FadeColors").getValue();
- byte[] colors = new byte[oldColors.length];
-
- int i = 0;
- for (int color : oldColors) {
- colors[i++] = FireworkColor.fromJavaID(color).getBedrockID();
- }
-
- newEffectData.put(new ByteArrayTag("FireworkFade", colors));
- }
-
- if (effectData.get("Trail") != null) {
- newEffectData.put(new ByteTag("FireworkTrail", MathUtils.convertByte(effectData.get("Trail").getValue())));
- }
-
- if (effectData.get("Flicker") != null) {
- newEffectData.put(new ByteTag("FireworkFlicker", MathUtils.convertByte(effectData.get("Flicker").getValue())));
- }
-
- explosions.remove(effect);
- explosions.add(newEffectData);
- }
- }
-
- @Override
- public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) {
- if (!itemTag.contains("Fireworks")) {
- return;
- }
- CompoundTag fireworks = itemTag.get("Fireworks");
- if (fireworks.contains("Flight")) {
- fireworks.put(new ByteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue())));
- }
-
- if (!itemTag.contains("Explosions")) {
- return;
- }
- ListTag explosions = fireworks.get("Explosions");
- for (Tag effect : explosions.getValue()) {
- CompoundTag effectData = (CompoundTag) effect;
-
- CompoundTag newEffectData = new CompoundTag("");
-
- if (effectData.get("FireworkType") != null) {
- newEffectData.put(new ByteTag("Type", MathUtils.convertByte(effectData.get("FireworkType").getValue())));
- }
-
- if (effectData.get("FireworkColor") != null) {
- byte[] oldColors = (byte[]) effectData.get("FireworkColor").getValue();
- int[] colors = new int[oldColors.length];
-
- int i = 0;
- for (byte color : oldColors) {
- colors[i++] = FireworkColor.fromBedrockID(color).getJavaID();
- }
-
- newEffectData.put(new IntArrayTag("Colors", colors));
- }
-
- if (effectData.get("FireworkFade") != null) {
- byte[] oldColors = (byte[]) effectData.get("FireworkFade").getValue();
- int[] colors = new int[oldColors.length];
-
- int i = 0;
- for (byte color : oldColors) {
- colors[i++] = FireworkColor.fromBedrockID(color).getJavaID();
- }
-
- newEffectData.put(new IntArrayTag("FadeColors", colors));
- }
-
- if (effectData.get("FireworkTrail") != null) {
- newEffectData.put(new ByteTag("Trail", MathUtils.convertByte(effectData.get("FireworkTrail").getValue())));
- }
-
- if (effectData.get("FireworkFlicker") != null) {
- newEffectData.put(new ByteTag("Flicker", MathUtils.convertByte(effectData.get("FireworkFlicker").getValue())));
- }
-
- explosions.remove(effect);
- explosions.add(newEffectData);
- }
- }
-
- @Override
- public boolean acceptItem(ItemEntry itemEntry) {
- return "minecraft:firework_rocket".equals(itemEntry.getJavaIdentifier());
- }
-}
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
deleted file mode 100644
index 8f5243366..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.java;
-
-import com.github.steveice10.mc.protocol.data.game.command.CommandNode;
-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.CommandParamData;
-import com.nukkitx.protocol.bedrock.data.command.CommandParamType;
-import com.nukkitx.protocol.bedrock.packet.AvailableCommandsPacket;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import lombok.Getter;
-import org.geysermc.connector.GeyserConnector;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-@Translator(packet = ServerDeclareCommandsPacket.class)
-public class JavaDeclareCommandsTranslator extends PacketTranslator {
- @Override
- public void translate(ServerDeclareCommandsPacket packet, GeyserSession session) {
- // Don't send command suggestions if they are disabled
- if (!session.getConnector().getConfig().isCommandSuggestions()) {
- session.getConnector().getLogger().debug("Not sending command suggestions as they are disabled.");
- return;
- }
- List commandData = new ArrayList<>();
- Int2ObjectMap commands = new Int2ObjectOpenHashMap<>();
- Int2ObjectMap> commandArgs = new Int2ObjectOpenHashMap<>();
-
- // Get the first node, it should be a root node
- CommandNode rootNode = packet.getNodes()[packet.getFirstNodeIndex()];
-
- // Loop through the root nodes to get all commands
- for (int nodeIndex : rootNode.getChildIndices()) {
- CommandNode node = packet.getNodes()[nodeIndex];
-
- // Make sure we don't have duplicated commands (happens if there is more than 1 root node)
- if (commands.containsKey(nodeIndex)) { continue; }
- if (commands.containsValue(node.getName())) { continue; }
-
- // Get and update the commandArgs list with the found arguments
- if (node.getChildIndices().length >= 1) {
- for (int childIndex : node.getChildIndices()) {
- commandArgs.putIfAbsent(nodeIndex, new ArrayList<>());
- commandArgs.get(nodeIndex).add(packet.getNodes()[childIndex]);
- }
- }
-
- // Insert the command name into the list
- commands.put(nodeIndex, node.getName());
- }
-
- // The command flags, not sure what these do apart from break things
- List flags = new ArrayList<>();
-
- // Loop through all the found commands
- for (int commandID : commands.keySet()) {
- String commandName = commands.get(commandID);
-
- // Create a basic alias
- CommandEnumData aliases = new CommandEnumData( commandName + "Aliases", new String[] { commandName.toLowerCase() }, false);
-
- // Get and parse all params
- CommandParamData[][] params = getParams(packet.getNodes()[commandID], packet.getNodes());
-
- // Build the completed command and add it to the final list
- CommandData data = new CommandData(commandName, session.getConnector().getCommandManager().getDescription(commandName), flags, (byte) 0, aliases, params);
- commandData.add(data);
- }
-
- // Add our commands to the AvailableCommandsPacket for the bedrock client
- AvailableCommandsPacket availableCommandsPacket = new AvailableCommandsPacket();
- for (CommandData data : commandData) {
- availableCommandsPacket.getCommands().add(data);
- }
-
- GeyserConnector.getInstance().getLogger().debug("Sending command packet of " + commandData.size() + " commands");
-
- // Finally, send the commands to the client
- session.sendUpstreamPacket(availableCommandsPacket);
- }
-
- /**
- * Build the command parameter array for the given command
- *
- * @param commandNode The command to build the parameters for
- * @param allNodes Every command node
- *
- * @return An array of parameter option arrays
- */
- private CommandParamData[][] getParams(CommandNode commandNode, CommandNode[] allNodes) {
- // Check if the command is an alias and redirect it
- if (commandNode.getRedirectIndex() != -1) {
- GeyserConnector.getInstance().getLogger().debug("Redirecting command " + commandNode.getName() + " to " + allNodes[commandNode.getRedirectIndex()].getName());
- commandNode = allNodes[commandNode.getRedirectIndex()];
- }
-
- if (commandNode.getChildIndices().length >= 1) {
- // Create the root param node and build all the children
- ParamInfo rootParam = new ParamInfo(commandNode, null);
- rootParam.buildChildren(allNodes);
-
- List treeData = rootParam.getTree();
- CommandParamData[][] params = new CommandParamData[treeData.size()][];
-
- // Fill the nested params array
- int i = 0;
- for (CommandParamData[] tree : treeData) {
- params[i] = tree;
- i++;
- }
-
- return params;
- }
-
- return new CommandParamData[0][0];
- }
-
- /**
- * Convert Java edition command types to Bedrock edition
- *
- * @param parser Command type to convert
- *
- * @return Bedrock parameter data type
- */
- private CommandParamType mapCommandType(CommandParser parser) {
- if (parser == null) { return CommandParamType.STRING; }
-
- switch (parser) {
- case FLOAT:
- return CommandParamType.FLOAT;
-
- case INTEGER:
- return CommandParamType.INT;
-
- case ENTITY:
- case GAME_PROFILE:
- return CommandParamType.TARGET;
-
- case BLOCK_POS:
- return CommandParamType.BLOCK_POSITION;
-
- case COLUMN_POS:
- case VEC3:
- return CommandParamType.POSITION;
-
- case MESSAGE:
- return CommandParamType.MESSAGE;
-
- case NBT:
- case NBT_COMPOUND_TAG:
- case NBT_TAG:
- case NBT_PATH:
- return CommandParamType.JSON;
-
- case RESOURCE_LOCATION:
- return CommandParamType.FILE_PATH;
-
- case INT_RANGE:
- return CommandParamType.INT_RANGE;
-
- case BOOL:
- case DOUBLE:
- case STRING:
- case VEC2:
- case BLOCK_STATE:
- case BLOCK_PREDICATE:
- case ITEM_STACK:
- case ITEM_PREDICATE:
- case COLOR:
- case COMPONENT:
- case OBJECTIVE:
- case OBJECTIVE_CRITERIA:
- case OPERATION: // Possibly OPERATOR
- case PARTICLE:
- case ROTATION:
- case SCOREBOARD_SLOT:
- case SCORE_HOLDER:
- case SWIZZLE:
- case TEAM:
- case ITEM_SLOT:
- case MOB_EFFECT:
- case FUNCTION:
- case ENTITY_ANCHOR:
- case RANGE:
- case FLOAT_RANGE:
- case ITEM_ENCHANTMENT:
- case ENTITY_SUMMON:
- case DIMENSION:
- case TIME:
- default:
- return CommandParamType.STRING;
- }
- }
-
- @Getter
- private class ParamInfo {
- private CommandNode paramNode;
- private CommandParamData paramData;
- private List children;
-
- /**
- * Create a new parameter info object
- *
- * @param paramNode CommandNode the parameter is for
- * @param paramData The existing parameters for the command
- */
- public ParamInfo(CommandNode paramNode, CommandParamData paramData) {
- this.paramNode = paramNode;
- this.paramData = paramData;
- this.children = new ArrayList<>();
- }
-
- /**
- * Build the array of all the child parameters (recursive)
- *
- * @param allNodes Every command node
- */
- public void buildChildren(CommandNode[] allNodes) {
- int enumIndex = -1;
-
- for (int paramID : paramNode.getChildIndices()) {
- CommandNode paramNode = allNodes[paramID];
-
- if (paramNode.getParser() == null) {
- if (enumIndex == -1) {
- enumIndex = children.size();
-
- // Create the new enum command
- CommandEnumData enumData = new CommandEnumData(paramNode.getName(), new String[] { paramNode.getName() }, false);
- children.add(new ParamInfo(paramNode, new CommandParamData(paramNode.getName(), false, enumData, mapCommandType(paramNode.getParser()), null, Collections.emptyList())));
- } else {
- // Get the existing enum
- ParamInfo enumParamInfo = children.get(enumIndex);
-
- // Extend the current list of enum values
- String[] enumOptions = Arrays.copyOf(enumParamInfo.getParamData().getEnumData().getValues(), enumParamInfo.getParamData().getEnumData().getValues().length + 1);
- enumOptions[enumOptions.length - 1] = paramNode.getName();
-
- // Re-create the command using the updated values
- CommandEnumData enumData = new CommandEnumData(enumParamInfo.getParamData().getEnumData().getName(), enumOptions, false);
- children.set(enumIndex, new ParamInfo(enumParamInfo.getParamNode(), new CommandParamData(enumParamInfo.getParamData().getName(), false, enumData, enumParamInfo.getParamData().getType(), null, Collections.emptyList())));
- }
- }else{
- // Put the non-enum param into the list
- children.add(new ParamInfo(paramNode, new CommandParamData(paramNode.getName(), false, null, mapCommandType(paramNode.getParser()), null, Collections.emptyList())));
- }
- }
-
- // Recursively build all child options
- for (ParamInfo child : children) {
- child.buildChildren(allNodes);
- }
- }
-
- /**
- * Get the tree of every parameter node (recursive)
- *
- * @return List of parameter options arrays for the command
- */
- public List getTree() {
- List treeParamData = new ArrayList<>();
-
- for (ParamInfo child : children) {
- // Get the tree from the child
- List childTree = child.getTree();
-
- // Un-pack the tree append the child node to it and push into the list
- for (CommandParamData[] subchild : childTree) {
- CommandParamData[] tmpTree = new ArrayList() {
- {
- add(child.getParamData());
- addAll(Arrays.asList(subchild));
- }
- }.toArray(new CommandParamData[0]);
-
- treeParamData.add(tmpTree);
- }
-
- // If we have no more child parameters just the child
- if (childTree.size() == 0) {
- treeParamData.add(new CommandParamData[] { child.getParamData() });
- }
- }
-
- return treeParamData;
- }
- }
-}
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
deleted file mode 100644
index 70303baa0..000000000
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.network.translators.java;
-
-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.packet.ingame.server.ServerDeclareRecipesPacket;
-import com.nukkitx.nbt.NbtMap;
-import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
-import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
-import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
-import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
-import it.unimi.dsi.fastutil.ints.IntSet;
-import lombok.AllArgsConstructor;
-import lombok.EqualsAndHashCode;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.network.translators.item.*;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-@Translator(packet = ServerDeclareRecipesPacket.class)
-public class JavaDeclareRecipesTranslator extends PacketTranslator {
-
- @Override
- public void translate(ServerDeclareRecipesPacket packet, GeyserSession session) {
- CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
- craftingDataPacket.setCleanRecipes(true);
- for (Recipe recipe : packet.getRecipes()) {
- switch (recipe.getType()) {
- case CRAFTING_SHAPELESS: {
- ShapelessRecipeData shapelessRecipeData = (ShapelessRecipeData) recipe.getData();
- ItemData output = ItemTranslator.translateToBedrock(session, shapelessRecipeData.getResult());
- output = ItemData.of(output.getId(), output.getDamage(), output.getCount()); //strip NBT
- ItemData[][] inputCombinations = combinations(session, shapelessRecipeData.getIngredients());
- for (ItemData[] inputs : inputCombinations) {
- UUID uuid = UUID.randomUUID();
- craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
- inputs, new ItemData[]{output}, uuid, "crafting_table", 0));
- }
- break;
- }
- case CRAFTING_SHAPED: {
- ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData();
- ItemData output = ItemTranslator.translateToBedrock(session, shapedRecipeData.getResult());
- output = ItemData.of(output.getId(), output.getDamage(), output.getCount()); //strip NBT
- ItemData[][] inputCombinations = combinations(session, shapedRecipeData.getIngredients());
- for (ItemData[] inputs : inputCombinations) {
- UUID uuid = UUID.randomUUID();
- craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
- shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), inputs,
- new ItemData[]{output}, uuid, "crafting_table", 0));
- }
- break;
- }
-
- // These recipes are enabled by sending a special recipe
- case CRAFTING_SPECIAL_BOOKCLONING: {
- craftingDataPacket.getCraftingData().add(RecipeRegistry.BOOK_CLONING_RECIPE_DATA);
- break;
- }
- case CRAFTING_SPECIAL_REPAIRITEM: {
- craftingDataPacket.getCraftingData().add(RecipeRegistry.TOOL_REPAIRING_RECIPE_DATA);
- break;
- }
-
- // Java doesn't actually tell us the recipes so we need to calculate this ahead of time.
- case CRAFTING_SPECIAL_FIREWORK_ROCKET: {
- craftingDataPacket.getCraftingData().addAll(RecipeRegistry.FIREWORK_ROCKET_RECIPES);
- break;
- }
- case CRAFTING_SPECIAL_FIREWORK_STAR: {
- craftingDataPacket.getCraftingData().addAll(RecipeRegistry.FIREWORK_STAR_RECIPES);
- break;
- }
- case CRAFTING_SPECIAL_SHULKERBOXCOLORING: {
- craftingDataPacket.getCraftingData().addAll(RecipeRegistry.SHULKER_BOX_DYEING_RECIPES);
- break;
- }
- case CRAFTING_SPECIAL_SUSPICIOUSSTEW: {
- craftingDataPacket.getCraftingData().addAll(RecipeRegistry.SUSPICIOUS_STEW_RECIPES);
- break;
- }
- case CRAFTING_SPECIAL_TIPPEDARROW: {
- craftingDataPacket.getCraftingData().addAll(RecipeRegistry.TIPPED_ARROW_RECIPES);
- break;
- }
- case CRAFTING_SPECIAL_ARMORDYE: {
- // This one's even worse since it's not actually on Bedrock, but it still works!
- craftingDataPacket.getCraftingData().addAll(RecipeRegistry.LEATHER_DYEING_RECIPES);
- break;
- }
- }
- }
- craftingDataPacket.getPotionMixData().addAll(PotionMixRegistry.POTION_MIXES);
- session.sendUpstreamPacket(craftingDataPacket);
- }
-
- //TODO: rewrite
- private ItemData[][] combinations(GeyserSession session, Ingredient[] ingredients) {
- Map