mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-02-18 03:16:29 +01:00
Some refactoring and bug fixes
Still much to do. Inventory desyncing when crafting will be fixed soon.
This commit is contained in:
parent
5e5aeed578
commit
1a9aa4255f
35 changed files with 1282 additions and 702 deletions
|
@ -46,6 +46,8 @@ import lombok.Getter;
|
||||||
import org.geysermc.connector.network.translators.bedrock.*;
|
import org.geysermc.connector.network.translators.bedrock.*;
|
||||||
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||||
import org.geysermc.connector.network.translators.inventory.*;
|
import org.geysermc.connector.network.translators.inventory.*;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
||||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||||
import org.geysermc.connector.network.translators.java.*;
|
import org.geysermc.connector.network.translators.java.*;
|
||||||
import org.geysermc.connector.network.translators.java.entity.*;
|
import org.geysermc.connector.network.translators.java.entity.*;
|
||||||
|
@ -72,7 +74,7 @@ public class TranslatorsInit {
|
||||||
private static BlockTranslator blockTranslator;
|
private static BlockTranslator blockTranslator;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static Map<WindowType, InventoryTranslator> inventoryTranslators = new HashMap<WindowType, InventoryTranslator>();
|
private static Map<WindowType, InventoryTranslator> inventoryTranslators = new HashMap<>();
|
||||||
|
|
||||||
private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag();
|
private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag();
|
||||||
public static final byte[] EMPTY_LEVEL_CHUNK_DATA;
|
public static final byte[] EMPTY_LEVEL_CHUNK_DATA;
|
||||||
|
@ -127,6 +129,7 @@ public class TranslatorsInit {
|
||||||
Registry.registerJava(ServerPlayerSetExperiencePacket.class, new JavaPlayerSetExperienceTranslator());
|
Registry.registerJava(ServerPlayerSetExperiencePacket.class, new JavaPlayerSetExperienceTranslator());
|
||||||
Registry.registerJava(ServerPlayerHealthPacket.class, new JavaPlayerHealthTranslator());
|
Registry.registerJava(ServerPlayerHealthPacket.class, new JavaPlayerHealthTranslator());
|
||||||
Registry.registerJava(ServerPlayerActionAckPacket.class, new JavaPlayerActionAckTranslator());
|
Registry.registerJava(ServerPlayerActionAckPacket.class, new JavaPlayerActionAckTranslator());
|
||||||
|
Registry.registerJava(ServerPlayerChangeHeldItemPacket.class, new JavaPlayerChangeHeldItemTranslator());
|
||||||
|
|
||||||
// FIXME: This translator messes with allowing flight in creative mode. Will need to be addressed later
|
// FIXME: This translator messes with allowing flight in creative mode. Will need to be addressed later
|
||||||
// Registry.registerJava(ServerPlayerAbilitiesPacket.class, new JavaPlayerAbilitiesTranslator());
|
// Registry.registerJava(ServerPlayerAbilitiesPacket.class, new JavaPlayerAbilitiesTranslator());
|
||||||
|
@ -176,9 +179,9 @@ public class TranslatorsInit {
|
||||||
inventoryTranslators.put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36));
|
inventoryTranslators.put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36));
|
||||||
inventoryTranslators.put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45));
|
inventoryTranslators.put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45));
|
||||||
inventoryTranslators.put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54));
|
inventoryTranslators.put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54));
|
||||||
inventoryTranslators.put(WindowType.BREWING_STAND, new BrewingStandInventoryTranslator());
|
inventoryTranslators.put(WindowType.BREWING_STAND, new BrewingInventoryTranslator());
|
||||||
inventoryTranslators.put(WindowType.ANVIL, new AnvilInventoryTranslator());
|
inventoryTranslators.put(WindowType.ANVIL, new AnvilInventoryTranslator());
|
||||||
inventoryTranslators.put(WindowType.CRAFTING, new CraftingTableInventoryTranslator());
|
inventoryTranslators.put(WindowType.CRAFTING, new CraftingInventoryTranslator());
|
||||||
//inventoryTranslators.put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO
|
//inventoryTranslators.put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO
|
||||||
|
|
||||||
InventoryTranslator furnace = new FurnaceInventoryTranslator();
|
InventoryTranslator furnace = new FurnaceInventoryTranslator();
|
||||||
|
@ -186,9 +189,10 @@ public class TranslatorsInit {
|
||||||
inventoryTranslators.put(WindowType.BLAST_FURNACE, furnace);
|
inventoryTranslators.put(WindowType.BLAST_FURNACE, furnace);
|
||||||
inventoryTranslators.put(WindowType.SMOKER, furnace);
|
inventoryTranslators.put(WindowType.SMOKER, furnace);
|
||||||
|
|
||||||
inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER));
|
InventoryUpdater containerUpdater = new ContainerInventoryUpdater();
|
||||||
inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER));
|
inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER, containerUpdater));
|
||||||
inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, "minecraft:shulker_box[facing=north]", ContainerType.CONTAINER));
|
inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, containerUpdater));
|
||||||
|
inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, "minecraft:shulker_box[facing=north]", ContainerType.CONTAINER, containerUpdater));
|
||||||
//inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO
|
//inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,7 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.bedrock;
|
package org.geysermc.connector.network.translators.bedrock;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.window.*;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientConfirmTransactionPacket;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCreativeInventoryActionPacket;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket;
|
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
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.metadata.Position;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
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.Hand;
|
||||||
|
@ -41,382 +35,31 @@ 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.ClientPlayerActionPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.InventorySource;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.ItemData;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
|
import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.inventory.PlayerInventory;
|
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
import org.geysermc.connector.utils.InventoryUtils;
|
||||||
import org.geysermc.connector.network.translators.inventory.SlotType;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class BedrockInventoryTransactionTranslator extends PacketTranslator<InventoryTransactionPacket> {
|
public class BedrockInventoryTransactionTranslator extends PacketTranslator<InventoryTransactionPacket> {
|
||||||
private final ItemStack refreshItem = new ItemStack(1, 127, new CompoundTag(""));
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(InventoryTransactionPacket packet, GeyserSession session) {
|
public void translate(InventoryTransactionPacket packet, GeyserSession session) {
|
||||||
switch (packet.getTransactionType()) {
|
switch (packet.getTransactionType()) {
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
for (InventoryAction action : packet.getActions()) {
|
|
||||||
if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT ||
|
|
||||||
action.getSource().getContainerId() == ContainerId.CRAFTING_RESULT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Inventory inventory = session.getInventoryCache().getOpenInventory();
|
Inventory inventory = session.getInventoryCache().getOpenInventory();
|
||||||
if (inventory == null)
|
if (inventory == null) inventory = session.getInventory();
|
||||||
inventory = session.getInventory();
|
TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()).translateActions(session, inventory, packet.getActions());
|
||||||
InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType());
|
|
||||||
|
|
||||||
int craftSlot = session.getCraftSlot();
|
|
||||||
session.setCraftSlot(0);
|
|
||||||
|
|
||||||
if (session.getGameMode() == GameMode.CREATIVE && inventory.getId() == 0) {
|
|
||||||
ItemStack javaItem;
|
|
||||||
for (InventoryAction action : packet.getActions()) {
|
|
||||||
switch (action.getSource().getContainerId()) {
|
|
||||||
case ContainerId.INVENTORY:
|
|
||||||
case ContainerId.ARMOR:
|
|
||||||
case ContainerId.OFFHAND:
|
|
||||||
int javaSlot = translator.bedrockSlotToJava(action);
|
|
||||||
if (action.getToItem().getId() == 0) {
|
|
||||||
javaItem = new ItemStack(-1, 0, null);
|
|
||||||
} else {
|
|
||||||
javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem());
|
|
||||||
if (javaItem.getId() == 0) { //item missing mapping
|
|
||||||
translator.updateInventory(session, inventory);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, fixStack(javaItem));
|
|
||||||
session.getDownstream().getSession().send(creativePacket);
|
|
||||||
inventory.setItem(javaSlot, javaItem);
|
|
||||||
break;
|
|
||||||
case ContainerId.NONE:
|
|
||||||
if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION &&
|
|
||||||
action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) {
|
|
||||||
javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem());
|
|
||||||
if (javaItem.getId() == 0) { //item missing mapping
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, fixStack(javaItem));
|
|
||||||
session.getDownstream().getSession().send(creativeDropPacket);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InventoryAction worldAction = null;
|
|
||||||
InventoryAction cursorAction = null;
|
|
||||||
for (InventoryAction action : packet.getActions()) {
|
|
||||||
if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION) {
|
|
||||||
worldAction = action;
|
|
||||||
} else if (action.getSource().getContainerId() == ContainerId.CURSOR && action.getSlot() == 0) {
|
|
||||||
cursorAction = action;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<InventoryAction> actions = packet.getActions();
|
|
||||||
if (inventory.getWindowType() == WindowType.ANVIL) {
|
|
||||||
InventoryAction anvilResult = null;
|
|
||||||
InventoryAction anvilInput = null;
|
|
||||||
for (InventoryAction action : packet.getActions()) {
|
|
||||||
if (action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL) {
|
|
||||||
//useless packet
|
|
||||||
return;
|
|
||||||
} else if (action.getSource().getContainerId() == ContainerId.ANVIL_RESULT) {
|
|
||||||
anvilResult = action;
|
|
||||||
} else if (translator.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;
|
|
||||||
com.nukkitx.nbt.tag.CompoundTag tag = itemName.getTag();
|
|
||||||
if (tag != null) {
|
|
||||||
rename = tag.getAsCompound("display").getAsString("Name");
|
|
||||||
} else {
|
|
||||||
rename = "";
|
|
||||||
}
|
|
||||||
ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename);
|
|
||||||
session.getDownstream().getSession().send(renameItemPacket);
|
|
||||||
}
|
|
||||||
if (anvilResult != null) {
|
|
||||||
//client will send another packet to grab anvil output
|
|
||||||
//this packet was only used to send rename packet
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actions.size() == 2) {
|
|
||||||
if (worldAction != null) {
|
|
||||||
//find container action
|
|
||||||
InventoryAction containerAction = null;
|
|
||||||
for (InventoryAction action : actions) {
|
|
||||||
if (action != worldAction) {
|
|
||||||
containerAction = action;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (containerAction != null && worldAction.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) {
|
|
||||||
//quick dropping from hotbar?
|
|
||||||
if (session.getInventoryCache().getOpenInventory() == null && containerAction.getSource().getContainerId() == ContainerId.INVENTORY) {
|
|
||||||
int heldSlot = session.getInventory().getHeldItemSlot();
|
|
||||||
if (containerAction.getSlot() == heldSlot) {
|
|
||||||
ClientPlayerActionPacket actionPacket = new ClientPlayerActionPacket(
|
|
||||||
containerAction.getToItem().getCount() == 0 ? PlayerAction.DROP_ITEM_STACK : PlayerAction.DROP_ITEM,
|
|
||||||
new Position(0, 0, 0), BlockFace.DOWN);
|
|
||||||
session.getDownstream().getSession().send(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 = containerAction.getFromItem().getCount() - containerAction.getToItem().getCount();
|
|
||||||
if (containerAction != cursorAction) { //dropping directly from inventory
|
|
||||||
int javaSlot = translator.bedrockSlotToJava(containerAction);
|
|
||||||
if (dropAmount == containerAction.getFromItem().getCount()) {
|
|
||||||
ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(),
|
|
||||||
inventory.getTransactionId().getAndIncrement(),
|
|
||||||
javaSlot, null, WindowAction.DROP_ITEM,
|
|
||||||
DropItemParam.DROP_SELECTED_STACK);
|
|
||||||
session.getDownstream().getSession().send(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.getDownstream().getSession().send(dropPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ItemStack item = session.getInventory().getItem(javaSlot);
|
|
||||||
if (item != null) {
|
|
||||||
session.getInventory().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.getDownstream().getSession().send(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) {
|
|
||||||
//find container action
|
|
||||||
InventoryAction containerAction = null;
|
|
||||||
for (InventoryAction action : actions) {
|
|
||||||
if (action != cursorAction) {
|
|
||||||
containerAction = action;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (containerAction != null) {
|
|
||||||
//left/right click
|
|
||||||
List<ClickAction> plan = new ArrayList<>();
|
|
||||||
ItemStack translatedCursor = cursorAction.getFromItem().isValid() ?
|
|
||||||
TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getFromItem()) : null;
|
|
||||||
ItemStack currentCursor = session.getInventory().getCursor();
|
|
||||||
boolean refresh = false;
|
|
||||||
if (currentCursor != null) {
|
|
||||||
if (translatedCursor != null) {
|
|
||||||
refresh = !(currentCursor.getId() == translatedCursor.getId() &&
|
|
||||||
currentCursor.getAmount() == translatedCursor.getAmount());
|
|
||||||
} else {
|
|
||||||
refresh = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int javaSlot = translator.bedrockSlotToJava(containerAction);
|
|
||||||
if (cursorAction.getFromItem().equals(containerAction.getToItem()) &&
|
|
||||||
containerAction.getFromItem().equals(cursorAction.getToItem()) &&
|
|
||||||
!canStack(cursorAction.getFromItem(), containerAction.getFromItem())) { //simple swap
|
|
||||||
Click.LEFT.onSlot(javaSlot, plan);
|
|
||||||
} else if (cursorAction.getFromItem().getCount() > cursorAction.getToItem().getCount()) { //release
|
|
||||||
if (cursorAction.getToItem().getCount() == 0) {
|
|
||||||
Click.LEFT.onSlot(javaSlot, plan);
|
|
||||||
} else {
|
|
||||||
int difference = cursorAction.getFromItem().getCount() - cursorAction.getToItem().getCount();
|
|
||||||
for (int i = 0; i < difference; i++) {
|
|
||||||
Click.RIGHT.onSlot(javaSlot, plan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { //pickup
|
|
||||||
if (cursorAction.getFromItem().getCount() == 0) {
|
|
||||||
if (containerAction.getToItem().getCount() == 0) { //pickup all
|
|
||||||
Click.LEFT.onSlot(javaSlot, plan);
|
|
||||||
} else { //pickup some
|
|
||||||
if (translator.getSlotType(javaSlot) == SlotType.FURNACE_OUTPUT ||
|
|
||||||
containerAction.getToItem().getCount() == containerAction.getFromItem().getCount() / 2) { //right click
|
|
||||||
Click.RIGHT.onSlot(javaSlot, plan);
|
|
||||||
} else {
|
|
||||||
Click.LEFT.onSlot(javaSlot, plan);
|
|
||||||
int difference = containerAction.getFromItem().getCount() - cursorAction.getToItem().getCount();
|
|
||||||
for (int i = 0; i < difference; i++) {
|
|
||||||
Click.RIGHT.onSlot(javaSlot, plan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { //pickup into non-empty cursor
|
|
||||||
if (translator.getSlotType(javaSlot) == SlotType.FURNACE_OUTPUT) {
|
|
||||||
if (containerAction.getToItem().getCount() == 0) {
|
|
||||||
Click.LEFT.onSlot(javaSlot, plan);
|
|
||||||
} else {
|
|
||||||
ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(),
|
|
||||||
inventory.getTransactionId().getAndIncrement(),
|
|
||||||
javaSlot, refreshItem, WindowAction.SHIFT_CLICK_ITEM,
|
|
||||||
ShiftClickItemParam.LEFT_CLICK);
|
|
||||||
session.getDownstream().getSession().send(shiftClickPacket);
|
|
||||||
translator.updateInventory(session, inventory);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (translator.getSlotType(javaSlot) == SlotType.OUTPUT) {
|
|
||||||
Click.LEFT.onSlot(javaSlot, plan);
|
|
||||||
} else {
|
|
||||||
int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot));
|
|
||||||
if (cursorSlot != -1) {
|
|
||||||
Click.LEFT.onSlot(cursorSlot, plan);
|
|
||||||
} else {
|
|
||||||
translator.updateInventory(session, inventory);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Click.LEFT.onSlot(javaSlot, plan);
|
|
||||||
int difference = cursorAction.getToItem().getCount() - cursorAction.getFromItem().getCount();
|
|
||||||
for (int i = 0; i < difference; i++) {
|
|
||||||
Click.RIGHT.onSlot(cursorSlot, plan);
|
|
||||||
}
|
|
||||||
Click.LEFT.onSlot(javaSlot, plan);
|
|
||||||
Click.LEFT.onSlot(cursorSlot, plan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
executePlan(session, inventory, translator, plan, refresh);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
List<ClickAction> plan = new ArrayList<>();
|
|
||||||
InventoryAction fromAction;
|
|
||||||
InventoryAction 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 ||
|
|
||||||
canStack(session.getInventory().getCursor(), inventory.getItem(toSlot)))) {
|
|
||||||
boolean refresh = false;
|
|
||||||
if (fromAction.getToItem().getCount() == 0) {
|
|
||||||
refresh = true;
|
|
||||||
Click.LEFT.onSlot(toSlot, plan);
|
|
||||||
if (craftSlot != -1) {
|
|
||||||
Click.LEFT.onSlot(craftSlot, plan);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount();
|
|
||||||
for (int i = 0; i < difference; i++) {
|
|
||||||
Click.RIGHT.onSlot(toSlot, plan);
|
|
||||||
}
|
|
||||||
session.setCraftSlot(craftSlot);
|
|
||||||
}
|
|
||||||
executePlan(session, inventory, translator, plan, 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));
|
|
||||||
if (cursorSlot != -1) {
|
|
||||||
Click.LEFT.onSlot(cursorSlot, plan);
|
|
||||||
} else {
|
|
||||||
translator.updateInventory(session, inventory);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((fromAction.getFromItem().equals(toAction.getToItem()) && !canStack(fromAction.getFromItem(), toAction.getFromItem())) || fromAction.getToItem().getId() == 0) { //slot swap
|
|
||||||
Click.LEFT.onSlot(fromSlot, plan);
|
|
||||||
Click.LEFT.onSlot(toSlot, plan);
|
|
||||||
if (fromAction.getToItem().getId() != 0) {
|
|
||||||
Click.LEFT.onSlot(fromSlot, plan);
|
|
||||||
}
|
|
||||||
} else if (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, refreshItem, WindowAction.SHIFT_CLICK_ITEM,
|
|
||||||
ShiftClickItemParam.LEFT_CLICK);
|
|
||||||
session.getDownstream().getSession().send(shiftClickPacket);
|
|
||||||
translator.updateInventory(session, inventory);
|
|
||||||
return;
|
|
||||||
} else if (translator.getSlotType(fromSlot) == SlotType.OUTPUT) {
|
|
||||||
session.setCraftSlot(cursorSlot);
|
|
||||||
Click.LEFT.onSlot(fromSlot, plan);
|
|
||||||
int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount();
|
|
||||||
for (int i = 0; i < difference; i++) {
|
|
||||||
Click.RIGHT.onSlot(toSlot, plan);
|
|
||||||
}
|
|
||||||
//client will send additional packets later to finish transferring crafting output
|
|
||||||
//translator will know how to handle this using the craftSlot variable
|
|
||||||
} else {
|
|
||||||
Click.LEFT.onSlot(fromSlot, plan);
|
|
||||||
int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount();
|
|
||||||
for (int i = 0; i < difference; i++) {
|
|
||||||
Click.RIGHT.onSlot(toSlot, plan);
|
|
||||||
}
|
|
||||||
Click.LEFT.onSlot(fromSlot, plan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cursorSlot != -1) {
|
|
||||||
Click.LEFT.onSlot(cursorSlot, plan);
|
|
||||||
}
|
|
||||||
executePlan(session, inventory, translator, plan, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
translator.updateInventory(session, inventory);
|
|
||||||
break;
|
break;
|
||||||
case INVENTORY_MISMATCH:
|
case INVENTORY_MISMATCH:
|
||||||
InventorySlotPacket cursorPacket = new InventorySlotPacket();
|
|
||||||
cursorPacket.setContainerId(ContainerId.CURSOR);
|
|
||||||
cursorPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor()));
|
|
||||||
//session.getUpstream().sendPacket(cursorPacket);
|
|
||||||
|
|
||||||
Inventory inv = session.getInventoryCache().getOpenInventory();
|
Inventory inv = session.getInventoryCache().getOpenInventory();
|
||||||
if (inv == null)
|
if (inv == null) inv = session.getInventory();
|
||||||
inv = session.getInventory();
|
|
||||||
TranslatorsInit.getInventoryTranslators().get(inv.getWindowType()).updateInventory(session, inv);
|
TranslatorsInit.getInventoryTranslators().get(inv.getWindowType()).updateInventory(session, inv);
|
||||||
|
InventoryUtils.updateCursor(session);
|
||||||
break;
|
break;
|
||||||
case ITEM_USE:
|
case ITEM_USE:
|
||||||
if (packet.getActionType() == 1) {
|
if (packet.getActionType() == 1) {
|
||||||
|
@ -448,136 +91,4 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int findTempSlot(Inventory inventory, ItemStack item, List<Integer> slotBlacklist) {
|
|
||||||
/*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<ItemStack> 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) {
|
|
||||||
for (ItemStack blacklistItem : itemBlacklist) {
|
|
||||||
if (canStack(testItem, blacklistItem)) {
|
|
||||||
acceptable = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (acceptable && !slotBlacklist.contains(i))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
//could not find a viable temp slot
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//NPE if compound tag is null
|
|
||||||
private ItemStack fixStack(ItemStack stack) {
|
|
||||||
if (stack == null || stack.getId() == 0)
|
|
||||||
return null;
|
|
||||||
return new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() == null ? new CompoundTag("") : stack.getNbt());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canStack(ItemStack item1, ItemStack item2) {
|
|
||||||
if (item1 == null || item2 == null)
|
|
||||||
return false;
|
|
||||||
return item1.getId() == item2.getId() && Objects.equals(item1.getNbt(), item2.getNbt());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canStack(ItemData item1, ItemData item2) {
|
|
||||||
if (item1 == null || item2 == null)
|
|
||||||
return false;
|
|
||||||
return item1.equals(item2, false, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void executePlan(GeyserSession session, Inventory inventory, InventoryTranslator translator, List<ClickAction> plan, boolean refresh) {
|
|
||||||
PlayerInventory playerInventory = session.getInventory();
|
|
||||||
ListIterator<ClickAction> planIter = plan.listIterator();
|
|
||||||
while (planIter.hasNext()) {
|
|
||||||
ClickAction action = planIter.next();
|
|
||||||
ItemStack cursorItem = playerInventory.getCursor();
|
|
||||||
ItemStack clickedItem = inventory.getItem(action.slot);
|
|
||||||
short actionId = (short) inventory.getTransactionId().getAndIncrement();
|
|
||||||
boolean isOutput = translator.getSlotType(action.slot) == SlotType.OUTPUT;
|
|
||||||
|
|
||||||
if (isOutput || translator.getSlotType(action.slot) == SlotType.FURNACE_OUTPUT)
|
|
||||||
refresh = true;
|
|
||||||
ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(),
|
|
||||||
actionId, action.slot, !planIter.hasNext() && refresh ? refreshItem : fixStack(clickedItem),
|
|
||||||
WindowAction.CLICK_ITEM, action.click.actionParam);
|
|
||||||
|
|
||||||
if (isOutput) {
|
|
||||||
if (cursorItem == null && clickedItem != null) {
|
|
||||||
playerInventory.setCursor(clickedItem);
|
|
||||||
} else if (canStack(cursorItem, clickedItem)) {
|
|
||||||
playerInventory.setCursor(new ItemStack(cursorItem.getId(),
|
|
||||||
cursorItem.getAmount() + clickedItem.getAmount(), cursorItem.getNbt()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (action.click) {
|
|
||||||
case LEFT:
|
|
||||||
if (!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 (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.getDownstream().getSession().send(clickPacket);
|
|
||||||
session.getDownstream().getSession().send(new ClientConfirmTransactionPacket(inventory.getId(), actionId, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Click {
|
|
||||||
LEFT(ClickItemParam.LEFT_CLICK),
|
|
||||||
RIGHT(ClickItemParam.RIGHT_CLICK);
|
|
||||||
|
|
||||||
final WindowActionParam actionParam;
|
|
||||||
Click(WindowActionParam actionParam) {
|
|
||||||
this.actionParam = actionParam;
|
|
||||||
}
|
|
||||||
void onSlot(int slot, List<ClickAction> plan) {
|
|
||||||
plan.add(new ClickAction(slot, this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ClickAction {
|
|
||||||
final int slot;
|
|
||||||
final Click click;
|
|
||||||
ClickAction(int slot, Click click) {
|
|
||||||
this.slot = slot;
|
|
||||||
this.click = click;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -25,13 +25,20 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.inventory;
|
package org.geysermc.connector.network.translators.inventory;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket;
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
||||||
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.ItemData;
|
||||||
|
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;
|
||||||
|
|
||||||
public class AnvilInventoryTranslator extends BlockInventoryTranslator {
|
public class AnvilInventoryTranslator extends BlockInventoryTranslator {
|
||||||
public AnvilInventoryTranslator() {
|
public AnvilInventoryTranslator() {
|
||||||
super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL);
|
super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL, new CursorInventoryUpdater());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,10 +56,62 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator {
|
||||||
return super.bedrockSlotToJava(action);
|
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
|
@Override
|
||||||
public SlotType getSlotType(int javaSlot) {
|
public SlotType getSlotType(int javaSlot) {
|
||||||
if (javaSlot == 2)
|
if (javaSlot == 2)
|
||||||
return SlotType.OUTPUT;
|
return SlotType.OUTPUT;
|
||||||
return SlotType.NORMAL;
|
return SlotType.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void translateActions(GeyserSession session, Inventory inventory, List<InventoryAction> actions) {
|
||||||
|
InventoryAction anvilResult = null;
|
||||||
|
InventoryAction anvilInput = null;
|
||||||
|
for (InventoryAction 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;
|
||||||
|
com.nukkitx.nbt.tag.CompoundTag tag = itemName.getTag();
|
||||||
|
if (tag != null) {
|
||||||
|
rename = tag.getAsCompound("display").getAsString("Name");
|
||||||
|
} else {
|
||||||
|
rename = "";
|
||||||
|
}
|
||||||
|
ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename);
|
||||||
|
session.getDownstream().getSession().send(renameItemPacket);
|
||||||
|
}
|
||||||
|
if (anvilResult != null) {
|
||||||
|
//client will send another packet to grab anvil output
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.translateActions(session, inventory, actions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -27,53 +27,20 @@ package org.geysermc.connector.network.translators.inventory;
|
||||||
|
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
||||||
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
||||||
import com.nukkitx.protocol.bedrock.data.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.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.inventory.action.InventoryActionTranslator;
|
||||||
|
|
||||||
public abstract class ContainerInventoryTranslator extends InventoryTranslator {
|
import java.util.List;
|
||||||
ContainerInventoryTranslator(int size) {
|
|
||||||
|
public abstract class BaseInventoryTranslator extends InventoryTranslator{
|
||||||
|
BaseInventoryTranslator(int size) {
|
||||||
super(size);
|
super(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateInventory(GeyserSession session, Inventory inventory) {
|
|
||||||
ItemData[] bedrockItems = new ItemData[this.size];
|
|
||||||
for (int i = 0; i < bedrockItems.length; i++) {
|
|
||||||
bedrockItems[javaSlotToBedrock(i)] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
|
||||||
}
|
|
||||||
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
|
||||||
contentPacket.setContainerId(inventory.getId());
|
|
||||||
contentPacket.setContents(bedrockItems);
|
|
||||||
session.getUpstream().sendPacket(contentPacket);
|
|
||||||
|
|
||||||
Inventory playerInventory = session.getInventory();
|
|
||||||
for (int i = 0; i < 36; i++) {
|
|
||||||
playerInventory.setItem(i + 9, inventory.getItem(i + this.size));
|
|
||||||
}
|
|
||||||
TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
|
|
||||||
if (slot >= this.size) {
|
|
||||||
Inventory playerInventory = session.getInventory();
|
|
||||||
playerInventory.setItem((slot + 9) - this.size, inventory.getItem(slot));
|
|
||||||
TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateSlot(session, playerInventory, (slot + 9) - this.size);
|
|
||||||
} else {
|
|
||||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
|
||||||
slotPacket.setContainerId(inventory.getId());
|
|
||||||
slotPacket.setInventorySlot(javaSlotToBedrock(slot));
|
|
||||||
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot)));
|
|
||||||
session.getUpstream().sendPacket(slotPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) {
|
public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) {
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -86,13 +53,20 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator {
|
||||||
} else {
|
} else {
|
||||||
return slotnum + this.size + 27;
|
return slotnum + this.size + 27;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return slotnum;
|
|
||||||
}
|
}
|
||||||
|
return slotnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int javaSlotToBedrock(int slot) {
|
public int javaSlotToBedrock(int slot) {
|
||||||
|
if (slot >= this.size) {
|
||||||
|
final int tmp = slot - this.size;
|
||||||
|
if (tmp < 27) {
|
||||||
|
return tmp + 9;
|
||||||
|
} else {
|
||||||
|
return tmp - 27;
|
||||||
|
}
|
||||||
|
}
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,4 +74,9 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator {
|
||||||
public SlotType getSlotType(int javaSlot) {
|
public SlotType getSlotType(int javaSlot) {
|
||||||
return SlotType.NORMAL;
|
return SlotType.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void translateActions(GeyserSession session, Inventory inventory, List<InventoryAction> actions) {
|
||||||
|
InventoryActionTranslator.translate(this, session, inventory, actions);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -25,70 +25,47 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.inventory;
|
package org.geysermc.connector.network.translators.inventory;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
|
||||||
import com.nukkitx.math.vector.Vector3i;
|
|
||||||
import com.nukkitx.nbt.tag.CompoundTag;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
||||||
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
import org.geysermc.connector.network.translators.block.BlockEntry;
|
import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
||||||
|
|
||||||
public class BlockInventoryTranslator extends ContainerInventoryTranslator {
|
public class BlockInventoryTranslator extends BaseInventoryTranslator {
|
||||||
final int blockId;
|
private final InventoryHolder holder;
|
||||||
private final ContainerType containerType;
|
private final InventoryUpdater updater;
|
||||||
|
|
||||||
public BlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType) {
|
public BlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater) {
|
||||||
super(size);
|
super(size);
|
||||||
this.blockId = TranslatorsInit.getBlockTranslator().getBlockEntry(javaBlockIdentifier).getBedrockRuntimeId();
|
final int blockId = TranslatorsInit.getBlockTranslator().getBlockEntry(javaBlockIdentifier).getBedrockRuntimeId();
|
||||||
this.containerType = containerType;
|
this.holder = new BlockInventoryHolder(blockId, containerType);
|
||||||
|
this.updater = updater;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||||
Vector3i position = session.getPlayerEntity().getPosition().toInt();
|
holder.prepareInventory(this, session, inventory);
|
||||||
position = position.add(Vector3i.UP);
|
|
||||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
|
||||||
blockPacket.setDataLayer(0);
|
|
||||||
blockPacket.setBlockPosition(position);
|
|
||||||
blockPacket.setRuntimeId(blockId);
|
|
||||||
blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
|
|
||||||
session.getUpstream().sendPacket(blockPacket);
|
|
||||||
inventory.setHolderPosition(position);
|
|
||||||
|
|
||||||
CompoundTag tag = CompoundTag.EMPTY.toBuilder()
|
|
||||||
.intTag("x", position.getX())
|
|
||||||
.intTag("y", position.getY())
|
|
||||||
.intTag("z", position.getZ())
|
|
||||||
.stringTag("CustomName", inventory.getTitle()).buildRootTag();
|
|
||||||
BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
|
|
||||||
dataPacket.setData(tag);
|
|
||||||
dataPacket.setBlockPosition(position);
|
|
||||||
session.getUpstream().sendPacket(dataPacket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void openInventory(GeyserSession session, Inventory inventory) {
|
public void openInventory(GeyserSession session, Inventory inventory) {
|
||||||
ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
|
holder.openInventory(this, session, inventory);
|
||||||
containerOpenPacket.setWindowId((byte) inventory.getId());
|
|
||||||
containerOpenPacket.setType((byte) containerType.id());
|
|
||||||
containerOpenPacket.setBlockPosition(inventory.getHolderPosition());
|
|
||||||
containerOpenPacket.setUniqueEntityId(inventory.getHolderId());
|
|
||||||
session.getUpstream().sendPacket(containerOpenPacket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeInventory(GeyserSession session, Inventory inventory) {
|
public void closeInventory(GeyserSession session, Inventory inventory) {
|
||||||
Vector3i holderPos = inventory.getHolderPosition();
|
holder.closeInventory(this, session, inventory);
|
||||||
Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ());
|
}
|
||||||
BlockEntry realBlock = session.getChunkCache().getBlockAt(pos);
|
|
||||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
@Override
|
||||||
blockPacket.setDataLayer(0);
|
public void updateInventory(GeyserSession session, Inventory inventory) {
|
||||||
blockPacket.setBlockPosition(holderPos);
|
updater.updateInventory(this, session, inventory);
|
||||||
blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId());
|
}
|
||||||
session.getUpstream().sendPacket(blockPacket);
|
|
||||||
|
@Override
|
||||||
|
public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
|
||||||
|
updater.updateSlot(this, session, inventory, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -30,10 +30,11 @@ import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
||||||
import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket;
|
import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater;
|
||||||
|
|
||||||
public class BrewingStandInventoryTranslator extends BlockInventoryTranslator {
|
public class BrewingInventoryTranslator extends BlockInventoryTranslator {
|
||||||
public BrewingStandInventoryTranslator() {
|
public BrewingInventoryTranslator() {
|
||||||
super(5, "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", ContainerType.BREWING_STAND);
|
super(5, "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", ContainerType.BREWING_STAND, new ContainerInventoryUpdater());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,8 +67,8 @@ public class BrewingStandInventoryTranslator extends BlockInventoryTranslator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int bedrockSlotToJava(InventoryAction action) {
|
public int bedrockSlotToJava(InventoryAction action) {
|
||||||
int slotnum = super.bedrockSlotToJava(action);
|
final int slot = super.bedrockSlotToJava(action);
|
||||||
switch (slotnum) {
|
switch (slot) {
|
||||||
case 0:
|
case 0:
|
||||||
return 3;
|
return 3;
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -77,13 +78,13 @@ public class BrewingStandInventoryTranslator extends BlockInventoryTranslator {
|
||||||
case 3:
|
case 3:
|
||||||
return 2;
|
return 2;
|
||||||
default:
|
default:
|
||||||
return slotnum;
|
return slot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int javaSlotToBedrock(int slotnum) {
|
public int javaSlotToBedrock(int slot) {
|
||||||
switch (slotnum) {
|
switch (slot) {
|
||||||
case 0:
|
case 0:
|
||||||
return 1;
|
return 1;
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -92,8 +93,7 @@ public class BrewingStandInventoryTranslator extends BlockInventoryTranslator {
|
||||||
return 3;
|
return 3;
|
||||||
case 3:
|
case 3:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
|
||||||
return slotnum;
|
|
||||||
}
|
}
|
||||||
|
return super.javaSlotToBedrock(slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -25,21 +25,33 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.inventory;
|
package org.geysermc.connector.network.translators.inventory;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
||||||
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.InventorySource;
|
||||||
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
||||||
|
import org.geysermc.connector.utils.InventoryUtils;
|
||||||
|
|
||||||
public class CraftingTableInventoryTranslator extends ContainerInventoryTranslator {
|
import java.util.List;
|
||||||
public CraftingTableInventoryTranslator() {
|
|
||||||
|
public class CraftingInventoryTranslator extends BaseInventoryTranslator {
|
||||||
|
private final InventoryUpdater updater;
|
||||||
|
|
||||||
|
public CraftingInventoryTranslator() {
|
||||||
super(10);
|
super(10);
|
||||||
|
this.updater = new CursorInventoryUpdater();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,7 +66,17 @@ public class CraftingTableInventoryTranslator extends ContainerInventoryTranslat
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeInventory(GeyserSession session, Inventory inventory) {
|
public void closeInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
@Override
|
||||||
|
@ -70,10 +92,29 @@ public class CraftingTableInventoryTranslator extends ContainerInventoryTranslat
|
||||||
return super.bedrockSlotToJava(action);
|
return super.bedrockSlotToJava(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int javaSlotToBedrock(int slot) {
|
||||||
|
return slot == 0 ? 50 : slot + 31;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SlotType getSlotType(int javaSlot) {
|
public SlotType getSlotType(int javaSlot) {
|
||||||
if (javaSlot == 0)
|
if (javaSlot == 0)
|
||||||
return SlotType.OUTPUT;
|
return SlotType.OUTPUT;
|
||||||
return SlotType.NORMAL;
|
return SlotType.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void translateActions(GeyserSession session, Inventory inventory, List<InventoryAction> actions) {
|
||||||
|
if (session.getGameMode() == GameMode.CREATIVE) {
|
||||||
|
for (InventoryAction action : actions) {
|
||||||
|
if (action.getSource().getType() == InventorySource.Type.CREATIVE) {
|
||||||
|
updateInventory(session, inventory);
|
||||||
|
InventoryUtils.updateCursor(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.translateActions(session, inventory, actions);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -29,32 +29,39 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||||
import com.nukkitx.math.vector.Vector3i;
|
import com.nukkitx.math.vector.Vector3i;
|
||||||
import com.nukkitx.nbt.tag.CompoundTag;
|
import com.nukkitx.nbt.tag.CompoundTag;
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
||||||
import com.nukkitx.protocol.bedrock.data.ItemData;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket;
|
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
import org.geysermc.connector.network.translators.block.BlockEntry;
|
import org.geysermc.connector.network.translators.block.BlockEntry;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
||||||
|
|
||||||
|
public class DoubleChestInventoryTranslator extends BaseInventoryTranslator {
|
||||||
|
private final int blockId;
|
||||||
|
private final InventoryUpdater updater;
|
||||||
|
|
||||||
public class DoubleChestInventoryTranslator extends BlockInventoryTranslator {
|
|
||||||
public DoubleChestInventoryTranslator(int size) {
|
public DoubleChestInventoryTranslator(int size) {
|
||||||
super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER);
|
super(size);
|
||||||
|
this.blockId = TranslatorsInit.getBlockTranslator().getBlockEntry("minecraft:chest[facing=north,type=single,waterlogged=false]").getBedrockRuntimeId();
|
||||||
|
this.updater = new ChestInventoryUpdater(54);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||||
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP);
|
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP);
|
||||||
Vector3i pairPosition = position.add(Vector3i.UNIT_X);
|
Vector3i pairPosition = position.add(Vector3i.UNIT_X);
|
||||||
|
|
||||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setBlockPosition(position);
|
blockPacket.setBlockPosition(position);
|
||||||
blockPacket.setRuntimeId(blockId);
|
blockPacket.setRuntimeId(blockId);
|
||||||
blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
|
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||||
session.getUpstream().sendPacket(blockPacket);
|
session.getUpstream().sendPacket(blockPacket);
|
||||||
|
|
||||||
CompoundTag tag = CompoundTag.EMPTY.toBuilder()
|
CompoundTag tag = CompoundTag.builder()
|
||||||
.stringTag("id", "Chest")
|
.stringTag("id", "Chest")
|
||||||
.intTag("x", position.getX())
|
.intTag("x", position.getX())
|
||||||
.intTag("y", position.getY())
|
.intTag("y", position.getY())
|
||||||
|
@ -71,10 +78,10 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator {
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setBlockPosition(pairPosition);
|
blockPacket.setBlockPosition(pairPosition);
|
||||||
blockPacket.setRuntimeId(blockId);
|
blockPacket.setRuntimeId(blockId);
|
||||||
blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
|
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||||
session.getUpstream().sendPacket(blockPacket);
|
session.getUpstream().sendPacket(blockPacket);
|
||||||
|
|
||||||
tag = CompoundTag.EMPTY.toBuilder()
|
tag = CompoundTag.builder()
|
||||||
.stringTag("id", "Chest")
|
.stringTag("id", "Chest")
|
||||||
.intTag("x", pairPosition.getX())
|
.intTag("x", pairPosition.getX())
|
||||||
.intTag("y", pairPosition.getY())
|
.intTag("y", pairPosition.getY())
|
||||||
|
@ -90,6 +97,16 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator {
|
||||||
inventory.setHolderPosition(position);
|
inventory.setHolderPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void openInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
|
||||||
|
containerOpenPacket.setWindowId((byte) inventory.getId());
|
||||||
|
containerOpenPacket.setType((byte) ContainerType.CONTAINER.id());
|
||||||
|
containerOpenPacket.setBlockPosition(inventory.getHolderPosition());
|
||||||
|
containerOpenPacket.setUniqueEntityId(inventory.getHolderId());
|
||||||
|
session.getUpstream().sendPacket(containerOpenPacket);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeInventory(GeyserSession session, Inventory inventory) {
|
public void closeInventory(GeyserSession session, Inventory inventory) {
|
||||||
Vector3i holderPos = inventory.getHolderPosition();
|
Vector3i holderPos = inventory.getHolderPosition();
|
||||||
|
@ -113,24 +130,11 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateInventory(GeyserSession session, Inventory inventory) {
|
public void updateInventory(GeyserSession session, Inventory inventory) {
|
||||||
//need to pad empty slots for 4x9 and 5x9
|
updater.updateInventory(this, session, inventory);
|
||||||
ItemData[] bedrockItems = new ItemData[54];
|
}
|
||||||
for (int i = 0; i < bedrockItems.length; i++) {
|
|
||||||
if (i <= this.size) {
|
|
||||||
bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
|
||||||
} else {
|
|
||||||
bedrockItems[i] = ItemData.AIR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
|
||||||
contentPacket.setContainerId(inventory.getId());
|
|
||||||
contentPacket.setContents(bedrockItems);
|
|
||||||
session.getUpstream().sendPacket(contentPacket);
|
|
||||||
|
|
||||||
Inventory playerInventory = session.getInventory();
|
@Override
|
||||||
for (int i = 0; i < 36; i++) {
|
public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
|
||||||
playerInventory.setItem(i + 9, inventory.getItem(i + this.size));
|
updater.updateSlot(this, session, inventory, slot);
|
||||||
}
|
|
||||||
TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -28,10 +28,11 @@ package org.geysermc.connector.network.translators.inventory;
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater;
|
||||||
|
|
||||||
public class EnchantmentInventoryTranslator extends BlockInventoryTranslator {
|
public class EnchantmentInventoryTranslator extends BlockInventoryTranslator {
|
||||||
public EnchantmentInventoryTranslator() {
|
public EnchantmentInventoryTranslator() {
|
||||||
super(2, "minecraft:enchanting_table", ContainerType.ENCHANTMENT);
|
super(2, "minecraft:enchanting_table", ContainerType.ENCHANTMENT, new ContainerInventoryUpdater());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -30,10 +30,11 @@ import com.nukkitx.protocol.bedrock.data.ContainerType;
|
||||||
import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket;
|
import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater;
|
||||||
|
|
||||||
public class FurnaceInventoryTranslator extends BlockInventoryTranslator {
|
public class FurnaceInventoryTranslator extends BlockInventoryTranslator {
|
||||||
public FurnaceInventoryTranslator() {
|
public FurnaceInventoryTranslator() {
|
||||||
super(3, "minecraft:furnace[facing=north,lit=false]", ContainerType.FURNACE);
|
super(3, "minecraft:furnace[facing=north,lit=false]", ContainerType.FURNACE, new ContainerInventoryUpdater());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -26,16 +26,16 @@
|
||||||
package org.geysermc.connector.network.translators.inventory;
|
package org.geysermc.connector.network.translators.inventory;
|
||||||
|
|
||||||
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
public abstract class InventoryTranslator {
|
public abstract class InventoryTranslator {
|
||||||
public final int size;
|
public final int size;
|
||||||
|
|
||||||
InventoryTranslator(int size) {
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void prepareInventory(GeyserSession session, Inventory inventory);
|
public abstract void prepareInventory(GeyserSession session, Inventory inventory);
|
||||||
public abstract void openInventory(GeyserSession session, Inventory inventory);
|
public abstract void openInventory(GeyserSession session, Inventory inventory);
|
||||||
public abstract void closeInventory(GeyserSession session, Inventory inventory);
|
public abstract void closeInventory(GeyserSession session, Inventory inventory);
|
||||||
|
@ -45,4 +45,5 @@ public abstract class InventoryTranslator {
|
||||||
public abstract int bedrockSlotToJava(InventoryAction action);
|
public abstract int bedrockSlotToJava(InventoryAction action);
|
||||||
public abstract int javaSlotToBedrock(int slot);
|
public abstract int javaSlotToBedrock(int slot);
|
||||||
public abstract SlotType getSlotType(int javaSlot);
|
public abstract SlotType getSlotType(int javaSlot);
|
||||||
|
public abstract void translateActions(GeyserSession session, Inventory inventory, List<InventoryAction> actions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -25,12 +25,19 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.inventory;
|
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.*;
|
import com.nukkitx.protocol.bedrock.data.*;
|
||||||
import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket;
|
import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.action.InventoryActionTranslator;
|
||||||
|
import org.geysermc.connector.utils.InventoryUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PlayerInventoryTranslator extends InventoryTranslator {
|
public class PlayerInventoryTranslator extends InventoryTranslator {
|
||||||
public PlayerInventoryTranslator() {
|
public PlayerInventoryTranslator() {
|
||||||
|
@ -39,20 +46,26 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateInventory(GeyserSession session, Inventory inventory) {
|
public void updateInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
// Crafting grid
|
||||||
|
for (int i = 1; i < 5; i++) {
|
||||||
|
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||||
|
slotPacket.setContainerId(ContainerId.CURSOR);
|
||||||
|
slotPacket.setInventorySlot(i + 27);
|
||||||
|
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)));
|
||||||
|
session.getUpstream().sendPacket(slotPacket);
|
||||||
|
}
|
||||||
|
|
||||||
InventoryContentPacket inventoryContentPacket = new InventoryContentPacket();
|
InventoryContentPacket inventoryContentPacket = new InventoryContentPacket();
|
||||||
inventoryContentPacket.setContainerId(ContainerId.INVENTORY);
|
inventoryContentPacket.setContainerId(ContainerId.INVENTORY);
|
||||||
|
|
||||||
ItemData[] contents = new ItemData[36];
|
ItemData[] contents = new ItemData[36];
|
||||||
// Inventory
|
// Inventory
|
||||||
for (int i = 9; i < 36; i++) {
|
for (int i = 9; i < 36; i++) {
|
||||||
contents[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
contents[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hotbar
|
// Hotbar
|
||||||
for (int i = 36; i < 45; i++) {
|
for (int i = 36; i < 45; i++) {
|
||||||
contents[i - 36] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
contents[i - 36] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
inventoryContentPacket.setContents(contents);
|
inventoryContentPacket.setContents(contents);
|
||||||
session.getUpstream().sendPacket(inventoryContentPacket);
|
session.getUpstream().sendPacket(inventoryContentPacket);
|
||||||
|
|
||||||
|
@ -75,7 +88,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
|
public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
|
||||||
if (slot >= 5 && slot <= 44) {
|
if (slot >= 1 && slot <= 44) {
|
||||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||||
if (slot >= 9) {
|
if (slot >= 9) {
|
||||||
slotPacket.setContainerId(ContainerId.INVENTORY);
|
slotPacket.setContainerId(ContainerId.INVENTORY);
|
||||||
|
@ -84,9 +97,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
|
||||||
} else {
|
} else {
|
||||||
slotPacket.setInventorySlot(slot);
|
slotPacket.setInventorySlot(slot);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (slot >= 5) {
|
||||||
slotPacket.setContainerId(ContainerId.ARMOR);
|
slotPacket.setContainerId(ContainerId.ARMOR);
|
||||||
slotPacket.setInventorySlot(slot - 5);
|
slotPacket.setInventorySlot(slot - 5);
|
||||||
|
} else {
|
||||||
|
slotPacket.setContainerId(ContainerId.CURSOR);
|
||||||
|
slotPacket.setInventorySlot(slot + 27);
|
||||||
}
|
}
|
||||||
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot)));
|
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot)));
|
||||||
session.getUpstream().sendPacket(slotPacket);
|
session.getUpstream().sendPacket(slotPacket);
|
||||||
|
@ -142,6 +158,55 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
|
||||||
return SlotType.NORMAL;
|
return SlotType.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void translateActions(GeyserSession session, Inventory inventory, List<InventoryAction> actions) {
|
||||||
|
if (session.getGameMode() == GameMode.CREATIVE) {
|
||||||
|
//crafting grid is not visible in creative mode in java edition
|
||||||
|
for (InventoryAction action : actions) {
|
||||||
|
if (action.getSource().getContainerId() == ContainerId.CURSOR && (action.getSlot() >= 28 && 31 >= action.getSlot())) {
|
||||||
|
updateInventory(session, inventory);
|
||||||
|
InventoryUtils.updateCursor(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack javaItem;
|
||||||
|
for (InventoryAction 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 = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem());
|
||||||
|
}
|
||||||
|
ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, InventoryUtils.fixStack(javaItem));
|
||||||
|
session.getDownstream().getSession().send(creativePacket);
|
||||||
|
inventory.setItem(javaSlot, javaItem);
|
||||||
|
break;
|
||||||
|
case ContainerId.CURSOR:
|
||||||
|
if (action.getSlot() == 0) {
|
||||||
|
session.getInventory().setCursor(TranslatorsInit.getItemTranslator().translateToJava(action.getToItem()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContainerId.NONE:
|
||||||
|
if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION
|
||||||
|
&& action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) {
|
||||||
|
javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem());
|
||||||
|
ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, InventoryUtils.fixStack(javaItem));
|
||||||
|
session.getDownstream().getSession().send(creativeDropPacket);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryActionTranslator.translate(this, session, inventory, actions);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,37 +26,10 @@
|
||||||
package org.geysermc.connector.network.translators.inventory;
|
package org.geysermc.connector.network.translators.inventory;
|
||||||
|
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
import com.nukkitx.protocol.bedrock.data.ContainerType;
|
||||||
import com.nukkitx.protocol.bedrock.data.ItemData;
|
import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater;
|
||||||
import com.nukkitx.protocol.bedrock.packet.*;
|
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
|
||||||
|
|
||||||
public class SingleChestInventoryTranslator extends BlockInventoryTranslator {
|
public class SingleChestInventoryTranslator extends BlockInventoryTranslator {
|
||||||
public SingleChestInventoryTranslator(int size) {
|
public SingleChestInventoryTranslator(int size) {
|
||||||
super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER);
|
super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER, new ChestInventoryUpdater(27));
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateInventory(GeyserSession session, Inventory inventory) {
|
|
||||||
//need to pad empty slots for 1x9 and 2x9
|
|
||||||
ItemData[] bedrockItems = new ItemData[27];
|
|
||||||
for (int i = 0; i < bedrockItems.length; i++) {
|
|
||||||
if (i <= this.size) {
|
|
||||||
bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
|
||||||
} else {
|
|
||||||
bedrockItems[i] = ItemData.AIR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
|
||||||
contentPacket.setContainerId(inventory.getId());
|
|
||||||
contentPacket.setContents(bedrockItems);
|
|
||||||
session.getUpstream().sendPacket(contentPacket);
|
|
||||||
|
|
||||||
Inventory playerInventory = session.getInventory();
|
|
||||||
for (int i = 0; i < 36; i++) {
|
|
||||||
playerInventory.setItem(i + 9, inventory.getItem(i + this.size));
|
|
||||||
}
|
|
||||||
TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* 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<ClickAction> 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<ClickAction> 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 : InventoryUtils.fixStack(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.getDownstream().getSession().send(clickPacket);
|
||||||
|
session.getDownstream().getSession().send(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,330 @@
|
||||||
|
/*
|
||||||
|
* 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.ContainerId;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.InventoryAction;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.InventorySource;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.ItemData;
|
||||||
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
|
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.*;
|
||||||
|
|
||||||
|
public class InventoryActionTranslator {
|
||||||
|
public static void translate(InventoryTranslator translator, GeyserSession session, Inventory inventory, List<InventoryAction> actions) {
|
||||||
|
if (actions.size() != 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
InventoryAction worldAction = null;
|
||||||
|
InventoryAction cursorAction = null;
|
||||||
|
InventoryAction containerAction = null;
|
||||||
|
boolean refresh = false;
|
||||||
|
for (InventoryAction action : actions) {
|
||||||
|
if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT || action.getSource().getContainerId() == ContainerId.CRAFTING_RESULT) {
|
||||||
|
return;
|
||||||
|
} else if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION) {
|
||||||
|
worldAction = action;
|
||||||
|
} else if (action.getSource().getContainerId() == ContainerId.CURSOR && action.getSlot() == 0) {
|
||||||
|
cursorAction = action;
|
||||||
|
ItemData translatedCursor = TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor());
|
||||||
|
if (!translatedCursor.equals(action.getFromItem())) {
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
containerAction = action;
|
||||||
|
ItemData translatedItem = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(translator.bedrockSlotToJava(action)));
|
||||||
|
if (!translatedItem.equals(action.getFromItem())) {
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final int craftSlot = session.getCraftSlot();
|
||||||
|
session.setCraftSlot(0);
|
||||||
|
|
||||||
|
if (worldAction != null) {
|
||||||
|
InventoryAction 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.getDownstream().getSession().send(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.getDownstream().getSession().send(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.getDownstream().getSession().send(dropPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItemStack item = session.getInventory().getItem(javaSlot);
|
||||||
|
if (item != null) {
|
||||||
|
session.getInventory().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.getDownstream().getSession().send(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.getDownstream().getSession().send(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));
|
||||||
|
if (cursorSlot != -1) {
|
||||||
|
plan.add(Click.LEFT, cursorSlot);
|
||||||
|
} else {
|
||||||
|
translator.updateInventory(session, inventory);
|
||||||
|
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();
|
||||||
|
InventoryAction fromAction;
|
||||||
|
InventoryAction 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));
|
||||||
|
if (cursorSlot != -1) {
|
||||||
|
plan.add(Click.LEFT, cursorSlot);
|
||||||
|
} else {
|
||||||
|
translator.updateInventory(session, inventory);
|
||||||
|
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.getDownstream().getSession().send(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<Integer> slotBlacklist) {
|
||||||
|
/*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<ItemStack> 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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* 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.tag.CompoundTag;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.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.block.BlockEntry;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
|
||||||
|
@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.getUpstream().sendPacket(blockPacket);
|
||||||
|
inventory.setHolderPosition(position);
|
||||||
|
|
||||||
|
CompoundTag tag = CompoundTag.builder()
|
||||||
|
.intTag("x", position.getX())
|
||||||
|
.intTag("y", position.getY())
|
||||||
|
.intTag("z", position.getZ())
|
||||||
|
.stringTag("CustomName", inventory.getTitle()).buildRootTag();
|
||||||
|
BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
|
||||||
|
dataPacket.setData(tag);
|
||||||
|
dataPacket.setBlockPosition(position);
|
||||||
|
session.getUpstream().sendPacket(dataPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||||
|
ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
|
||||||
|
containerOpenPacket.setWindowId((byte) inventory.getId());
|
||||||
|
containerOpenPacket.setType((byte) containerType.id());
|
||||||
|
containerOpenPacket.setBlockPosition(inventory.getHolderPosition());
|
||||||
|
containerOpenPacket.setUniqueEntityId(inventory.getHolderId());
|
||||||
|
session.getUpstream().sendPacket(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());
|
||||||
|
BlockEntry realBlock = session.getChunkCache().getBlockAt(pos);
|
||||||
|
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||||
|
blockPacket.setDataLayer(0);
|
||||||
|
blockPacket.setBlockPosition(holderPos);
|
||||||
|
blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId());
|
||||||
|
session.getUpstream().sendPacket(blockPacket);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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 org.geysermc.connector.inventory.Inventory;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
|
||||||
|
public abstract class InventoryHolder {
|
||||||
|
public abstract void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
|
||||||
|
public abstract void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
|
||||||
|
public abstract void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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.updater;
|
||||||
|
|
||||||
|
import com.nukkitx.protocol.bedrock.data.ItemData;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ChestInventoryUpdater extends InventoryUpdater {
|
||||||
|
private final int paddedSize;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||||
|
super.updateInventory(translator, session, inventory);
|
||||||
|
|
||||||
|
ItemData[] bedrockItems = new ItemData[paddedSize];
|
||||||
|
for (int i = 0; i < bedrockItems.length; i++) {
|
||||||
|
if (i <= translator.size) {
|
||||||
|
bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
||||||
|
} else {
|
||||||
|
bedrockItems[i] = ItemData.AIR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
||||||
|
contentPacket.setContainerId(inventory.getId());
|
||||||
|
contentPacket.setContents(bedrockItems);
|
||||||
|
session.getUpstream().sendPacket(contentPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||||
|
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||||
|
slotPacket.setContainerId(inventory.getId());
|
||||||
|
slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot));
|
||||||
|
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot)));
|
||||||
|
session.getUpstream().sendPacket(slotPacket);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.updater;
|
||||||
|
|
||||||
|
import com.nukkitx.protocol.bedrock.data.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.TranslatorsInit;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
|
||||||
|
public class ContainerInventoryUpdater extends InventoryUpdater {
|
||||||
|
@Override
|
||||||
|
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||||
|
super.updateInventory(translator, session, inventory);
|
||||||
|
|
||||||
|
ItemData[] bedrockItems = new ItemData[translator.size];
|
||||||
|
for (int i = 0; i < bedrockItems.length; i++) {
|
||||||
|
bedrockItems[translator.javaSlotToBedrock(i)] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
||||||
|
contentPacket.setContainerId(inventory.getId());
|
||||||
|
contentPacket.setContents(bedrockItems);
|
||||||
|
session.getUpstream().sendPacket(contentPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||||
|
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||||
|
slotPacket.setContainerId(inventory.getId());
|
||||||
|
slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot));
|
||||||
|
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot)));
|
||||||
|
session.getUpstream().sendPacket(slotPacket);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.updater;
|
||||||
|
|
||||||
|
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
||||||
|
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.TranslatorsInit;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
|
||||||
|
public class CursorInventoryUpdater extends InventoryUpdater {
|
||||||
|
@Override
|
||||||
|
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||||
|
super.updateInventory(translator, session, inventory);
|
||||||
|
|
||||||
|
for (int i = 0; i < translator.size; i++) {
|
||||||
|
final int bedrockSlot = translator.javaSlotToBedrock(i);
|
||||||
|
if (bedrockSlot == 50)
|
||||||
|
continue;
|
||||||
|
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||||
|
slotPacket.setContainerId(ContainerId.CURSOR);
|
||||||
|
slotPacket.setInventorySlot(bedrockSlot);
|
||||||
|
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)));
|
||||||
|
session.getUpstream().sendPacket(slotPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||||
|
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||||
|
slotPacket.setContainerId(ContainerId.CURSOR);
|
||||||
|
slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot));
|
||||||
|
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot)));
|
||||||
|
session.getUpstream().sendPacket(slotPacket);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* 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.updater;
|
||||||
|
|
||||||
|
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.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.TranslatorsInit;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
|
||||||
|
public abstract class InventoryUpdater {
|
||||||
|
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||||
|
ItemData[] bedrockItems = new ItemData[36];
|
||||||
|
for (int i = 0; i < 36; i++) {
|
||||||
|
final int offset = i < 9 ? 27 : -9;
|
||||||
|
bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(translator.size + i + offset));
|
||||||
|
}
|
||||||
|
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
||||||
|
contentPacket.setContainerId(ContainerId.INVENTORY);
|
||||||
|
contentPacket.setContents(bedrockItems);
|
||||||
|
session.getUpstream().sendPacket(contentPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||||
|
if (javaSlot >= translator.size) {
|
||||||
|
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||||
|
slotPacket.setContainerId(ContainerId.INVENTORY);
|
||||||
|
slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot));
|
||||||
|
slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot)));
|
||||||
|
session.getUpstream().sendPacket(slotPacket);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -74,9 +74,8 @@ public class ItemTranslator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemData translateToBedrock(ItemStack stack) {
|
public ItemData translateToBedrock(ItemStack stack) {
|
||||||
// Most likely dirt if null
|
|
||||||
if (stack == null) {
|
if (stack == null) {
|
||||||
return ItemData.of(3, (short)0, 0);
|
return ItemData.AIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemEntry bedrockItem = getItem(stack);
|
ItemEntry bedrockItem = getItem(stack);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -49,8 +49,10 @@ import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclareRecipesPacket> {
|
public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclareRecipesPacket> {
|
||||||
|
private static final Collection<PotionMixData> POTION_MIXES =
|
||||||
private final int[] brewingIngredients = new int[]{372, 331, 348, 376, 289, 437, 353, 414, 382, 375, 462, 378, 396, 377, 370, 469, 470};
|
Arrays.stream(new int[]{372, 331, 348, 376, 289, 437, 353, 414, 382, 375, 462, 378, 396, 377, 370, 469, 470})
|
||||||
|
.mapToObj(ingredient -> new PotionMixData(0, ingredient, 0))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(ServerDeclareRecipesPacket packet, GeyserSession session) {
|
public void translate(ServerDeclareRecipesPacket packet, GeyserSession session) {
|
||||||
|
@ -61,6 +63,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclare
|
||||||
case CRAFTING_SHAPELESS: {
|
case CRAFTING_SHAPELESS: {
|
||||||
ShapelessRecipeData shapelessRecipeData = (ShapelessRecipeData) recipe.getData();
|
ShapelessRecipeData shapelessRecipeData = (ShapelessRecipeData) recipe.getData();
|
||||||
ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapelessRecipeData.getResult());
|
ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapelessRecipeData.getResult());
|
||||||
|
output = ItemData.of(output.getId(), output.getDamage(), output.getCount()); //strip NBT
|
||||||
ItemData[][] inputCombinations = combinations(shapelessRecipeData.getIngredients());
|
ItemData[][] inputCombinations = combinations(shapelessRecipeData.getIngredients());
|
||||||
for (ItemData[] inputs : inputCombinations) {
|
for (ItemData[] inputs : inputCombinations) {
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
|
@ -72,6 +75,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclare
|
||||||
case CRAFTING_SHAPED: {
|
case CRAFTING_SHAPED: {
|
||||||
ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData();
|
ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData();
|
||||||
ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapedRecipeData.getResult());
|
ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapedRecipeData.getResult());
|
||||||
|
output = ItemData.of(output.getId(), output.getDamage(), output.getCount()); //strip NBT
|
||||||
ItemData[][] inputCombinations = combinations(shapedRecipeData.getIngredients());
|
ItemData[][] inputCombinations = combinations(shapedRecipeData.getIngredients());
|
||||||
for (ItemData[] inputs : inputCombinations) {
|
for (ItemData[] inputs : inputCombinations) {
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
|
@ -83,12 +87,11 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclare
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int brewingIngredient : brewingIngredients) {
|
craftingDataPacket.getPotionMixData().addAll(POTION_MIXES);
|
||||||
craftingDataPacket.getPotionMixData().add(new PotionMixData(0, brewingIngredient, 0));
|
|
||||||
}
|
|
||||||
session.getUpstream().sendPacket(craftingDataPacket);
|
session.getUpstream().sendPacket(craftingDataPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: rewrite
|
||||||
private ItemData[][] combinations(Ingredient[] ingredients) {
|
private ItemData[][] combinations(Ingredient[] ingredients) {
|
||||||
Map<Set<ItemData>, IntSet> squashedOptions = new HashMap<>();
|
Map<Set<ItemData>, IntSet> squashedOptions = new HashMap<>();
|
||||||
for (int i = 0; i < ingredients.length; i++) {
|
for (int i = 0; i < ingredients.length; i++) {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.entity.player;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerChangeHeldItemPacket;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.PlayerHotbarPacket;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
|
|
||||||
|
public class JavaPlayerChangeHeldItemTranslator extends PacketTranslator<ServerPlayerChangeHeldItemPacket> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void translate(ServerPlayerChangeHeldItemPacket packet, GeyserSession session) {
|
||||||
|
PlayerHotbarPacket hotbarPacket = new PlayerHotbarPacket();
|
||||||
|
hotbarPacket.setContainerId(0);
|
||||||
|
hotbarPacket.setSelectedHotbarSlot(packet.getSlot());
|
||||||
|
hotbarPacket.setSelectHotbarSlot(true);
|
||||||
|
session.getUpstream().sendPacket(hotbarPacket);
|
||||||
|
|
||||||
|
session.getInventory().setHeldItemSlot(packet.getSlot());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -80,7 +80,7 @@ public class JavaOpenWindowTranslator extends PacketTranslator<ServerOpenWindowP
|
||||||
InventoryTranslator openTranslator = TranslatorsInit.getInventoryTranslators().get(openInventory.getWindowType());
|
InventoryTranslator openTranslator = TranslatorsInit.getInventoryTranslators().get(openInventory.getWindowType());
|
||||||
if (!openTranslator.getClass().equals(newTranslator.getClass())) {
|
if (!openTranslator.getClass().equals(newTranslator.getClass())) {
|
||||||
InventoryUtils.closeInventory(session, openInventory.getId());
|
InventoryUtils.closeInventory(session, openInventory.getId());
|
||||||
Geyser.getGeneralThreadPool().schedule(() -> InventoryUtils.openInventory(session, newInventory), 350, TimeUnit.MILLISECONDS);
|
Geyser.getGeneralThreadPool().schedule(() -> InventoryUtils.openInventory(session, newInventory), 500, TimeUnit.MILLISECONDS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
import org.geysermc.connector.utils.InventoryUtils;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -43,8 +44,9 @@ public class JavaSetSlotTranslator extends PacketTranslator<ServerSetSlotPacket>
|
||||||
return;
|
return;
|
||||||
if (session.getCraftSlot() != 0)
|
if (session.getCraftSlot() != 0)
|
||||||
return;
|
return;
|
||||||
//bedrock client is bugged when changing the cursor. do not send slot update packet
|
|
||||||
session.getInventory().setCursor(packet.getItem());
|
session.getInventory().setCursor(packet.getItem());
|
||||||
|
InventoryUtils.updateCursor(session);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -25,6 +25,11 @@
|
||||||
|
|
||||||
package org.geysermc.connector.utils;
|
package org.geysermc.connector.utils;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||||
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.ItemData;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||||
import org.geysermc.api.Geyser;
|
import org.geysermc.api.Geyser;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
@ -32,9 +37,11 @@ import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
import org.geysermc.connector.network.translators.inventory.DoubleChestInventoryTranslator;
|
import org.geysermc.connector.network.translators.inventory.DoubleChestInventoryTranslator;
|
||||||
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class InventoryUtils {
|
public class InventoryUtils {
|
||||||
|
public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new CompoundTag("")); //TODO: stop using this
|
||||||
|
|
||||||
public static void openInventory(GeyserSession session, Inventory inventory) {
|
public static void openInventory(GeyserSession session, Inventory inventory) {
|
||||||
InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType());
|
InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType());
|
||||||
|
@ -71,4 +78,31 @@ public class InventoryUtils {
|
||||||
session.setCraftSlot(0);
|
session.setCraftSlot(0);
|
||||||
session.getInventory().setCursor(null);
|
session.getInventory().setCursor(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void updateCursor(GeyserSession session) {
|
||||||
|
InventorySlotPacket cursorPacket = new InventorySlotPacket();
|
||||||
|
cursorPacket.setContainerId(ContainerId.CURSOR);
|
||||||
|
cursorPacket.setInventorySlot(0);
|
||||||
|
cursorPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor()));
|
||||||
|
session.getUpstream().sendPacket(cursorPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
//NPE if compound tag is null
|
||||||
|
public static ItemStack fixStack(ItemStack stack) {
|
||||||
|
if (stack == null || stack.getId() == 0)
|
||||||
|
return null;
|
||||||
|
return new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() == null ? new CompoundTag("") : stack.getNbt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canStack(ItemStack item1, ItemStack item2) {
|
||||||
|
if (item1 == null || item2 == null)
|
||||||
|
return false;
|
||||||
|
return item1.getId() == item2.getId() && Objects.equals(item1.getNbt(), item2.getNbt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canStack(ItemData item1, ItemData item2) {
|
||||||
|
if (item1 == null || item2 == null)
|
||||||
|
return false;
|
||||||
|
return item1.equals(item2, false, true, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
package org.geysermc.connector.utils;
|
package org.geysermc.connector.utils;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.nukkitx.nbt.NbtUtils;
|
import com.nukkitx.nbt.NbtUtils;
|
||||||
import com.nukkitx.nbt.stream.NBTInputStream;
|
import com.nukkitx.nbt.stream.NBTInputStream;
|
||||||
|
@ -150,31 +151,31 @@ public class Toolbox {
|
||||||
|
|
||||||
InputStream creativeItemStream = Toolbox.class.getClassLoader().getResourceAsStream("bedrock/creative_items.json");
|
InputStream creativeItemStream = Toolbox.class.getClassLoader().getResourceAsStream("bedrock/creative_items.json");
|
||||||
ObjectMapper creativeItemMapper = new ObjectMapper();
|
ObjectMapper creativeItemMapper = new ObjectMapper();
|
||||||
List<LinkedHashMap<String, Object>> creativeItemEntries = new ArrayList<>();
|
JsonNode creativeItemEntries;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
creativeItemEntries = (ArrayList<LinkedHashMap<String, Object>>) creativeItemMapper.readValue(creativeItemStream, HashMap.class).get("items");
|
creativeItemEntries = creativeItemMapper.readTree(creativeItemStream).get("items");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throw new AssertionError("Unable to load creative items", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ItemData> creativeItems = new ArrayList<>();
|
List<ItemData> creativeItems = new ArrayList<>();
|
||||||
for (Map<String, Object> map : creativeItemEntries) {
|
for (JsonNode itemNode : creativeItemEntries) {
|
||||||
short damage = 0;
|
short damage = 0;
|
||||||
if (map.containsKey("damage")) {
|
if (itemNode.has("damage")) {
|
||||||
damage = (short)(int) map.get("damage");
|
damage = itemNode.get("damage").numberValue().shortValue();
|
||||||
}
|
}
|
||||||
if (map.containsKey("nbt_b64")) {
|
if (itemNode.has("nbt_b64")) {
|
||||||
byte[] bytes = Base64.getDecoder().decode((String) map.get("nbt_b64"));
|
byte[] bytes = Base64.getDecoder().decode(itemNode.get("nbt_b64").asText());
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||||
try {
|
try {
|
||||||
com.nukkitx.nbt.tag.CompoundTag tag = (com.nukkitx.nbt.tag.CompoundTag) NbtUtils.createReaderLE(bais).readTag();
|
com.nukkitx.nbt.tag.CompoundTag tag = (com.nukkitx.nbt.tag.CompoundTag) NbtUtils.createReaderLE(bais).readTag();
|
||||||
creativeItems.add(ItemData.of((int) map.get("id"), damage, 1, tag));
|
creativeItems.add(ItemData.of(itemNode.get("id").asInt(), damage, 1, tag));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
creativeItems.add(ItemData.of((int) map.get("id"), damage, 1));
|
creativeItems.add(ItemData.of(itemNode.get("id").asInt(), damage, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue