Skip to content
This repository was archived by the owner on Apr 7, 2021. It is now read-only.

Inventories #489

Draft
wants to merge 7 commits into
base: rewrite
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import lombok.Getter;
import org.dragonet.proxy.data.window.BedrockWindowType;
import org.dragonet.proxy.network.session.cache.object.CachedWindow;
import org.dragonet.proxy.network.translator.misc.inventory.IInventoryTranslator;
import org.dragonet.proxy.network.translator.misc.inventory.PlayerInventoryTranslator;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -36,9 +38,10 @@ public class WindowCache implements Cache {
private AtomicInteger javaActionIdAllocator = new AtomicInteger(1);

private AtomicInteger localWindowIdAllocator = new AtomicInteger(1000);
private AtomicInteger transactionIdCounter = new AtomicInteger(0);

public WindowCache() {
windows.put(0, new CachedWindow(0, null, 45));
windows.put(0, new CachedWindow(0, new PlayerInventoryTranslator(45)));
}

public CachedWindow getPlayerInventory() {
Expand All @@ -52,8 +55,8 @@ public CachedWindow getById(int windowId) {
return null;
}

public CachedWindow newWindow(BedrockWindowType windowType, int windowId) {
CachedWindow window = new CachedWindow(windowId, windowType, 50);
public CachedWindow newWindow(IInventoryTranslator inventoryTranslator, int windowId) {
CachedWindow window = new CachedWindow(windowId, inventoryTranslator);
windows.put(window.getWindowId(), window);
return window;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,47 @@
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.tag.CompoundTag;
import com.nukkitx.protocol.bedrock.data.EntityData;
import com.nukkitx.protocol.bedrock.data.ItemData;
import com.nukkitx.protocol.bedrock.packet.*;
import it.unimi.dsi.fastutil.ints.Int2BooleanMap;
import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.data.entity.BedrockEntityType;
import org.dragonet.proxy.data.window.BedrockWindowType;
import org.dragonet.proxy.network.session.ProxySession;
import org.dragonet.proxy.network.translator.ItemTranslatorRegistry;
import org.dragonet.proxy.network.translator.misc.BlockEntityTranslator;
import org.dragonet.proxy.network.translator.misc.BlockTranslator;
import org.dragonet.proxy.network.translator.misc.inventory.IInventoryTranslator;
import org.dragonet.proxy.network.translator.misc.inventory.action.SlotChangeAction;

import java.util.concurrent.atomic.AtomicInteger;

@Data
@Log4j2
public class CachedWindow {
private final int windowId;

private ItemStack[] items;
private IInventoryTranslator inventoryTranslator;
private BedrockWindowType windowType;

private String name;
private boolean open = false;

private Vector3i fakeBlockPosition = null;

public CachedWindow(int windowId, BedrockWindowType windowType, int size) {
private AtomicInteger transactionIdCounter = new AtomicInteger(1);
private Int2BooleanMap transactions = new Int2BooleanOpenHashMap();

public CachedWindow(int windowId, IInventoryTranslator inventoryTranslator) {
this.windowId = windowId;
this.windowType = windowType;
this.items = new ItemStack[size];
this.inventoryTranslator = inventoryTranslator;
this.items = new ItemStack[inventoryTranslator.getSize()];
this.windowType = inventoryTranslator.getBedrockWindowType();
}

public void open(ProxySession session) {
Expand Down Expand Up @@ -96,6 +111,27 @@ public void close(ProxySession session) {
// TODO: should we remove the window from the cache at this point? i'll leave it for now.
}

public void sendInventory(ProxySession session) {
inventoryTranslator.updateInventory(session, this);
}

public void sendSlot(ProxySession session, int slot) {
inventoryTranslator.updateSlot(session, this, slot);
}

public boolean setItem(int slot, ItemData item) {
if(slot > items.length) {
log.warn("set item");
return false;
}
this.items[slot] = ItemTranslatorRegistry.translateToJava(item);
return true;
}

public ItemData getItem(int slot) {
return ItemTranslatorRegistry.translateSlotToBedrock(items[slot]);
}

private void sendFakeEntity(ProxySession session, Vector3i position) {
long entityId = session.getEntityCache().getNextClientEntityId().getAndIncrement();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,38 @@
*/
package org.dragonet.proxy.network.translator.bedrock;

import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
import com.github.steveice10.mc.protocol.data.game.window.ClickItemParam;
import com.github.steveice10.mc.protocol.data.game.window.WindowAction;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket;
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.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.ContainerId;
import com.nukkitx.protocol.bedrock.data.InventoryActionData;
import com.nukkitx.protocol.bedrock.data.InventorySource;
import com.nukkitx.protocol.bedrock.data.ItemData;
import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.network.session.ProxySession;
import org.dragonet.proxy.network.session.cache.object.CachedEntity;
import org.dragonet.proxy.network.session.cache.object.CachedWindow;
import org.dragonet.proxy.network.translator.ItemTranslatorRegistry;
import org.dragonet.proxy.network.translator.misc.PacketTranslator;
import org.dragonet.proxy.util.registry.PacketRegisterInfo;
import org.dragonet.proxy.network.translator.misc.inventory.action.DropItemAction;
import org.dragonet.proxy.network.translator.misc.inventory.action.IInventoryAction;
import org.dragonet.proxy.network.translator.misc.inventory.action.SlotChangeAction;
import org.dragonet.proxy.util.TextFormat;
import org.dragonet.proxy.util.registry.PacketRegisterInfo;

@Log4j2
@PacketRegisterInfo(packet = InventoryTransactionPacket.class)
Expand All @@ -55,7 +66,7 @@ public void translate(ProxySession session, InventoryTransactionPacket packet) {

switch(source.getType()) {
case WORLD_INTERACTION:
session.sendRemotePacket(new ClientPlayerActionPacket(PlayerAction.DROP_ITEM, new Position(0, 0, 0), BlockFace.UP));
executeAction(session, new DropItemAction(action));
break;
case CREATIVE:
switch(action.getSlot()) {
Expand All @@ -68,6 +79,36 @@ public void translate(ProxySession session, InventoryTransactionPacket packet) {
break;
}
break;
case CONTAINER:
CachedWindow inventory = session.getWindowCache().getById(source.getContainerId());
if(inventory == null) {
log.warn("inventory translator: inventory is null");
return;
}

// TODO
executeAction(session, new SlotChangeAction(inventory, action, WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK));
break;
case NON_IMPLEMENTED_TODO:
if(source.getContainerId() >= ContainerId.ANVIL_OUTPUT && source.getContainerId() <= -10 /* anvil input */) {
if (source.getContainerId() == ContainerId.ANVIL_RESULT) {
ItemData item = action.getFromItem();
String name = item.getTag() != null ? item.getTag().getCompound("display").getString("Name") : "";

session.sendRemotePacket(new ClientRenameItemPacket(name));
}
}

if(source.getContainerId() == ContainerId.BEACON) {
CachedWindow beacon = session.getWindowCache().getById(source.getContainerId());
if(beacon == null) {
log.warn("inventory translator: beacon inventory is null");
return;
}

executeAction(session, new SlotChangeAction(beacon, action, WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK));
}
break;
}
}
break;
Expand Down Expand Up @@ -111,4 +152,13 @@ public void translate(ProxySession session, InventoryTransactionPacket packet) {
break;
}
}

private void executeAction(ProxySession session, IInventoryAction action) {
if(action.isValid(session) && action.execute(session)) {
action.onSuccess(session);
} else {
log.info("inventory action failed: " + action.getClass().getSimpleName());
action.onFail(session);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ public void translate(ProxySession session, PlayerActionPacket packet) {

// Open command block window, as its handled client side on Java edition
if(session.getChunkCache().getBlockAt(packet.getBlockPosition()) == BlockTranslator.BEDROCK_COMMAND_BLOCK_ID) {
CachedWindow cachedWindow = session.getWindowCache().newWindow(BedrockWindowType.COMMAND_BLOCK, session.getWindowCache().getLocalWindowIdAllocator().getAndIncrement());
cachedWindow.setName("Command Block");
cachedWindow.open(session);
// CachedWindow cachedWindow = session.getWindowCache().newWindow(session.getWindowCache().getLocalWindowIdAllocator().getAndIncrement());
// cachedWindow.setName("Command Block");
// cachedWindow.open(session);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerConfirmTransactionPacket;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.network.session.ProxySession;
import org.dragonet.proxy.network.session.cache.object.CachedWindow;
import org.dragonet.proxy.network.translator.misc.PacketTranslator;
import org.dragonet.proxy.util.registry.PacketRegisterInfo;

Expand All @@ -32,6 +33,15 @@ public class PCConfirmTransactionTranslator extends PacketTranslator<ServerConfi

@Override
public void translate(ProxySession session, ServerConfirmTransactionPacket packet) {
session.sendRemotePacket(new ClientConfirmTransactionPacket(packet.getWindowId(), packet.getActionId(), packet.isAccepted()));
CachedWindow inventory = session.getWindowCache().getById(packet.getWindowId());
if(inventory == null) {
return;
}

boolean transactionStatus = inventory.getTransactions().get(packet.getActionId());

if(!packet.isAccepted()) {
session.sendRemotePacket(new ClientConfirmTransactionPacket(packet.getWindowId(), packet.getActionId(), true));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,50 +19,53 @@
package org.dragonet.proxy.network.translator.java.window;

import com.github.steveice10.mc.protocol.data.game.window.WindowType;
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.data.ItemData;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.data.window.BedrockWindowType;
import org.dragonet.proxy.network.session.ProxySession;
import org.dragonet.proxy.network.session.cache.object.CachedWindow;
import org.dragonet.proxy.network.translator.misc.PacketTranslator;
import org.dragonet.proxy.util.registry.PacketRegisterInfo;
import org.dragonet.proxy.network.translator.misc.MessageTranslator;
import org.dragonet.proxy.network.translator.misc.PacketTranslator;
import org.dragonet.proxy.network.translator.misc.inventory.*;
import org.dragonet.proxy.util.TextFormat;
import org.dragonet.proxy.util.registry.PacketRegisterInfo;

import java.util.HashMap;
import java.util.Map;

@Log4j2
@PacketRegisterInfo(packet = ServerOpenWindowPacket.class)
public class PCOpenWindowTranslator extends PacketTranslator<ServerOpenWindowPacket> {
private static final Map<WindowType, BedrockWindowType> windowMap = new HashMap<>();
private static final Map<WindowType, IInventoryTranslator> windowMap = new HashMap<>();

static {
windowMap.put(WindowType.ANVIL, BedrockWindowType.ANVIL);
windowMap.put(WindowType.BEACON, BedrockWindowType.BEACON);
windowMap.put(WindowType.ENCHANTMENT, BedrockWindowType.ENCHANT_TABLE);
windowMap.put(WindowType.BREWING_STAND, BedrockWindowType.BREWING_STAND);
windowMap.put(WindowType.FURNACE, BedrockWindowType.FURNACE);
windowMap.put(WindowType.HOPPER, BedrockWindowType.HOPPER);
windowMap.put(WindowType.CRAFTING, BedrockWindowType.CRAFTING_TABLE);
//windowMap.put(WindowType.MERCHANT, BedrockWindowType.TRADING);
windowMap.put(WindowType.BLAST_FURNACE, BedrockWindowType.BLAST_FURNACE);
windowMap.put(WindowType.SMOKER, BedrockWindowType.SMOKER);
windowMap.put(WindowType.STONECUTTER, BedrockWindowType.STONECUTTER);
// TODO: chest style inventories
windowMap.put(WindowType.GENERIC_9X1, new SingleChestInventoryTranslator(27, 1));
windowMap.put(WindowType.GENERIC_9X2, new SingleChestInventoryTranslator(27, 2));
windowMap.put(WindowType.GENERIC_9X3, new SingleChestInventoryTranslator(27, 3));
windowMap.put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(54, 4));
windowMap.put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(54, 5));
windowMap.put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54, 6));
windowMap.put(WindowType.SHULKER_BOX, new SingleChestInventoryTranslator(BedrockWindowType.SHULKER_BOX, 27, 3));
windowMap.put(WindowType.GENERIC_3X3, new DispenserInventoryTranslator(9));
windowMap.put(WindowType.ANVIL, new AnvilInventoryTranslator(3));
windowMap.put(WindowType.FURNACE, new FurnaceInventoryTranslator(3));
windowMap.put(WindowType.BEACON, new BeaconInventoryTranslator(1));
}

@Override
public void translate(ProxySession session, ServerOpenWindowPacket packet) {
BedrockWindowType bedrockWindowType = windowMap.get(packet.getType());
if(bedrockWindowType == null) {
log.info(TextFormat.GRAY + "(debug) Unhandled window type: " + packet.getType().name() + TextFormat.AQUA + " It is not supported yet.");
IInventoryTranslator bedrockWindowTranslator = windowMap.get(packet.getType());
if(bedrockWindowTranslator == null) {
log.info(TextFormat.GRAY + "(debug) Unhandled window type: " + packet.getType().name() + ". It is not supported yet.");

// Close the window
session.sendRemotePacket(new ClientCloseWindowPacket(packet.getWindowId()));
return;
}

//log.warn("WINDOW: " + packet.getWindowId() + " - " + packet.getType().name());

CachedWindow cachedWindow = session.getWindowCache().newWindow(bedrockWindowType, packet.getWindowId());
CachedWindow cachedWindow = session.getWindowCache().newWindow(bedrockWindowTranslator, packet.getWindowId());
cachedWindow.setName(MessageTranslator.translate(packet.getName()));
cachedWindow.open(session);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@

import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerSetSlotPacket;
import com.nukkitx.protocol.bedrock.data.ContainerId;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.network.session.ProxySession;
import org.dragonet.proxy.network.session.cache.WindowCache;
import org.dragonet.proxy.network.session.cache.object.CachedWindow;
import org.dragonet.proxy.network.translator.misc.PacketTranslator;
import org.dragonet.proxy.util.registry.PacketRegisterInfo;
import org.dragonet.proxy.network.translator.misc.InventoryTranslator;


@Log4j2
@PacketRegisterInfo(packet = ServerSetSlotPacket.class)
Expand All @@ -41,7 +40,6 @@ public void translate(ProxySession session, ServerSetSlotPacket packet) {
return;
}
CachedWindow window = windowCache.getWindows().get(packet.getWindowId());
// log.warn("Set slot translator: " + packet.getWindowId());
if(packet.getWindowId() != 0 && window.getWindowType() == null) {
return;
}
Expand All @@ -54,13 +52,14 @@ public void translate(ProxySession session, ServerSetSlotPacket packet) {
items[packet.getSlot()] = packet.getItem();
window.setItems(items);

InventoryTranslator.sendPlayerInventory(session);
//InventoryTranslator.sendPlayerInventory(session);
}

if(window.isOpen()) {
// update slot
if(window.isOpen() || window.getWindowId() == ContainerId.INVENTORY) {
window.getItems()[packet.getSlot()] = packet.getItem();
window.sendSlot(session, packet.getSlot());
} else {
// cache packet
log.warn("tried to set slot of closed inventory");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@
package org.dragonet.proxy.network.translator.java.window;

import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerWindowItemsPacket;
import com.nukkitx.protocol.bedrock.data.ContainerId;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.network.session.ProxySession;
import org.dragonet.proxy.network.session.cache.WindowCache;
import org.dragonet.proxy.network.session.cache.object.CachedWindow;
import org.dragonet.proxy.network.translator.misc.PacketTranslator;
import org.dragonet.proxy.util.registry.PacketRegisterInfo;
import org.dragonet.proxy.network.translator.misc.InventoryTranslator;


@Log4j2
@PacketRegisterInfo(packet = ServerWindowItemsPacket.class)
Expand All @@ -46,12 +45,11 @@ public void translate(ProxySession session, ServerWindowItemsPacket packet) {
return;
}

if(packet.getWindowId() == 0) {
if(packet.getItems().length < 40) {
return; // TODO: check this?
}
if(window.isOpen() || window.getWindowId() == ContainerId.INVENTORY) {
window.setItems(packet.getItems());
InventoryTranslator.sendPlayerInventory(session);
window.sendInventory(session);
} else {
log.warn("tried to set items of closed inventory");
}
}
}
Loading