Inventory handling improvements

Fix click issue for item with NBT
Show custom display names in inventory
See issues #910 #912 #914
This commit is contained in:
ORelio 2020-04-01 22:05:44 +02:00
parent b01c50b792
commit dbe02c063c
4 changed files with 51 additions and 9 deletions

View file

@ -37,7 +37,12 @@ namespace MinecraftClient.Commands
List<string> response = new List<string>(); List<string> response = new List<string>();
response.Add("Inventory #" + inventoryId + " - " + inventory.Title + "§8"); response.Add("Inventory #" + inventoryId + " - " + inventory.Title + "§8");
foreach (KeyValuePair<int, Item> item in inventory.Items) foreach (KeyValuePair<int, Item> item in inventory.Items)
response.Add(String.Format(" #{0}: {1} x{2}", item.Key, item.Value.Type, item.Value.Count)); {
string displayName = item.Value.DisplayName;
if (String.IsNullOrEmpty(displayName))
response.Add(String.Format(" #{0}: {1} x{2}", item.Key, item.Value.Type, item.Value.Count));
else response.Add(String.Format(" #{0}: {1} x{2} - {3}§8", item.Key, item.Value.Type, item.Value.Count, displayName));
}
return String.Join("\n", response.ToArray()); return String.Join("\n", response.ToArray());
case "click": case "click":
if (args.Length == 3) if (args.Length == 3)

View file

@ -49,5 +49,26 @@ namespace MinecraftClient.Inventory
return Type == ItemType.Air || Count == 0; return Type == ItemType.Air || Count == 0;
} }
} }
/// <summary>
/// Retrieve item display name from NBT properties. NULL if no display name is defined.
/// </summary>
public string DisplayName
{
get
{
if (NBT != null && NBT.ContainsKey("display"))
{
var displayProperties = NBT["display"] as Dictionary<string, object>;
if (displayProperties != null && displayProperties.ContainsKey("Name"))
{
string displayName = displayProperties["Name"] as string;
if (!String.IsNullOrEmpty(displayName))
return MinecraftClient.Protocol.ChatParser.ParseText(displayProperties["Name"].ToString());
}
}
return null;
}
}
} }
} }

View file

@ -368,7 +368,11 @@ namespace MinecraftClient.Protocol.Handlers
if (cache[0] != 10) // TAG_Compound if (cache[0] != 10) // TAG_Compound
throw new System.IO.InvalidDataException("Failed to decode NBT: Does not start with TAG_Compound"); throw new System.IO.InvalidDataException("Failed to decode NBT: Does not start with TAG_Compound");
ReadNextByte(cache); // Tag type (TAG_Compound) ReadNextByte(cache); // Tag type (TAG_Compound)
ReadData(ReadNextUShort(cache), cache); // NBT root name
// NBT root name
string rootName = Encoding.ASCII.GetString(ReadData(ReadNextUShort(cache), cache));
if (!String.IsNullOrEmpty(rootName))
NbtData[""] = rootName;
} }
while (true) while (true)
@ -456,6 +460,15 @@ namespace MinecraftClient.Protocol.Handlers
if (root) if (root)
{ {
bytes.Add(10); // TAG_Compound bytes.Add(10); // TAG_Compound
// NBT root name
string rootName = null;
if (nbt.ContainsKey(""))
rootName = nbt[""] as string;
if (rootName == null)
rootName = "";
bytes.AddRange(GetUShort((ushort)rootName.Length));
bytes.AddRange(Encoding.ASCII.GetBytes(rootName));
} }
foreach (var item in nbt) foreach (var item in nbt)
@ -464,9 +477,9 @@ namespace MinecraftClient.Protocol.Handlers
byte[] fieldNameLength = GetUShort((ushort)item.Key.Length); byte[] fieldNameLength = GetUShort((ushort)item.Key.Length);
byte[] fieldName = Encoding.ASCII.GetBytes(item.Key); byte[] fieldName = Encoding.ASCII.GetBytes(item.Key);
byte[] fieldData = GetNbtField(item.Value, out fieldType); byte[] fieldData = GetNbtField(item.Value, out fieldType);
bytes.Add(fieldType);
bytes.AddRange(fieldNameLength); bytes.AddRange(fieldNameLength);
bytes.AddRange(fieldName); bytes.AddRange(fieldName);
bytes.Add(fieldType);
bytes.AddRange(fieldData); bytes.AddRange(fieldData);
} }

View file

@ -507,7 +507,6 @@ namespace MinecraftClient.Protocol.Handlers
string title = dataTypes.ReadNextString(packetData); string title = dataTypes.ReadNextString(packetData);
byte slots = dataTypes.ReadNextByte(packetData); byte slots = dataTypes.ReadNextByte(packetData);
Container inventory = new Container(windowID, inventoryType, ChatParser.ParseText(title)); Container inventory = new Container(windowID, inventoryType, ChatParser.ParseText(title));
window_actions[windowID] = 0;
handler.OnInventoryOpen(windowID, inventory); handler.OnInventoryOpen(windowID, inventory);
} }
else else
@ -517,7 +516,6 @@ namespace MinecraftClient.Protocol.Handlers
int windowType = dataTypes.ReadNextVarInt(packetData); int windowType = dataTypes.ReadNextVarInt(packetData);
string title = dataTypes.ReadNextString(packetData); string title = dataTypes.ReadNextString(packetData);
Container inventory = new Container(windowID, windowType, ChatParser.ParseText(title)); Container inventory = new Container(windowID, windowType, ChatParser.ParseText(title));
window_actions[windowID] = 0;
handler.OnInventoryOpen(windowID, inventory); handler.OnInventoryOpen(windowID, inventory);
} }
} }
@ -526,7 +524,7 @@ namespace MinecraftClient.Protocol.Handlers
if (handler.GetInventoryEnabled()) if (handler.GetInventoryEnabled())
{ {
byte windowID = dataTypes.ReadNextByte(packetData); byte windowID = dataTypes.ReadNextByte(packetData);
window_actions[windowID] = 0; lock (window_actions) { window_actions[windowID] = 0; }
handler.OnInventoryClose(windowID); handler.OnInventoryClose(windowID);
} }
break; break;
@ -542,7 +540,6 @@ namespace MinecraftClient.Protocol.Handlers
if (item != null) if (item != null)
inventorySlots[slotId] = item; inventorySlots[slotId] = item;
} }
window_actions[windowId] = 0;
handler.OnWindowItems(windowId, inventorySlots); handler.OnWindowItems(windowId, inventorySlots);
} }
break; break;
@ -1317,8 +1314,14 @@ namespace MinecraftClient.Protocol.Handlers
{ {
try try
{ {
short actionNumber = (short)(window_actions[windowId] + 1); short actionNumber;
window_actions[windowId] = actionNumber; lock (window_actions)
{
if (!window_actions.ContainsKey(windowId))
window_actions[windowId] = 0;
actionNumber = (short)(window_actions[windowId] + 1);
window_actions[windowId] = actionNumber;
}
List<byte> packet = new List<byte>(); List<byte> packet = new List<byte>();
packet.Add((byte)windowId); packet.Add((byte)windowId);