/// <summary> /// Read a single item slot from a cache of bytes and remove it from the cache /// </summary> /// <returns>The item that was read or NULL for an empty slot</returns> public Item ReadNextItemSlot(Queue <byte> cache, ItemPalette itemPalette) { List <byte> slotData = new List <byte>(); if (protocolversion > Protocol18Handler.MC113Version) { // MC 1.13 and greater bool itemPresent = ReadNextBool(cache); if (itemPresent) { ItemType type = itemPalette.FromId(ReadNextVarInt(cache)); byte itemCount = ReadNextByte(cache); Dictionary <string, object> nbt = ReadNextNbt(cache); return(new Item(type, itemCount, nbt)); } else { return(null); } } else { // MC 1.12.2 and lower short itemID = ReadNextShort(cache); if (itemID == -1) { return(null); } byte itemCount = ReadNextByte(cache); short itemDamage = ReadNextShort(cache); Dictionary <string, object> nbt = ReadNextNbt(cache); return(new Item(itemPalette.FromId(itemID), itemCount, nbt)); } }
/// <summary> /// Get a byte array representing the given item as an item slot /// </summary> /// <param name="item">Item</param> /// <param name="itemPalette">Item Palette</param> /// <returns>Item slot representation</returns> public byte[] GetItemSlot(Item item, ItemPalette itemPalette) { List <byte> slotData = new List <byte>(); if (protocolversion > Protocol18Handler.MC113Version) { // MC 1.13 and greater if (item == null || item.IsEmpty) { slotData.Add(0); // No item } else { slotData.Add(1); // Item is present slotData.AddRange(GetVarInt(itemPalette.ToId(item.Type))); slotData.Add((byte)item.Count); slotData.AddRange(GetNbt(item.NBT)); } } else { // MC 1.12.2 and lower if (item == null || item.IsEmpty) { slotData.AddRange(GetShort(-1)); } else { slotData.AddRange(GetShort((short)itemPalette.ToId(item.Type))); slotData.Add((byte)item.Count); slotData.AddRange(GetNbt(item.NBT)); } } return(slotData.ToArray()); }
/// <summary> /// Read a single villager trade from a cache of bytes and remove it from the cache /// </summary> /// <returns>The item that was read or NULL for an empty slot</returns> public VillagerTrade ReadNextTrade(Queue <byte> cache, ItemPalette itemPalette) { Item inputItem1 = ReadNextItemSlot(cache, itemPalette); Item outputItem = ReadNextItemSlot(cache, itemPalette); Item inputItem2 = null; if (ReadNextBool(cache)) //check if villager has second item { inputItem2 = ReadNextItemSlot(cache, itemPalette); } bool tradeDisabled = ReadNextBool(cache); int numberOfTradeUses = ReadNextInt(cache); int maximumNumberOfTradeUses = ReadNextInt(cache); int xp = ReadNextInt(cache); int specialPrice = ReadNextInt(cache); float priceMultiplier = ReadNextFloat(cache); int demand = ReadNextInt(cache); return(new VillagerTrade(inputItem1, outputItem, inputItem2, tradeDisabled, numberOfTradeUses, maximumNumberOfTradeUses, xp, specialPrice, priceMultiplier, demand)); }
public Dictionary <int, object> ReadNextMetadata(Queue <byte> cache, ItemPalette itemPalette) { Dictionary <int, object> data = new Dictionary <int, object>(); byte key = ReadNextByte(cache); while (key != 0xff) { int type = ReadNextVarInt(cache); // starting from 1.13, Optional Chat is inserted as number 5 in 1.13 and IDs after 5 got shifted. // Increase type ID by 1 if // - below 1.13 // - type ID larger than 4 if (protocolversion < Protocol18Handler.MC113Version) { if (type > 4) { type += 1; } } // Value's data type is depended on Type object value = null; // This is backward compatible since new type is appended to the end // Version upgrade note // - Check type ID got shifted or not // - Add new type if any switch (type) { case 0: // byte value = ReadNextByte(cache); break; case 1: // VarInt value = ReadNextVarInt(cache); break; case 2: // Float value = ReadNextFloat(cache); break; case 3: // String value = ReadNextString(cache); break; case 4: // Chat value = ReadNextString(cache); break; case 5: // Optional Chat if (ReadNextBool(cache)) { value = ReadNextString(cache); } break; case 6: // Slot value = ReadNextItemSlot(cache, itemPalette); break; case 7: // Boolean value = ReadNextBool(cache); break; case 8: // Rotation (3x floats) List <float> t = new List <float>(); t.Add(ReadNextFloat(cache)); t.Add(ReadNextFloat(cache)); t.Add(ReadNextFloat(cache)); value = t; break; case 9: // Position value = ReadNextLocation(cache); break; case 10: // Optional Position if (ReadNextBool(cache)) { value = ReadNextLocation(cache); } break; case 11: // Direction (VarInt) value = ReadNextVarInt(cache); break; case 12: // Optional UUID if (ReadNextBool(cache)) { value = ReadNextUUID(cache); } break; case 13: // Optional BlockID (VarInt) value = ReadNextVarInt(cache); break; case 14: // NBT value = ReadNextNbt(cache); break; case 15: // Particle // Currecutly not handled. Reading data only int ParticleID = ReadNextVarInt(cache); switch (ParticleID) { case 3: ReadNextVarInt(cache); break; case 14: ReadNextFloat(cache); ReadNextFloat(cache); ReadNextFloat(cache); ReadNextFloat(cache); break; case 23: ReadNextVarInt(cache); break; case 32: ReadNextItemSlot(cache, itemPalette); break; } break; case 16: // Villager Data (3x VarInt) List <int> d = new List <int>(); d.Add(ReadNextVarInt(cache)); d.Add(ReadNextVarInt(cache)); d.Add(ReadNextVarInt(cache)); value = d; break; case 17: // Optional VarInt if (ReadNextBool(cache)) { value = ReadNextVarInt(cache); } break; case 18: // Pose value = ReadNextVarInt(cache); break; default: throw new System.IO.InvalidDataException("Unknown Metadata Type ID " + type + ". Is this up to date for new MC Version?"); } data[key] = value; key = ReadNextByte(cache); } return(data); }