ViaVersion/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/storage/InventoryTracker.java

184 lines
6.5 KiB
Java

/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.protocol1_9to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
import java.util.HashMap;
import java.util.Map;
public class InventoryTracker extends StoredObject {
private String inventory;
private final Map<Short, Map<Short, Integer>> windowItemCache = new HashMap<>();
private int itemIdInCursor = 0;
private boolean dragging = false;
public InventoryTracker(UserConnection user) {
super(user);
}
public String getInventory() {
return inventory;
}
public void setInventory(String inventory) {
this.inventory = inventory;
}
public void resetInventory(short windowId) {
// Reset the cursor state of the inventory
if (inventory == null) {
this.itemIdInCursor = 0;
this.dragging = false;
// Remove window from cache (Except players window)
if (windowId != 0) {
this.windowItemCache.remove(windowId);
}
}
}
public int getItemId(short windowId, short slot) {
Map<Short, Integer> itemMap = this.windowItemCache.get(windowId);
if (itemMap == null) {
return 0;
}
return itemMap.getOrDefault(slot, 0);
}
public void setItemId(short windowId, short slot, int itemId) {
if (windowId == -1 && slot == -1) {
// Set the cursor item
this.itemIdInCursor = itemId;
} else {
// Set item in normal inventory
this.windowItemCache.computeIfAbsent(windowId, k -> new HashMap<>()).put(slot, itemId);
}
}
/**
* Handle the window click to track the position of the sword
*
* @param windowId Id of the current inventory
* @param mode Inventory operation mode
* @param hoverSlot The slot number of the current mouse position
* @param button The button to use in the click
*/
public void handleWindowClick(short windowId, byte mode, short hoverSlot, byte button) {
EntityTracker1_9 entityTracker = getUser().getEntityTracker(Protocol1_9To1_8.class);
// Skip inventory background clicks
if (hoverSlot == -1) {
return;
}
// Interaction with the offhand slot
if (hoverSlot == 45) {
entityTracker.setSecondHand(null); // Remove it so we know that we can update it on ITEM_USE
return;
}
// It is not possible to put a sword into the armor or crafting result slot
boolean isArmorOrResultSlot = hoverSlot >= 5 && hoverSlot <= 8 || hoverSlot == 0;
switch (mode) {
case 0: // Click on slot
// The cursor is empty, so we can put an item to it
if (this.itemIdInCursor == 0) {
// Move item to cursor
this.itemIdInCursor = getItemId(windowId, hoverSlot);
// Remove item in slot
setItemId(windowId, hoverSlot, 0);
} else {
// Dropping item
if (hoverSlot == -999) {
this.itemIdInCursor = 0;
} else if (!isArmorOrResultSlot) {
int previousItem = getItemId(windowId, hoverSlot);
// Place item in inventory
setItemId(windowId, hoverSlot, this.itemIdInCursor);
// Pick up the other item
this.itemIdInCursor = previousItem;
}
}
break;
case 2: // Move item using number keys
if (!isArmorOrResultSlot) {
short hotkeySlot = (short) (button + 36);
// Get items to swap
int sourceItem = getItemId(windowId, hoverSlot);
int destinationItem = getItemId(windowId, hotkeySlot);
// Swap
setItemId(windowId, hotkeySlot, sourceItem);
setItemId(windowId, hoverSlot, destinationItem);
}
break;
case 4: // Drop item
int hoverItem = getItemId(windowId, hoverSlot);
if (hoverItem != 0) {
setItemId(windowId, hoverSlot, 0);
}
break;
case 5: // Mouse dragging
switch (button) {
case 0: // Start left dragging
case 4: // Start right dragging
this.dragging = true;
break;
case 1: // Place item during left dragging
case 5: // Place item during right dragging
// Check dragging mode and item on cursor
if (this.dragging && this.itemIdInCursor != 0 && !isArmorOrResultSlot) {
int previousItem = getItemId(windowId, hoverSlot);
// Place item on cursor in hovering slot
setItemId(windowId, hoverSlot, this.itemIdInCursor);
// Pick up the other item
this.itemIdInCursor = previousItem;
}
break;
case 2: // Stop left dragging
case 6: // Stop right dragging
this.dragging = false;
break;
}
break;
default:
break;
}
// Update shield state in offhand
entityTracker.syncShieldWithSword();
}
}