mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
bugfix: Player inventory state sync from the Container inventory
bugfix: Player inventory state sync from the Container inventory
This commit is contained in:
commit
5b13e740ef
3 changed files with 87 additions and 39 deletions
|
|
@ -54,6 +54,7 @@ namespace MinecraftClient
|
|||
private readonly List<ChatBot> bots = new();
|
||||
private static readonly List<ChatBot> botsOnHold = new();
|
||||
private static readonly Dictionary<int, Container> inventories = new();
|
||||
private static readonly HashSet<int> inventoriesWithFullContents = new();
|
||||
private readonly Dictionary<string, RecipeBookRecipeEntry> unlockedRecipes = new(StringComparer.Ordinal);
|
||||
private readonly Dictionary<string, Achievement> achievements = new(StringComparer.Ordinal);
|
||||
private string? activeAdvancementTab;
|
||||
|
|
@ -2004,8 +2005,8 @@ namespace MinecraftClient
|
|||
if (item.Count <= spaceLeft)
|
||||
{
|
||||
// Can fit into the stack
|
||||
item.Count = 0;
|
||||
curItem.Count += item.Count;
|
||||
item.Count = 0;
|
||||
|
||||
changedSlots.Add(new Tuple<short, Item?>((short)curId, curItem));
|
||||
changedSlots.Add(new Tuple<short, Item?>((short)slotId, null));
|
||||
|
|
@ -2067,12 +2068,12 @@ namespace MinecraftClient
|
|||
firstWindowSlot = -1;
|
||||
lastWindowSlot = -1;
|
||||
|
||||
if (inventory.Type == ContainerType.PlayerInventory)
|
||||
if (inventory.Type is ContainerType.PlayerInventory or ContainerType.Unknown)
|
||||
return false;
|
||||
|
||||
const int mirroredPlayerInventorySlotCount = 36;
|
||||
int slotCount = inventory.Type.SlotCount();
|
||||
if (slotCount < mirroredPlayerInventorySlotCount)
|
||||
if (slotCount <= mirroredPlayerInventorySlotCount)
|
||||
return false;
|
||||
|
||||
firstWindowSlot = slotCount - mirroredPlayerInventorySlotCount;
|
||||
|
|
@ -2080,20 +2081,6 @@ namespace MinecraftClient
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool TryGetMirroredPlayerInventorySlot(Container inventory, int windowSlot, out int playerInventorySlot)
|
||||
{
|
||||
playerInventorySlot = -1;
|
||||
|
||||
if (!TryGetMirroredPlayerInventoryRange(inventory, out int firstWindowSlot, out int lastWindowSlot))
|
||||
return false;
|
||||
|
||||
if (windowSlot < firstWindowSlot || windowSlot > lastWindowSlot)
|
||||
return false;
|
||||
|
||||
playerInventorySlot = windowSlot - firstWindowSlot + 9;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool AreSameInventorySlot(Item? left, Item? right)
|
||||
{
|
||||
if (left is null || left.IsEmpty)
|
||||
|
|
@ -2113,35 +2100,67 @@ namespace MinecraftClient
|
|||
if (!inventories.TryGetValue(0, out Container? playerInventory))
|
||||
return false;
|
||||
|
||||
if (item is null || item.IsEmpty)
|
||||
return playerInventory.Items.Remove(playerInventorySlot);
|
||||
|
||||
Item itemClone = item.CloneWithCount(item.Count);
|
||||
|
||||
playerInventory.Items.TryGetValue(playerInventorySlot, out Item? previousItem);
|
||||
if (AreSameInventorySlot(previousItem, item))
|
||||
if (AreSameInventorySlot(previousItem, itemClone))
|
||||
return false;
|
||||
|
||||
if (item is null || item.IsEmpty)
|
||||
playerInventory.Items.Remove(playerInventorySlot);
|
||||
else
|
||||
playerInventory.Items[playerInventorySlot] = item;
|
||||
playerInventory.Items[playerInventorySlot] = itemClone;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SyncPlayerInventorySlotFromWindow(Container inventory, int windowSlot)
|
||||
private bool SyncPlayerInventorySlotsFromWindow(Container? inventory)
|
||||
{
|
||||
if (!TryGetMirroredPlayerInventorySlot(inventory, windowSlot, out int playerInventorySlot))
|
||||
if (inventory is null)
|
||||
return false;
|
||||
|
||||
inventory.Items.TryGetValue(windowSlot, out Item? item);
|
||||
return SetPlayerInventorySlot(playerInventorySlot, item);
|
||||
}
|
||||
if (!inventoriesWithFullContents.Contains(inventory.ID))
|
||||
return false;
|
||||
|
||||
private bool SyncPlayerInventorySlotsFromWindow(Container inventory)
|
||||
{
|
||||
if (!TryGetMirroredPlayerInventoryRange(inventory, out int firstWindowSlot, out int lastWindowSlot))
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
if (!inventories.TryGetValue(0, out Container? playerInventory))
|
||||
return false;
|
||||
|
||||
const int firstPlayerInventorySlot = 9;
|
||||
const int lastPlayerInventorySlot = firstPlayerInventorySlot + 36 - 1;
|
||||
Dictionary<int, Item> mirroredItems = new();
|
||||
|
||||
for (int windowSlot = firstWindowSlot; windowSlot <= lastWindowSlot; windowSlot++)
|
||||
changed |= SyncPlayerInventorySlotFromWindow(inventory, windowSlot);
|
||||
{
|
||||
if (!inventory.Items.TryGetValue(windowSlot, out Item? item) || item.IsEmpty)
|
||||
continue;
|
||||
|
||||
int playerInventorySlot = windowSlot - firstWindowSlot + firstPlayerInventorySlot;
|
||||
mirroredItems[playerInventorySlot] = item.CloneWithCount(item.Count);
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
for (int playerInventorySlot = firstPlayerInventorySlot; playerInventorySlot <= lastPlayerInventorySlot; playerInventorySlot++)
|
||||
{
|
||||
playerInventory.Items.TryGetValue(playerInventorySlot, out Item? previousItem);
|
||||
mirroredItems.TryGetValue(playerInventorySlot, out Item? mirroredItem);
|
||||
if (AreSameInventorySlot(previousItem, mirroredItem))
|
||||
continue;
|
||||
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!changed)
|
||||
return false;
|
||||
|
||||
for (int playerInventorySlot = firstPlayerInventorySlot; playerInventorySlot <= lastPlayerInventorySlot; playerInventorySlot++)
|
||||
playerInventory.Items.Remove(playerInventorySlot);
|
||||
|
||||
foreach ((int playerInventorySlot, Item item) in mirroredItems)
|
||||
playerInventory.Items[playerInventorySlot] = item;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
|
@ -2210,6 +2229,10 @@ namespace MinecraftClient
|
|||
playerInventory.Items.Remove(-1);
|
||||
}
|
||||
|
||||
// Clean up cursor item if count reached zero
|
||||
if (playerInventory.Items.TryGetValue(-1, out Item? cursorAfterLeft) && cursorAfterLeft.IsEmpty)
|
||||
playerInventory.Items.Remove(-1);
|
||||
|
||||
if (inventory.Items.ContainsKey(slotId))
|
||||
changedSlots.Add(new Tuple<short, Item?>((short)slotId, inventory.Items[slotId]));
|
||||
else
|
||||
|
|
@ -2266,6 +2289,10 @@ namespace MinecraftClient
|
|||
inventory.Items[slotId] = itemClone;
|
||||
playerInventory.Items[-1].Count--;
|
||||
}
|
||||
|
||||
// Clean up cursor item if count reached zero
|
||||
if (playerInventory.Items.TryGetValue(-1, out Item? cursorItem) && cursorItem.IsEmpty)
|
||||
playerInventory.Items.Remove(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2851,6 +2878,11 @@ namespace MinecraftClient
|
|||
changedSlots.Add(new Tuple<short, Item?>((short)slotId, inventory.Items[slotId]));
|
||||
}
|
||||
}
|
||||
if (item!.Count <= 0 && inventory.Items.ContainsKey(slotId))
|
||||
{
|
||||
inventory.Items.Remove(slotId);
|
||||
changedSlots.Add(new Tuple<short, Item?>((short)slotId, null));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WindowActionType.DropItem:
|
||||
|
|
@ -2872,10 +2904,10 @@ namespace MinecraftClient
|
|||
changedSlots.Add(new Tuple<short, Item?>((short)slotId, null));
|
||||
break;
|
||||
}
|
||||
|
||||
SyncPlayerInventorySlotsFromWindow(inventory);
|
||||
}
|
||||
|
||||
SyncPlayerInventorySlotsFromWindow(inventory);
|
||||
|
||||
return handler.SendWindowAction(windowId, slotId, action, item, changedSlots, inventories[windowId].StateID);
|
||||
}
|
||||
|
||||
|
|
@ -2926,7 +2958,10 @@ namespace MinecraftClient
|
|||
if (inventories.ContainsKey(windowId))
|
||||
{
|
||||
if (windowId != 0)
|
||||
{
|
||||
inventories.Remove(windowId);
|
||||
inventoriesWithFullContents.Remove(windowId);
|
||||
}
|
||||
bool result = handler.SendCloseWindow(windowId);
|
||||
DispatchBotEvent(bot => bot.OnInventoryClose(windowId));
|
||||
return result;
|
||||
|
|
@ -2947,6 +2982,7 @@ namespace MinecraftClient
|
|||
return InvokeOnMainThread<bool>(ClearInventories);
|
||||
|
||||
inventories.Clear();
|
||||
inventoriesWithFullContents.Clear();
|
||||
inventories[0] = new Container(0, ContainerType.PlayerInventory, "Player Inventory");
|
||||
ClearUnlockedRecipes();
|
||||
return true;
|
||||
|
|
@ -3759,6 +3795,7 @@ namespace MinecraftClient
|
|||
/// <param name="inventoryID">Inventory ID</param>
|
||||
public void OnInventoryOpen(int inventoryID, Container inventory)
|
||||
{
|
||||
inventoriesWithFullContents.Remove(inventoryID);
|
||||
inventories[inventoryID] = inventory;
|
||||
|
||||
if (inventoryID != 0)
|
||||
|
|
@ -3785,9 +3822,15 @@ namespace MinecraftClient
|
|||
if (inventories.ContainsKey(inventoryID))
|
||||
{
|
||||
if (inventoryID == 0)
|
||||
{
|
||||
inventories[0].Items.Clear(); // Don't delete player inventory
|
||||
inventoriesWithFullContents.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
inventories.Remove(inventoryID);
|
||||
inventoriesWithFullContents.Remove(inventoryID);
|
||||
}
|
||||
}
|
||||
|
||||
if (inventoryID != 0)
|
||||
|
|
@ -3913,8 +3956,13 @@ namespace MinecraftClient
|
|||
{
|
||||
if (inventories.ContainsKey(inventoryID))
|
||||
{
|
||||
// Filter out empty items (Count=0 or Air) that some servers may send
|
||||
foreach (int key in itemList.Where(slot => slot.Value.IsEmpty).Select(slot => slot.Key).ToList())
|
||||
itemList.Remove(key);
|
||||
|
||||
inventories[inventoryID].Items = itemList;
|
||||
inventories[inventoryID].StateID = stateId;
|
||||
inventoriesWithFullContents.Add(inventoryID);
|
||||
bool playerInventoryChanged = SyncPlayerInventorySlotsFromWindow(inventories[inventoryID]);
|
||||
if (playerInventoryChanged)
|
||||
DispatchBotEvent(bot => bot.OnInventoryUpdate(0));
|
||||
|
|
@ -3942,7 +3990,7 @@ namespace MinecraftClient
|
|||
inventoryID = 0; // Prevent key not found for some bots relied to this event
|
||||
if (inventories.ContainsKey(0))
|
||||
{
|
||||
if (item is not null)
|
||||
if (item is not null && !item.IsEmpty)
|
||||
inventories[0].Items[-1] = item;
|
||||
else
|
||||
inventories[0].Items.Remove(-1);
|
||||
|
|
@ -3959,7 +4007,7 @@ namespace MinecraftClient
|
|||
}
|
||||
else inventories[inventoryID].Items[slotID] = item;
|
||||
|
||||
if (SyncPlayerInventorySlotFromWindow(inventories[inventoryID], slotID))
|
||||
if (SyncPlayerInventorySlotsFromWindow(inventories[inventoryID]))
|
||||
DispatchBotEvent(bot => bot.OnInventoryUpdate(0));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4135,7 +4135,7 @@ namespace MinecraftClient {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Shift clicking slot {0} in window #{1}.
|
||||
/// Looks up a localized string similar to Shift.
|
||||
/// </summary>
|
||||
internal static string cmd_inventory_shiftclick {
|
||||
get {
|
||||
|
|
@ -4153,7 +4153,7 @@ namespace MinecraftClient {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Shift right-clicking slot {0} in window #{1}.
|
||||
/// Looks up a localized string similar to Shift right.
|
||||
/// </summary>
|
||||
internal static string cmd_inventory_shiftrightclick {
|
||||
get {
|
||||
|
|
|
|||
|
|
@ -1457,7 +1457,7 @@ Note that parameters in '[]' are optional.</value>
|
|||
<value>Right</value>
|
||||
</data>
|
||||
<data name="cmd.inventory.shiftclick" xml:space="preserve">
|
||||
<value>Shift clicking slot {0} in window #{1}</value>
|
||||
<value>Shift</value>
|
||||
</data>
|
||||
<data name="cmd.inventory.shiftclick_fail" xml:space="preserve">
|
||||
<value>Shift click failed, this may be because this container type is not supported</value>
|
||||
|
|
@ -2329,7 +2329,7 @@ Logging in...</value>
|
|||
<value>Minimum number that you have provided is bigger than the maximum, swapping them around!</value>
|
||||
</data>
|
||||
<data name="cmd.inventory.shiftrightclick" xml:space="preserve">
|
||||
<value>Shift right-clicking slot {0} in window #{1}</value>
|
||||
<value>Shift right</value>
|
||||
</data>
|
||||
<data name="mcc.avaliable_profiles" xml:space="preserve">
|
||||
<value>Avaliable profiles:</value>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue