Complete inventory shift click

Complete item stacking mechanism for left click
This commit is contained in:
ReinforceZwei 2020-07-21 16:22:45 +08:00 committed by ORelio
parent a6e6668fe0
commit 9137fa59e7
5 changed files with 180 additions and 27 deletions

View file

@ -172,5 +172,19 @@ namespace MinecraftClient.Inventory
}
return result.ToArray();
}
public int[] GetEmpytSlot()
{
List<int> result = new List<int>();
for (int i = 0; i < Type.SlotCount(); i++)
{
result.Add(i);
}
foreach (var item in Items)
{
result.Remove(item.Key);
}
return result.ToArray();
}
}
}

View file

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Inventory
{
public static class ContainerTypeExtensions
{
public static int SlotCount(this ContainerType c)
{
switch (c)
{
case ContainerType.PlayerInventory: return 44;
case ContainerType.Generic_9x3: return 62;
case ContainerType.Generic_9x6: return 89;
case ContainerType.Generic_3x3: return 44;
case ContainerType.Crafting: return 45;
case ContainerType.BlastFurnace: return 38;
case ContainerType.Furnace: return 38;
case ContainerType.Smoker: return 38;
case ContainerType.Enchantment: return 37;
case ContainerType.BrewingStand: return 40;
case ContainerType.Merchant: return 38;
case ContainerType.Beacon: return 36;
case ContainerType.Anvil: return 38;
case ContainerType.Hopper: return 40;
case ContainerType.ShulkerBox: return 62;
case ContainerType.Loom: return 39;
case ContainerType.Stonecutter: return 37;
case ContainerType.Lectern: return 36;
case ContainerType.Cartography: return 38;
case ContainerType.Grindstone: return 38;
case ContainerType.Unknown: return 0;
default: return 0;
}
}
}
}

View file

