Adds support for villager trading (#1316)

* adds villager trading support
Adds handler for tradeList packet and selectTrade packet
* added extra line at end
* removed tab; removed size and hasSecondItem
removed a mistakenly added tab instead of 4 spaces. SelectTrade was already added in 1.13. Removed unnecessary size and hasSecondItem from trade dataType.
* Added VillagerInfo class and capitalized vars in Trade class
* Update VillagerInfo.cs
* Small formatting/naming adjustments
Co-authored-by: ORelio <ORelio@users.noreply.github.com>
This commit is contained in:
mexiscool 2020-11-08 23:39:07 +01:00 committed by GitHub
parent 2a7f0c7f16
commit 28f47cc532
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 186 additions and 1 deletions

View file

@ -610,6 +610,29 @@ namespace MinecraftClient.Protocol.Handlers
return data;
}
/// <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);
}
/// <summary>
/// Build an uncompressed Named Binary Tag blob for sending over the network
/// </summary>

View file

@ -845,5 +845,10 @@ namespace MinecraftClient.Protocol.Handlers
}
catch { return false; }
}
public bool SelectTrade(int selectedSlot)
{
return false; //MC 1.13+
}
}
}

View file

@ -432,6 +432,28 @@ namespace MinecraftClient.Protocol.Handlers
int iconcount = dataTypes.ReadNextVarInt(packetData);
handler.OnMapData(mapid, scale, trackingposition, locked, iconcount);
break;
case PacketTypesIn.TradeList:
if ((protocolversion >= MC114Version) && (handler.GetInventoryEnabled()))
{
// MC 1.14 or greater
int windowID = dataTypes.ReadNextVarInt(packetData);
int size = dataTypes.ReadNextByte(packetData);
List<VillagerTrade> trades = new List<VillagerTrade>();
for (int tradeId = 0; tradeId < size; tradeId++)
{
VillagerTrade trade = dataTypes.ReadNextTrade(packetData, itemPalette);
trades.Add(trade);
}
VillagerInfo villagerInfo = new VillagerInfo()
{
Level = dataTypes.ReadNextVarInt(packetData),
Experience = dataTypes.ReadNextVarInt(packetData),
IsRegularVillager = dataTypes.ReadNextBool(packetData),
CanRestock = dataTypes.ReadNextBool(packetData)
};
handler.OnTradeList(windowID, trades, villagerInfo);
}
break;
case PacketTypesIn.Title:
if (protocolversion >= MC18Version)
{
@ -1889,5 +1911,24 @@ namespace MinecraftClient.Protocol.Handlers
catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; }
}
public bool SelectTrade(int selectedSlot)
{
// MC 1.13 or greater
if (protocolversion >= MC113Version)
{
try
{
List<byte> packet = new List<byte>();
packet.AddRange(dataTypes.GetVarInt(selectedSlot));
SendPacket(PacketTypesOut.SelectTrade, packet);
return true;
}
catch (SocketException) { return false; }
catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; }
}
else { return false; }
}
}
}

View file

@ -229,5 +229,11 @@ namespace MinecraftClient.Protocol
/// <param name="mode">command block mode</param>
/// <param name="flags">command block flags</param>
bool UpdateCommandBlock(Location location, string command, CommandBlockMode mode, CommandBlockFlags flags);
/// <summary>
/// Select villager trade
/// </summary>
/// <param name="selectedSlot">The slot of the trade, starts at 0.</param>
bool SelectTrade(int selectedSlot);
}
}

View file

@ -330,5 +330,16 @@ namespace MinecraftClient.Protocol
/// <param name="objectivename">The name of the objective the score belongs to</param>
/// <param name="value">he score to be displayed next to the entry. Only sent when Action does not equal 1.</param>
void OnUpdateScore(string entityname, byte action, string objectivename, int value);
/// <summary>
/// Called when tradeList is received from server
/// </summary>
/// <param name="windowID">Window ID</param>
/// <param name="trades">List of trades.</param>
/// <param name="villagerLevel">The level the villager is.</param>
/// <param name="experience">The amount of experience the villager has.</param>
/// <param name="isRegularVillager">True if regular villagers and false if the wandering trader.</param>
/// <param name="canRestock">If the villager can restock his trades at a workstation, True for regular villagers and false for the wandering trader.</param>
void OnTradeList(int windowID, List<VillagerTrade> trades, VillagerInfo villagerInfo);
}
}