Various fixes

Fix offhand, use AtomicInteger for transaction id, send null stack instead of air, and clear open inventory on dimension change
This commit is contained in:
AJ Ferguson 2019-10-22 15:31:03 -08:00
parent 38fd5376e7
commit 24c27a03a9
8 changed files with 69 additions and 40 deletions

View file

@ -31,6 +31,8 @@ import com.nukkitx.math.vector.Vector3i;
import lombok.Getter;
import lombok.Setter;
import java.util.concurrent.atomic.AtomicInteger;
public class Inventory {
@Getter
@ -43,6 +45,9 @@ public class Inventory {
@Getter
protected WindowType windowType;
@Getter
protected final int size;
@Getter
@Setter
protected String title;
@ -59,23 +64,22 @@ public class Inventory {
@Setter
protected long holderId = -1;
protected short transactionId = 1;
@Getter
protected AtomicInteger transactionId = new AtomicInteger(1);
public Inventory(int id, WindowType windowType) {
this("Inventory", id, windowType);
public Inventory(int id, WindowType windowType, int size) {
this("Inventory", id, windowType, size);
}
public Inventory(String title, int id, WindowType windowType) {
public Inventory(String title, int id, WindowType windowType, int size) {
this.title = title;
this.id = id;
this.windowType = windowType;
this.size = size;
this.items = new ItemStack[size];
}
public ItemStack getItem(int slot) {
return items[slot];
}
public short getNextTransactionId() {
return transactionId++;
}
}

View file

@ -39,9 +39,7 @@ public class PlayerInventory extends Inventory {
private ItemStack cursor;
public PlayerInventory() {
super(0, null);
items = new ItemStack[45];
super(0, null, 46);
heldItemSlot = 0;
}

View file

@ -45,7 +45,6 @@ import com.nukkitx.protocol.bedrock.data.ItemData;
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
@ -110,13 +109,13 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
boolean leftClick = containerAction.getToItem().getCount() == 0;
if (containerAction.getSource().getContainerId() != ContainerId.CURSOR) { //dropping directly from inventory
int javaSlot = translator.bedrockSlotToJava(containerAction);
ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
javaSlot, null, WindowAction.DROP_ITEM,
leftClick ? DropItemParam.DROP_SELECTED_STACK : DropItemParam.DROP_FROM_SELECTED);
session.getDownstream().getSession().send(dropPacket);
return;
} else { //clicking outside of inventory
ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
-999, null, WindowAction.CLICK_ITEM,
leftClick ? ClickItemParam.LEFT_CLICK : ClickItemParam.RIGHT_CLICK);
session.getDownstream().getSession().send(dropPacket);
@ -136,7 +135,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
if (InventoryUtils.canCombine(cursorAction.getFromItem(), cursorAction.getToItem())
&& cursorAction.getToItem().getCount() > cursorAction.getFromItem().getCount()) { //fill stack
int javaSlot = session.getLastClickedSlot();
ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
javaSlot, null, WindowAction.FILL_STACK, FillStackParam.FILL);
session.getDownstream().getSession().send(fillStackPacket);
translator.updateInventory(session, inventory); //bedrock fill stack can sometimes differ from java version, refresh and let server change slots
@ -153,8 +152,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
ItemStack translatedCursor = TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getFromItem());
boolean refresh = !Objects.equals(session.getInventory().getCursor(), translatedCursor.getId() == 0 ? null : translatedCursor); //refresh slot if there is a cursor mismatch
ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(),
inventory.getNextTransactionId(), javaSlot,
refresh ? new ItemStack(1, 127, new CompoundTag("")) : InventoryUtils.fixNbt(TranslatorsInit.getItemTranslator().translateToJava(containerAction.getFromItem())), //send invalid item stack to refresh slot
inventory.getTransactionId().getAndIncrement(), javaSlot,
refresh ? new ItemStack(1, 127, new CompoundTag("")) : InventoryUtils.fixStack(TranslatorsInit.getItemTranslator().translateToJava(containerAction.getFromItem())), //send invalid item stack to refresh slot
WindowAction.CLICK_ITEM, rightClick ? ClickItemParam.RIGHT_CLICK : ClickItemParam.LEFT_CLICK);
session.getDownstream().getSession().send(clickPacket);
inventory.getItems()[javaSlot] = TranslatorsInit.getItemTranslator().translateToJava(containerAction.getToItem());
@ -182,27 +181,27 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
//check if dealing with output only slot like furnace. this is to handle a situation where the output slot was partially emptied without right clicking (touchscreen or full inventory)
//this is only possible by shift clicking
if (translator.isOutputSlot(fromAction) && fromAction.getToItem().getCount() != 0) {
ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
fromSlot, InventoryUtils.fixNbt(inventory.getItem(fromSlot)), WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK);
ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
fromSlot, InventoryUtils.fixStack(inventory.getItem(fromSlot)), WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK);
session.getDownstream().getSession().send(shiftClickPacket);
inventory.getItems()[toSlot] = TranslatorsInit.getItemTranslator().translateToJava(toAction.getToItem());
inventory.getItems()[fromSlot] = TranslatorsInit.getItemTranslator().translateToJava(fromAction.getToItem());
return;
} else {
//pickup fromAction item
ClientWindowActionPacket leftClick1Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
fromSlot, InventoryUtils.fixNbt(TranslatorsInit.getItemTranslator().translateToJava(fromAction.getFromItem())), WindowAction.CLICK_ITEM,
ClientWindowActionPacket leftClick1Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
fromSlot, InventoryUtils.fixStack(TranslatorsInit.getItemTranslator().translateToJava(fromAction.getFromItem())), WindowAction.CLICK_ITEM,
ClickItemParam.LEFT_CLICK);
session.getDownstream().getSession().send(leftClick1Packet);
//release fromAction item into toAction slot
ClientWindowActionPacket leftClick2Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
toSlot, InventoryUtils.fixNbt(TranslatorsInit.getItemTranslator().translateToJava(toAction.getFromItem())), WindowAction.CLICK_ITEM,
ClientWindowActionPacket leftClick2Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
toSlot, InventoryUtils.fixStack(TranslatorsInit.getItemTranslator().translateToJava(toAction.getFromItem())), WindowAction.CLICK_ITEM,
ClickItemParam.LEFT_CLICK);
session.getDownstream().getSession().send(leftClick2Packet);
//test if swapping two items or moving one item
//if swapping then complete it
if (fromAction.getToItem().getId() != 0) {
ClientWindowActionPacket leftClick3Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
ClientWindowActionPacket leftClick3Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
fromSlot, null, WindowAction.CLICK_ITEM,
ClickItemParam.LEFT_CLICK);
session.getDownstream().getSession().send(leftClick3Packet);
@ -250,8 +249,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
}
}
int javaSlot = translator.bedrockSlotToJava(sourceAction);
ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
javaSlot, InventoryUtils.fixNbt(inventory.getItem(javaSlot)), WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK);
ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
javaSlot, InventoryUtils.fixStack(inventory.getItem(javaSlot)), WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK);
session.getDownstream().getSession().send(shiftClickPacket);
return;
} else if (destActions.size() == 1) { //fill stack
@ -259,17 +258,17 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
int javaSlot;
if (destAction != cursorAction) { //if touchscreen
javaSlot = translator.bedrockSlotToJava(destAction);
ClientWindowActionPacket leftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
javaSlot, InventoryUtils.fixNbt(inventory.getItem(javaSlot)), WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK);
ClientWindowActionPacket leftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
javaSlot, InventoryUtils.fixStack(inventory.getItem(javaSlot)), WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK);
session.getDownstream().getSession().send(leftClickPacket);
} else {
javaSlot = session.getLastClickedSlot();
}
ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
javaSlot, null, WindowAction.FILL_STACK, FillStackParam.FILL);
session.getDownstream().getSession().send(fillStackPacket);
if (destAction != cursorAction) { //if touchscreen
ClientWindowActionPacket leftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(),
ClientWindowActionPacket leftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(),
javaSlot, null, WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK);
session.getDownstream().getSession().send(leftClickPacket);
inventory.getItems()[javaSlot] = TranslatorsInit.getItemTranslator().translateToJava(destAction.getToItem());