@ -1006,9 +1006,20 @@ namespace MinecraftClient
// Check if both item are the same?
if (inventory.Items[slotId].Type == playerInventory.Items[-1].Type)
{
// Put cursor item to target
inventory.Items[slotId].Count += playerInventory.Items[-1].Count;
playerInventory.Items.Remove(-1);
int maxCount = inventory.Items[slotId].Type.StackCount();
// Check item stacking
if ((inventory.Items[slotId].Count + playerInventory.Items[-1].Count) <= maxCount)
{
// Put cursor item to target
inventory.Items[slotId].Count += playerInventory.Items[-1].Count;
playerInventory.Items.Remove(-1);
}
else
{
// Leave some item on cursor
playerInventory.Items[-1].Count -= (maxCount - inventory.Items[slotId].Count);
inventory.Items[slotId].Count = maxCount;
}
}
else
{
@ -1052,9 +1063,13 @@ namespace MinecraftClient
// Check if both item are the same?
if (inventory.Items[slotId].Type == playerInventory.Items[-1].Type)
{
// Drop 1 item count from cursor
playerInventory.Items[-1].Count--;
inventory.Items[slotId].Count++;
// Check item stacking
if (inventory.Items[slotId].Count < inventory.Items[slotId].Type.StackCount())
{
// Drop 1 item count from cursor
playerInventory.Items[-1].Count--;
inventory.Items[slotId].Count++;
}
}
else
{
@ -1117,33 +1132,117 @@ namespace MinecraftClient
{
/* Target slot have item */
// Cursor have item or not doesn't matter
int upperStartSlot = 9;
int upperEndSlot = 35;
switch (inventory.Type)
{
case ContainerType.PlayerInventory: // Shift click within player inventory
// If hotbar already have same item, will put on it first until every stack are full
// If no more same item , will put on the first empty slot (smaller slot id)
// If inventory full, item will not move
if (slotId < 36)
{
// Clicked slot is on upper side inventory, put it to hotbar
foreach(KeyValuePair<int, Item> _item in playerInventory.Items)
{
if (_item.Key < 35) continue;
case ContainerType.PlayerInventory:
upperStartSlot = 9;
upperEndSlot = 35;
break;
case ContainerType.Crafting:
upperStartSlot = 1;
upperEndSlot = 9;
break;
// TODO: Define more container type here
}
if (_item.Value.Type == inventory.Items[slotId].Type && _item.Value.Count < 64)
{
//
}
// Cursor have item or not doesn't matter
// If hotbar already have same item, will put on it first until every stack are full
// If no more same item , will put on the first empty slot (smaller slot id)
// If inventory full, item will not move
if (slotId <= upperEndSlot)
{
// Clicked slot is on upper side inventory, put it to hotbar
// Now try to find same item and put on them
var itemsClone = playerInventory.Items.ToDictionary(entry => entry.Key, entry => entry.Value);
foreach (KeyValuePair<int, Item> _item in itemsClone)
{
if (_item.Key <= upperEndSlot) continue;
int maxCount = _item.Value.Type.StackCount();
if (_item.Value.Type == inventory.Items[slotId].Type && _item.Value.Count < maxCount)
{
// Put item on that stack
int spaceLeft = maxCount - _item.Value.Count;
if (inventory.Items[slotId].Count <= spaceLeft)
{
// Can fit into the stack
inventory.Items[_item.Key].Count += inventory.Items[slotId].Count;
inventory.Items.Remove(slotId);
}
else
{
inventory.Items[slotId].Count -= spaceLeft;
inventory.Items[_item.Key].Count = inventory.Items[_item.Key].Type.StackCount();
}
}
else
}
if (inventory.Items[slotId].Count > 0)
{
int[] emptySlots = inventory.GetEmpytSlot();
int emptySlot = -2;
foreach (int slot in emptySlots)
{
// Clicked slot is on hotbar, put it to upper inventory
if (slot <= upperEndSlot) continue;
emptySlot = slot;
break;
}
break;
if (emptySlot != -2)
{
var itemTmp = inventory.Items[slotId];
inventory.Items[emptySlot] = new Item((int)itemTmp.Type, itemTmp.Count, itemTmp.NBT);
inventory.Items.Remove(slotId);
}
}
}
else
{
// Clicked slot is on hotbar, put it to upper inventory
// Now try to find same item and put on them
var itemsClone = playerInventory.Items.ToDictionary(entry => entry.Key, entry => entry.Value);
foreach (KeyValuePair<int, Item> _item in itemsClone)
{
if (_item.Key < upperStartSlot) continue;
if (_item.Key >= upperEndSlot) break;
int maxCount = _item.Value.Type.StackCount();
if (_item.Value.Type == inventory.Items[slotId].Type && _item.Value.Count < maxCount)
{
// Put item on that stack
int spaceLeft = maxCount - _item.Value.Count;
if (inventory.Items[slotId].Count <= spaceLeft)
{
// Can fit into the stack
inventory.Items[_item.Key].Count += inventory.Items[slotId].Count;
inventory.Items.Remove(slotId);
}
else
{
inventory.Items[slotId].Count -= spaceLeft;
inventory.Items[_item.Key].Count = inventory.Items[_item.Key].Type.StackCount();
}
}
}
if (inventory.Items[slotId].Count > 0)
{
int[] emptySlots = inventory.GetEmpytSlot();
int emptySlot = -2;
foreach (int slot in emptySlots)
{
if (slot < upperStartSlot) continue;
if (slot >= upperEndSlot) break;
emptySlot = slot;
break;
}
if (emptySlot != -2)
{
var itemTmp = inventory.Items[slotId];
inventory.Items[emptySlot] = new Item((int)itemTmp.Type, itemTmp.Count, itemTmp.NBT);
inventory.Items.Remove(slotId);
}
}
}
}
break;

View file

@ -112,6 +112,7 @@
<Compile Include="Commands\UseItem.cs" />
<Compile Include="Inventory\Container.cs" />
<Compile Include="Inventory\ContainerType.cs" />
<Compile Include="Inventory\ContainerTypeExtensions.cs" />
<Compile Include="Inventory\Effects.cs" />
<Compile Include="Inventory\Hand.cs" />
<Compile Include="Inventory\Item.cs" />

View file

@ -1573,7 +1573,7 @@ namespace MinecraftClient.Protocol.Handlers
case WindowActionType.LeftClick: button = 0; break;
case WindowActionType.RightClick: button = 1; break;
case WindowActionType.MiddleClick: button = 2; mode = 3; break;
case WindowActionType.ShiftClick: button = 0; mode = 1; break;
case WindowActionType.ShiftClick: button = 0; mode = 1; item = new Item(-1, 0, null); break;
case WindowActionType.DropItem:
button = 0;
mode = 4;