From c7fade295ea93d31752f38dcf879ad70ce8c23d5 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 24 Dec 2020 20:43:24 -0500 Subject: [PATCH] Add swap support for creative mode; start on cartography table --- .../inventory/InventoryTranslator.java | 53 +++++++++-- .../CartographyInventoryTranslator.java | 95 +++++++++++++++++++ .../translators/LoomInventoryTranslator.java | 8 +- 3 files changed, 145 insertions(+), 11 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/CartographyInventoryTranslator.java 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 index b3f2475d..3e5bf0c6 100644 --- 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 @@ -82,6 +82,7 @@ public abstract class InventoryTranslator { put(WindowType.ANVIL, new AnvilInventoryTranslator()); put(WindowType.BEACON, new BeaconInventoryTranslator()); put(WindowType.BREWING_STAND, new BrewingInventoryTranslator()); + put(WindowType.CARTOGRAPHY, new CartographyInventoryTranslator()); put(WindowType.CRAFTING, new CraftingInventoryTranslator()); put(WindowType.ENCHANTMENT, new EnchantingInventoryTranslator()); put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator()); @@ -96,7 +97,6 @@ public abstract class InventoryTranslator { put(WindowType.HOPPER, new GenericBlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER)); /* todo */ - //put(WindowType.CARTOGRAPHY // horse } }; @@ -122,9 +122,11 @@ public abstract class InventoryTranslator { * Should be overwritten in cases where specific inventories should reject an item being in a specific spot. * For examples, looms use this to reject items that are dyes in Bedrock but not in Java. * + * javaSourceSlot will be -1 if the cursor is the source + * * @return true if this transfer should be rejected */ - public boolean shouldRejectItemPlace(GeyserSession session, Inventory inventory, int javaDestinationSlot) { + public boolean shouldRejectItemPlace(GeyserSession session, Inventory inventory, int javaSourceSlot, int javaDestinationSlot) { return false; } @@ -188,9 +190,10 @@ public abstract class InventoryTranslator { return rejectRequest(request); } + int sourceSlot = bedrockSlotToJava(transferAction.getSource()); int destSlot = bedrockSlotToJava(transferAction.getDestination()); - if (shouldRejectItemPlace(session, inventory, destSlot)) { + if (shouldRejectItemPlace(session, inventory, isCursor(transferAction.getSource()) ? -1 :sourceSlot, destSlot)) { // This item would not be here in Java return rejectRequest(request, false); } @@ -199,7 +202,6 @@ public abstract class InventoryTranslator { return rejectRequest(request); } else if (session.getGameMode().equals(GameMode.CREATIVE) && inventory instanceof PlayerInventory) { // TODO: does the Java server use this stuff all the time in creative? // Creative acts a little differently because it just edits slots - int sourceSlot = bedrockSlotToJava(transferAction.getSource()); boolean sourceIsCursor = isCursor(transferAction.getSource()); boolean destIsCursor = isCursor(transferAction.getDestination()); @@ -228,6 +230,15 @@ public abstract class InventoryTranslator { affectedSlots.add(destSlot); break; } + } else { + // Delete the source since we're moving it + inventory.setItem(sourceSlot, GeyserItemStack.EMPTY); + ClientCreativeInventoryActionPacket creativeActionPacket = new ClientCreativeInventoryActionPacket( + sourceSlot, + new ItemStack(0) + ); + session.sendDownstreamPacket(creativeActionPacket); + affectedSlots.add(sourceSlot); } // Update the item count with however much the client took newItem.setAmount(transferAction.getCount()); @@ -273,7 +284,6 @@ public abstract class InventoryTranslator { } } } else if (isCursor(transferAction.getDestination())) { //picking up into cursor - int sourceSlot = bedrockSlotToJava(transferAction.getSource()); GeyserItemStack sourceItem = plan.getItem(sourceSlot); int sourceAmount = sourceItem.getAmount(); if (cursor.isEmpty()) { //picking up into empty cursor @@ -303,7 +313,6 @@ public abstract class InventoryTranslator { if (!cursor.isEmpty()) { //TODO: handle slot transfer when cursor is already in use (temp slot) return rejectRequest(request); } - int sourceSlot = bedrockSlotToJava(transferAction.getSource()); int sourceAmount = plan.getItem(sourceSlot).getAmount(); if (transferAction.getCount() == sourceAmount) { //transfer all plan.add(Click.LEFT, sourceSlot); //pickup source @@ -339,7 +348,37 @@ public abstract class InventoryTranslator { if (!(checkNetId(session, inventory, swapAction.getSource()) && checkNetId(session, inventory, swapAction.getDestination()))) return rejectRequest(request); - if (isCursor(swapAction.getSource()) && isCursor(swapAction.getDestination())) { //??? + if (session.getGameMode().equals(GameMode.CREATIVE) && inventory instanceof PlayerInventory) { + int destSlot = bedrockSlotToJava(swapAction.getDestination()); + GeyserItemStack oldSourceItem; + GeyserItemStack oldDestinationItem = inventory.getItem(destSlot); + if (isCursor(swapAction.getSource())) { + oldSourceItem = session.getPlayerInventory().getCursor(); + session.getPlayerInventory().setCursor(oldDestinationItem); + } else { + int sourceSlot = bedrockSlotToJava(swapAction.getSource()); + oldSourceItem = inventory.getItem(sourceSlot); + ClientCreativeInventoryActionPacket creativeActionPacket = new ClientCreativeInventoryActionPacket( + sourceSlot, + oldDestinationItem.isEmpty() ? new ItemStack(0) : oldDestinationItem.getItemStack() // isEmpty check... just in case + ); + System.out.println(creativeActionPacket); + session.sendDownstreamPacket(creativeActionPacket); + inventory.setItem(sourceSlot, oldDestinationItem); + } + if (isCursor(swapAction.getDestination())) { + session.getPlayerInventory().setCursor(oldSourceItem); + } else { + ClientCreativeInventoryActionPacket creativeActionPacket = new ClientCreativeInventoryActionPacket( + destSlot, + oldSourceItem.isEmpty() ? new ItemStack(0) : oldSourceItem.getItemStack() + ); + System.out.println(creativeActionPacket); + session.sendDownstreamPacket(creativeActionPacket); + inventory.setItem(destSlot, oldSourceItem); + } + + } else if (isCursor(swapAction.getSource()) && isCursor(swapAction.getDestination())) { //??? return rejectRequest(request); } else if (isCursor(swapAction.getSource())) { //swap cursor int destSlot = bedrockSlotToJava(swapAction.getDestination()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/CartographyInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/CartographyInventoryTranslator.java new file mode 100644 index 00000000..1ce6d078 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/CartographyInventoryTranslator.java @@ -0,0 +1,95 @@ +/* + * 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.translators; + +import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData; +import org.geysermc.connector.inventory.GeyserItemStack; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot; +import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater; +import org.geysermc.connector.network.translators.item.ItemRegistry; + +public class CartographyInventoryTranslator extends AbstractBlockInventoryTranslator { + public CartographyInventoryTranslator() { + super(3, "minecraft:cartography_table", ContainerType.CARTOGRAPHY, UIInventoryUpdater.INSTANCE); + } + + @Override + public boolean shouldRejectItemPlace(GeyserSession session, Inventory inventory, int javaSourceSlot, int javaDestinationSlot) { + if (javaDestinationSlot == 1) { + // Bedrock Edition can use a compass to create locator maps in the ADDITIONAL slot + GeyserItemStack itemStack = javaSourceSlot == -1 ? session.getPlayerInventory().getCursor() : inventory.getItem(javaSourceSlot); + return ItemRegistry.getItem(itemStack.getItemStack()).getJavaIdentifier().equals("minecraft:compass"); + } else if (javaSourceSlot == 2) { + // Java doesn't allow an item to be renamed; this is why CARTOGRAPHY_ADDITIONAL could remain empty for Bedrock + return inventory.getItem(1).isEmpty(); + } + return false; + } + + @Override + public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { + if (slotInfoData.getContainer() == ContainerSlotType.CARTOGRAPHY_INPUT) { + return 0; + } + if (slotInfoData.getContainer() == ContainerSlotType.CARTOGRAPHY_ADDITIONAL) { + return 1; + } + if (slotInfoData.getContainer() == ContainerSlotType.CARTOGRAPHY_RESULT || slotInfoData.getContainer() == ContainerSlotType.CREATIVE_OUTPUT) { + return 2; + } + return super.bedrockSlotToJava(slotInfoData); + } + + @Override + public BedrockContainerSlot javaSlotToBedrockContainer(int slot) { + switch (slot) { + case 0: + return new BedrockContainerSlot(ContainerSlotType.CARTOGRAPHY_INPUT, 12); + case 1: + return new BedrockContainerSlot(ContainerSlotType.CARTOGRAPHY_ADDITIONAL, 13); + case 2: + return new BedrockContainerSlot(ContainerSlotType.CARTOGRAPHY_RESULT, 50); + } + return super.javaSlotToBedrockContainer(slot); + } + + @Override + public int javaSlotToBedrock(int slot) { + switch (slot) { + case 0: + return 12; + case 1: + return 13; + case 2: + return 50; + } + return super.javaSlotToBedrock(slot); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/LoomInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/LoomInventoryTranslator.java index bacc83a0..47f21379 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/LoomInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/LoomInventoryTranslator.java @@ -101,11 +101,11 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { } @Override - public boolean shouldRejectItemPlace(GeyserSession session, Inventory inventory, int javaDestinationSlot) { + public boolean shouldRejectItemPlace(GeyserSession session, Inventory inventory, int javaSourceSlot, int javaDestinationSlot) { if (javaDestinationSlot != 1) { return false; } - GeyserItemStack itemStack = session.getPlayerInventory().getCursor(); + GeyserItemStack itemStack = javaSourceSlot == -1 ? session.getPlayerInventory().getCursor() : inventory.getItem(javaSourceSlot); if (itemStack.isEmpty()) { return false; } @@ -129,9 +129,9 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { } CraftResultsDeprecatedStackRequestActionData craftData = (CraftResultsDeprecatedStackRequestActionData) data; // Get the patterns compound tag - List newblockEntityTag = craftData.getResultItems()[0].getTag().getList("Patterns", NbtType.COMPOUND); + List newBlockEntityTag = craftData.getResultItems()[0].getTag().getList("Patterns", NbtType.COMPOUND); // Get the pattern that the Bedrock client requests - the last pattern in the Patterns list - NbtMap pattern = newblockEntityTag.get(newblockEntityTag.size() - 1); + NbtMap pattern = newBlockEntityTag.get(newBlockEntityTag.size() - 1); // Get the Java index of this pattern int index = PATTERN_TO_INDEX.getOrDefault(pattern.getString("Pattern"), -1); if (index == -1) {