View file

@ -34,7 +34,7 @@ import org.geysermc.connector.network.translators.TranslatorsInit;
public class PlayerInventoryTranslator extends InventoryTranslator {
public PlayerInventoryTranslator() {
super(45);
super(46);
}
@Override
@ -65,6 +65,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
}
armorContentPacket.setContents(contents);
session.getUpstream().sendPacket(armorContentPacket);
// Offhand
InventoryContentPacket offhandPacket = new InventoryContentPacket();
offhandPacket.setContainerId(ContainerId.OFFHAND);
offhandPacket.setContents(new ItemData[]{TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(45))});
session.getUpstream().sendPacket(offhandPacket);
}
@Override
@ -86,6 +92,11 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
session.getUpstream().sendPacket(slotPacket);
} else if (slot == 0) {
//TODO: crafting output
} else if (slot == 45) {
InventoryContentPacket offhandPacket = new InventoryContentPacket();
offhandPacket.setContainerId(ContainerId.OFFHAND);
offhandPacket.setContents(new ItemData[]{TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot))});
session.getUpstream().sendPacket(offhandPacket);
}
}
@ -108,6 +119,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
return slotnum + 5;
}
break;
case ContainerId.OFFHAND:
return 45;
case ContainerId.CRAFTING_ADD_INGREDIENT:
case ContainerId.CRAFTING_REMOVE_INGREDIENT:
return slotnum + 1;

View file

@ -44,6 +44,7 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
if (entity.getDimension() == getDimension(packet.getDimension()))
return;
session.getInventoryCache().setOpenInventory(null);
session.getChunkCache().getChunks().clear();
entity.setDimension(getDimension(packet.getDimension()));

View file

@ -28,6 +28,7 @@ package org.geysermc.connector.network.translators.java.window;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCloseWindowPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerOpenWindowPacket;
import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket;
import org.geysermc.api.Geyser;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
@ -42,15 +43,23 @@ public class JavaOpenWindowTranslator extends PacketTranslator<ServerOpenWindowP
@Override
public void translate(ServerOpenWindowPacket packet, GeyserSession session) {
if (packet.getWindowId() == 0) {
return;
}
InventoryTranslator newTranslator = TranslatorsInit.getInventoryTranslators().get(packet.getType());
Inventory openInventory = session.getInventoryCache().getOpenInventory();
if (newTranslator == null) {
if (openInventory != null) {
ContainerClosePacket closePacket = new ContainerClosePacket();
closePacket.setWindowId((byte)openInventory.getId());
session.getUpstream().sendPacket(closePacket);
TranslatorsInit.getInventoryTranslators().get(openInventory.getWindowType()).closeInventory(session, openInventory);
}
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(packet.getWindowId());
session.getDownstream().getSession().send(closeWindowPacket);
return;
}
Inventory openInventory = session.getInventoryCache().getOpenInventory();
Inventory newInventory = new Inventory(packet.getWindowId(), packet.getType());
newInventory.setItems(new ItemStack[newTranslator.size + 36]);
Inventory newInventory = new Inventory(packet.getWindowId(), packet.getType(), newTranslator.size + 36);
session.getInventoryCache().cacheInventory(newInventory);
if (openInventory != null) {
InventoryTranslator openTranslator = TranslatorsInit.getInventoryTranslators().get(openInventory.getWindowType());

View file

@ -28,11 +28,11 @@ package org.geysermc.connector.network.translators.java.window;
import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerWindowItemsPacket;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.session.cache.InventoryCache;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.TranslatorsInit;
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.utils.InventoryUtils;
import java.util.Arrays;
public class JavaWindowItemsTranslator extends PacketTranslator<ServerWindowItemsPacket> {
@ -42,7 +42,12 @@ public class JavaWindowItemsTranslator extends PacketTranslator<ServerWindowItem
if (inventory == null || (packet.getWindowId() != 0 && inventory.getWindowType() == null))
return;
if (packet.getItems().length < inventory.getSize()) {
inventory.setItems(Arrays.copyOf(packet.getItems(), inventory.getSize()));
} else {
inventory.setItems(packet.getItems());
}
InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType());
if (translator != null) {
translator.updateInventory(session, inventory);

View file

@ -42,10 +42,10 @@ public class InventoryUtils {
InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType());
translator.closeInventory(session, inventory);
session.getInventoryCache().uncacheInventory(windowId);
}
session.getInventoryCache().setOpenInventory(null);
}
}
}
//currently, ItemStack.equals() does not check the item id
public static boolean canCombine(ItemData stack1, ItemData stack2) {
@ -55,8 +55,8 @@ public class InventoryUtils {
}
//NPE if nbt tag is null
public static ItemStack fixNbt(ItemStack stack) {
if (stack == 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());
}