mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Fix inventory handling across protocol versions
This commit is contained in:
parent
03e2e0d3fd
commit
5228670131
9 changed files with 364 additions and 89 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using Brigadier.NET;
|
using Brigadier.NET;
|
||||||
using Brigadier.NET.Builder;
|
using Brigadier.NET.Builder;
|
||||||
using MinecraftClient.CommandHandler;
|
using MinecraftClient.CommandHandler;
|
||||||
|
|
@ -53,8 +54,27 @@ namespace MinecraftClient.Commands
|
||||||
Location current = handler.GetCurrentLocation();
|
Location current = handler.GetCurrentLocation();
|
||||||
block = block.ToAbsolute(current).ToFloor();
|
block = block.ToAbsolute(current).ToFloor();
|
||||||
Location blockCenter = block.ToCenter();
|
Location blockCenter = block.ToCenter();
|
||||||
bool res = handler.PlaceBlock(block, Direction.Down, hand, lookAtBlock: true);
|
bool res = handler.PlaceBlock(block, GetFaceNearestPlayer(current, blockCenter), hand, lookAtBlock: true);
|
||||||
return r.SetAndReturn(string.Format(Translations.cmd_useblock_use, blockCenter.X, blockCenter.Y, blockCenter.Z, res ? "succeeded" : "failed"), res);
|
return r.SetAndReturn(string.Format(Translations.cmd_useblock_use, blockCenter.X, blockCenter.Y, blockCenter.Z, res ? "succeeded" : "failed"), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Direction GetFaceNearestPlayer(Location playerLocation, Location blockCenter)
|
||||||
|
{
|
||||||
|
double dx = playerLocation.X - blockCenter.X;
|
||||||
|
double dy = playerLocation.Y - blockCenter.Y;
|
||||||
|
double dz = playerLocation.Z - blockCenter.Z;
|
||||||
|
|
||||||
|
double absX = Math.Abs(dx);
|
||||||
|
double absY = Math.Abs(dy);
|
||||||
|
double absZ = Math.Abs(dz);
|
||||||
|
|
||||||
|
if (absX >= absY && absX >= absZ)
|
||||||
|
return dx >= 0 ? Direction.East : Direction.West;
|
||||||
|
|
||||||
|
if (absY >= absZ)
|
||||||
|
return dy >= 0 ? Direction.Up : Direction.Down;
|
||||||
|
|
||||||
|
return dz >= 0 ? Direction.South : Direction.North;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,16 @@ namespace MinecraftClient.Mapping
|
||||||
/// <param name="registryCodec">Registry Codec nbt data</param>
|
/// <param name="registryCodec">Registry Codec nbt data</param>
|
||||||
public static void StoreDimensionList(Dictionary<string, object> registryCodec)
|
public static void StoreDimensionList(Dictionary<string, object> registryCodec)
|
||||||
{
|
{
|
||||||
var dimensionListNbt = (object[])(((Dictionary<string, object>)registryCodec["minecraft:dimension_type"])["value"]);
|
const string namespacedDimensionTypeKey = "minecraft:dimension_type";
|
||||||
|
const string legacyDimensionTypeKey = "dimension_type";
|
||||||
|
|
||||||
|
if (!registryCodec.TryGetValue(namespacedDimensionTypeKey, out var dimensionTypeRegistry)
|
||||||
|
&& !registryCodec.TryGetValue(legacyDimensionTypeKey, out dimensionTypeRegistry))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dimensionListNbt = (object[])(((Dictionary<string, object>)dimensionTypeRegistry)["value"]);
|
||||||
foreach (var (dimensionName, dimensionType) in from Dictionary<string, object> dimensionNbt in dimensionListNbt
|
foreach (var (dimensionName, dimensionType) in from Dictionary<string, object> dimensionNbt in dimensionListNbt
|
||||||
let dimensionName = (string)dimensionNbt["name"]
|
let dimensionName = (string)dimensionNbt["name"]
|
||||||
let dimensionType = (Dictionary<string, object>)dimensionNbt["element"]
|
let dimensionType = (Dictionary<string, object>)dimensionNbt["element"]
|
||||||
|
|
@ -324,19 +333,48 @@ namespace MinecraftClient.Mapping
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not found, check if name lacks 'minecraft:' prefix and try again
|
// If not found, check if name lacks 'minecraft:' prefix and try again
|
||||||
if (!name.StartsWith("minecraft:"))
|
if (!name.StartsWith("minecraft:"))
|
||||||
{
|
{
|
||||||
string prefixedName = "minecraft:" + name;
|
string prefixedName = "minecraft:" + name;
|
||||||
if (dimensionList.TryGetValue(prefixedName, out dimension))
|
if (dimensionList.TryGetValue(prefixedName, out dimension))
|
||||||
{
|
{
|
||||||
curDimension = dimension;
|
curDimension = dimension;
|
||||||
return; // Dimension found with prefixed name
|
return; // Dimension found with prefixed name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string unprefixedName = name["minecraft:".Length..];
|
||||||
|
if (dimensionList.TryGetValue(unprefixedName, out dimension))
|
||||||
|
{
|
||||||
|
curDimension = dimension;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If still not found, dimension does not exist
|
if (TryStoreDefaultVanillaDimension(name)
|
||||||
throw new KeyNotFoundException($"Dimension '{name}' not found in dimensions dictionary.");
|
&& dimensionList.TryGetValue(name, out dimension))
|
||||||
}
|
{
|
||||||
|
curDimension = dimension;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If still not found, dimension does not exist
|
||||||
|
throw new KeyNotFoundException($"Dimension '{name}' not found in dimensions dictionary.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryStoreDefaultVanillaDimension(string name)
|
||||||
|
{
|
||||||
|
var normalizedName = name.StartsWith("minecraft:")
|
||||||
|
? name
|
||||||
|
: "minecraft:" + name;
|
||||||
|
|
||||||
|
if (normalizedName is not ("minecraft:overworld" or "minecraft:the_nether" or "minecraft:the_end"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
StoreOneDimension(name, new Dictionary<string, object>());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2022,6 +2022,90 @@ namespace MinecraftClient
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool TryGetMirroredPlayerInventoryRange(Container inventory, out int firstWindowSlot, out int lastWindowSlot)
|
||||||
|
{
|
||||||
|
firstWindowSlot = -1;
|
||||||
|
lastWindowSlot = -1;
|
||||||
|
|
||||||
|
if (inventory.Type == ContainerType.PlayerInventory)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const int mirroredPlayerInventorySlotCount = 36;
|
||||||
|
int slotCount = inventory.Type.SlotCount();
|
||||||
|
if (slotCount < mirroredPlayerInventorySlotCount)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
firstWindowSlot = slotCount - mirroredPlayerInventorySlotCount;
|
||||||
|
lastWindowSlot = slotCount - 1;
|
||||||
|
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)
|
||||||
|
return right is null || right.IsEmpty;
|
||||||
|
if (right is null || right.IsEmpty)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return left.Type == right.Type
|
||||||
|
&& left.Count == right.Count
|
||||||
|
&& left.Data == right.Data
|
||||||
|
&& ReferenceEquals(left.NBT, right.NBT)
|
||||||
|
&& ReferenceEquals(left.Components, right.Components);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SetPlayerInventorySlot(int playerInventorySlot, Item? item)
|
||||||
|
{
|
||||||
|
if (!inventories.TryGetValue(0, out Container? playerInventory))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
playerInventory.Items.TryGetValue(playerInventorySlot, out Item? previousItem);
|
||||||
|
if (AreSameInventorySlot(previousItem, item))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (item is null || item.IsEmpty)
|
||||||
|
playerInventory.Items.Remove(playerInventorySlot);
|
||||||
|
else
|
||||||
|
playerInventory.Items[playerInventorySlot] = item;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SyncPlayerInventorySlotFromWindow(Container inventory, int windowSlot)
|
||||||
|
{
|
||||||
|
if (!TryGetMirroredPlayerInventorySlot(inventory, windowSlot, out int playerInventorySlot))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
inventory.Items.TryGetValue(windowSlot, out Item? item);
|
||||||
|
return SetPlayerInventorySlot(playerInventorySlot, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SyncPlayerInventorySlotsFromWindow(Container inventory)
|
||||||
|
{
|
||||||
|
if (!TryGetMirroredPlayerInventoryRange(inventory, out int firstWindowSlot, out int lastWindowSlot))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
for (int windowSlot = firstWindowSlot; windowSlot <= lastWindowSlot; windowSlot++)
|
||||||
|
changed |= SyncPlayerInventorySlotFromWindow(inventory, windowSlot);
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Click a slot in the specified window
|
/// Click a slot in the specified window
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -2748,6 +2832,8 @@ namespace MinecraftClient
|
||||||
changedSlots.Add(new Tuple<short, Item?>((short)slotId, null));
|
changedSlots.Add(new Tuple<short, Item?>((short)slotId, null));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyncPlayerInventorySlotsFromWindow(inventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
return handler.SendWindowAction(windowId, slotId, action, item, changedSlots, inventories[windowId].StateID);
|
return handler.SendWindowAction(windowId, slotId, action, item, changedSlots, inventories[windowId].StateID);
|
||||||
|
|
@ -2764,7 +2850,16 @@ namespace MinecraftClient
|
||||||
/// <returns>TRUE if item given successfully</returns>
|
/// <returns>TRUE if item given successfully</returns>
|
||||||
public bool DoCreativeGive(int slot, ItemType itemType, int count, Dictionary<string, object>? nbt = null)
|
public bool DoCreativeGive(int slot, ItemType itemType, int count, Dictionary<string, object>? nbt = null)
|
||||||
{
|
{
|
||||||
return InvokeOnMainThread(() => handler.SendCreativeInventoryAction(slot, itemType, count, nbt));
|
return InvokeOnMainThread(() =>
|
||||||
|
{
|
||||||
|
if (!handler.SendCreativeInventoryAction(slot, itemType, count, nbt))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (slot is >= 1 and <= 45)
|
||||||
|
SetPlayerInventorySlot(slot, new Item(itemType, count, nbt));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -3780,6 +3875,9 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
inventories[inventoryID].Items = itemList;
|
inventories[inventoryID].Items = itemList;
|
||||||
inventories[inventoryID].StateID = stateId;
|
inventories[inventoryID].StateID = stateId;
|
||||||
|
bool playerInventoryChanged = SyncPlayerInventorySlotsFromWindow(inventories[inventoryID]);
|
||||||
|
if (playerInventoryChanged)
|
||||||
|
DispatchBotEvent(bot => bot.OnInventoryUpdate(0));
|
||||||
DispatchBotEvent(bot => bot.OnInventoryUpdate(inventoryID));
|
DispatchBotEvent(bot => bot.OnInventoryUpdate(inventoryID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3820,6 +3918,9 @@ namespace MinecraftClient
|
||||||
inventories[inventoryID].Items.Remove(slotID);
|
inventories[inventoryID].Items.Remove(slotID);
|
||||||
}
|
}
|
||||||
else inventories[inventoryID].Items[slotID] = item;
|
else inventories[inventoryID].Items[slotID] = item;
|
||||||
|
|
||||||
|
if (SyncPlayerInventorySlotFromWindow(inventories[inventoryID], slotID))
|
||||||
|
DispatchBotEvent(bot => bot.OnInventoryUpdate(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DispatchBotEvent(bot => bot.OnInventoryUpdate(inventoryID));
|
DispatchBotEvent(bot => bot.OnInventoryUpdate(inventoryID));
|
||||||
|
|
@ -4676,6 +4777,9 @@ namespace MinecraftClient
|
||||||
{
|
{
|
||||||
switch (reason)
|
switch (reason)
|
||||||
{
|
{
|
||||||
|
case 3:
|
||||||
|
OnGamemodeUpdate(Guid.Empty, (int)value);
|
||||||
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
DispatchBotEvent(bot => bot.OnRainLevelChange(value));
|
DispatchBotEvent(bot => bot.OnRainLevelChange(value));
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -59,32 +59,7 @@
|
||||||
<PackageReference Include="Telegram.Bot" Version="22.9.5.3" />
|
<PackageReference Include="Telegram.Bot" Version="22.9.5.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="config\ChatBots\AutoLeaveOnLowHp.cs" />
|
<Compile Remove="config\**\*.cs" />
|
||||||
<Compile Remove="config\ChatBots\AutoLook.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\AutoTree.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\CobblestoneMiner.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\DiscordWebhook.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\EntityCount.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\OreMiner.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\PayKassa.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\QIWIAPI.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\SugarCaneMiner.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\TreeFarmer.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\VkMessager.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\WebSocketBot.cs" />
|
|
||||||
<Compile Remove="config\sample-script-extended.cs" />
|
|
||||||
<Compile Remove="config\sample-script-packet-capture.cs" />
|
|
||||||
<Compile Remove="config\sample-script-pm-forwarder.cs" />
|
|
||||||
<Compile Remove="config\sample-script-random-command.cs" />
|
|
||||||
<Compile Remove="config\sample-script-tick-counter.cs" />
|
|
||||||
<Compile Remove="config\sample-script-with-chatbot.cs" />
|
|
||||||
<Compile Remove="config\sample-script-with-http-request.cs" />
|
|
||||||
<Compile Remove="config\sample-script-with-task.cs" />
|
|
||||||
<Compile Remove="config\sample-script-with-world-access.cs" />
|
|
||||||
<Compile Remove="config\sample-script-packet-capture.cs" />
|
|
||||||
<Compile Remove="config\sample-script.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\MineCube.cs" />
|
|
||||||
<Compile Remove="config\ChatBots\SugarCaneFarmer.cs" />
|
|
||||||
<Compile Remove="Mapping\VillagerInfo.cs" />
|
<Compile Remove="Mapping\VillagerInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -118,9 +118,9 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes
|
||||||
{ 0x00, PacketTypesOut.TeleportConfirm }, // (Wiki name: Confirm Teleportation)
|
{ 0x00, PacketTypesOut.TeleportConfirm }, // (Wiki name: Confirm Teleportation)
|
||||||
{ 0x01, PacketTypesOut.QueryBlockNBT }, // (Wiki name: Query Block Entity Tag)
|
{ 0x01, PacketTypesOut.QueryBlockNBT }, // (Wiki name: Query Block Entity Tag)
|
||||||
{ 0x02, PacketTypesOut.SetDifficulty }, // (Wiki name: Change Difficutly)
|
{ 0x02, PacketTypesOut.SetDifficulty }, // (Wiki name: Change Difficutly)
|
||||||
{ 0x03, PacketTypesOut.MessageAcknowledgment }, //
|
{ 0x03, PacketTypesOut.ChatCommand }, // Added in 1.19
|
||||||
{ 0x04, PacketTypesOut.ChatCommand }, // Added in 1.19
|
{ 0x04, PacketTypesOut.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Chat)
|
||||||
{ 0x05, PacketTypesOut.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Chat)
|
{ 0x05, PacketTypesOut.ChatPreview }, // Added in 1.19 (Wiki name: Chat Preview (serverbound))
|
||||||
{ 0x06, PacketTypesOut.ClientStatus }, // (Wiki name: Client Command)
|
{ 0x06, PacketTypesOut.ClientStatus }, // (Wiki name: Client Command)
|
||||||
{ 0x07, PacketTypesOut.ClientSettings }, // (Wiki name: Client Information)
|
{ 0x07, PacketTypesOut.ClientSettings }, // (Wiki name: Client Information)
|
||||||
{ 0x08, PacketTypesOut.TabComplete }, // (Wiki name: Command Suggestions Request)
|
{ 0x08, PacketTypesOut.TabComplete }, // (Wiki name: Command Suggestions Request)
|
||||||
|
|
@ -147,25 +147,24 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes
|
||||||
{ 0x1D, PacketTypesOut.EntityAction }, // (Wiki name: Player Command)
|
{ 0x1D, PacketTypesOut.EntityAction }, // (Wiki name: Player Command)
|
||||||
{ 0x1E, PacketTypesOut.SteerVehicle }, // (Wiki name: Player Input)
|
{ 0x1E, PacketTypesOut.SteerVehicle }, // (Wiki name: Player Input)
|
||||||
{ 0x1F, PacketTypesOut.Pong }, // (Wiki name: Pong (play))
|
{ 0x1F, PacketTypesOut.Pong }, // (Wiki name: Pong (play))
|
||||||
{ 0x20, PacketTypesOut.PlayerSession }, // Added in 1.19.3
|
{ 0x20, PacketTypesOut.SetDisplayedRecipe }, // (Wiki name: Recipe Book Change Settings)
|
||||||
{ 0x21, PacketTypesOut.SetDisplayedRecipe }, // (Wiki name: Recipe Book Change Settings)
|
{ 0x21, PacketTypesOut.SetRecipeBookState }, // (Wiki name: Recipe Book Seen Recipe)
|
||||||
{ 0x22, PacketTypesOut.SetRecipeBookState }, // (Wiki name: Recipe Book Seen Recipe)
|
{ 0x22, PacketTypesOut.NameItem }, // (Wiki name: Rename Item)
|
||||||
{ 0x23, PacketTypesOut.NameItem }, // (Wiki name: Rename Item)
|
{ 0x23, PacketTypesOut.ResourcePackStatus }, // (Wiki name: Resource Pack (serverbound))
|
||||||
{ 0x24, PacketTypesOut.ResourcePackStatus }, // (Wiki name: Resource Pack (serverbound))
|
{ 0x24, PacketTypesOut.AdvancementTab }, // (Wiki name: Seen Advancements)
|
||||||
{ 0x25, PacketTypesOut.AdvancementTab }, // (Wiki name: Seen Advancements)
|
{ 0x25, PacketTypesOut.SelectTrade }, //
|
||||||
{ 0x26, PacketTypesOut.SelectTrade }, //
|
{ 0x26, PacketTypesOut.SetBeaconEffect }, // Changed in 1.19 (Added a "Secondary Effect Present" and "Secondary Effect" fields) (Wiki name: Set Beacon) - (No need to be implemented)
|
||||||
{ 0x27, PacketTypesOut.SetBeaconEffect }, // Changed in 1.19 (Added a "Secondary Effect Present" and "Secondary Effect" fields) (Wiki name: Set Beacon) - (No need to be implemented)
|
{ 0x27, PacketTypesOut.HeldItemChange }, // (Wiki name: Set Carried Item (serverbound))
|
||||||
{ 0x28, PacketTypesOut.HeldItemChange }, // (Wiki name: Set Carried Item (serverbound))
|
{ 0x28, PacketTypesOut.UpdateCommandBlock }, // (Wiki name: Set Command Block)
|
||||||
{ 0x29, PacketTypesOut.UpdateCommandBlock }, // (Wiki name: Set Command Block)
|
{ 0x29, PacketTypesOut.UpdateCommandBlockMinecart }, //
|
||||||
{ 0x2A, PacketTypesOut.UpdateCommandBlockMinecart }, //
|
{ 0x2A, PacketTypesOut.CreativeInventoryAction }, // (Wiki name: Set Creative Mode Slot)
|
||||||
{ 0x2B, PacketTypesOut.CreativeInventoryAction }, // (Wiki name: Set Creative Mode Slot)
|
{ 0x2B, PacketTypesOut.UpdateJigsawBlock }, // (Wiki name: Set Jigsaw Block)
|
||||||
{ 0x2C, PacketTypesOut.UpdateJigsawBlock }, // (Wiki name: Set Jigsaw Block)
|
{ 0x2C, PacketTypesOut.UpdateStructureBlock }, // (Wiki name: Set Structure Block)
|
||||||
{ 0x2D, PacketTypesOut.UpdateStructureBlock }, // (Wiki name: Set Structure Block)
|
{ 0x2D, PacketTypesOut.UpdateSign }, // (Wiki name: Sign Update)
|
||||||
{ 0x2E, PacketTypesOut.UpdateSign }, // (Wiki name: Sign Update)
|
{ 0x2E, PacketTypesOut.Animation }, // (Wiki name: Swing)
|
||||||
{ 0x2F, PacketTypesOut.Animation }, // (Wiki name: Swing)
|
{ 0x2F, PacketTypesOut.Spectate }, // (Wiki name: Teleport To Entity)
|
||||||
{ 0x30, PacketTypesOut.Spectate }, // (Wiki name: Teleport To Entity)
|
{ 0x30, PacketTypesOut.PlayerBlockPlacement }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item On)
|
||||||
{ 0x31, PacketTypesOut.PlayerBlockPlacement }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item On)
|
{ 0x31, PacketTypesOut.UseItem }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item)
|
||||||
{ 0x32, PacketTypesOut.UseItem }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override Dictionary<int, PacketTypesIn> GetListIn() => typeIn;
|
protected override Dictionary<int, PacketTypesIn> GetListIn() => typeIn;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MinecraftClient.Protocol.Handlers.PacketPalettes
|
||||||
|
{
|
||||||
|
public class PacketPalette19 : PacketTypePalette
|
||||||
|
{
|
||||||
|
private readonly Dictionary<int, PacketTypesIn> typeIn = new()
|
||||||
|
{
|
||||||
|
{ 0x00, PacketTypesIn.SpawnEntity },
|
||||||
|
{ 0x01, PacketTypesIn.SpawnExperienceOrb },
|
||||||
|
{ 0x02, PacketTypesIn.SpawnWeatherEntity },
|
||||||
|
{ 0x03, PacketTypesIn.SpawnLivingEntity },
|
||||||
|
{ 0x04, PacketTypesIn.SpawnPainting },
|
||||||
|
{ 0x05, PacketTypesIn.SpawnPlayer },
|
||||||
|
{ 0x06, PacketTypesIn.EntityAnimation },
|
||||||
|
{ 0x07, PacketTypesIn.Statistics },
|
||||||
|
{ 0x08, PacketTypesIn.BlockBreakAnimation },
|
||||||
|
{ 0x09, PacketTypesIn.BlockEntityData },
|
||||||
|
{ 0x0A, PacketTypesIn.BlockAction },
|
||||||
|
{ 0x0B, PacketTypesIn.BlockChange },
|
||||||
|
{ 0x0C, PacketTypesIn.BossBar },
|
||||||
|
{ 0x0D, PacketTypesIn.ServerDifficulty },
|
||||||
|
{ 0x0E, PacketTypesIn.TabComplete },
|
||||||
|
{ 0x0F, PacketTypesIn.ChatMessage },
|
||||||
|
{ 0x10, PacketTypesIn.MultiBlockChange },
|
||||||
|
{ 0x11, PacketTypesIn.WindowConfirmation },
|
||||||
|
{ 0x12, PacketTypesIn.CloseWindow },
|
||||||
|
{ 0x13, PacketTypesIn.OpenWindow },
|
||||||
|
{ 0x14, PacketTypesIn.WindowItems },
|
||||||
|
{ 0x15, PacketTypesIn.WindowProperty },
|
||||||
|
{ 0x16, PacketTypesIn.SetSlot },
|
||||||
|
{ 0x17, PacketTypesIn.SetCooldown },
|
||||||
|
{ 0x18, PacketTypesIn.PluginMessage },
|
||||||
|
{ 0x19, PacketTypesIn.NamedSoundEffect },
|
||||||
|
{ 0x1A, PacketTypesIn.Disconnect },
|
||||||
|
{ 0x1B, PacketTypesIn.EntityStatus },
|
||||||
|
{ 0x1C, PacketTypesIn.Explosion },
|
||||||
|
{ 0x1D, PacketTypesIn.UnloadChunk },
|
||||||
|
{ 0x1E, PacketTypesIn.ChangeGameState },
|
||||||
|
{ 0x1F, PacketTypesIn.KeepAlive },
|
||||||
|
{ 0x20, PacketTypesIn.ChunkData },
|
||||||
|
{ 0x21, PacketTypesIn.Effect },
|
||||||
|
{ 0x22, PacketTypesIn.Particle },
|
||||||
|
{ 0x23, PacketTypesIn.JoinGame },
|
||||||
|
{ 0x24, PacketTypesIn.MapData },
|
||||||
|
{ 0x25, PacketTypesIn.EntityPosition },
|
||||||
|
{ 0x26, PacketTypesIn.EntityPositionAndRotation },
|
||||||
|
{ 0x27, PacketTypesIn.EntityRotation },
|
||||||
|
{ 0x28, PacketTypesIn.EntityMovement },
|
||||||
|
{ 0x29, PacketTypesIn.VehicleMove },
|
||||||
|
{ 0x2A, PacketTypesIn.OpenSignEditor },
|
||||||
|
{ 0x2B, PacketTypesIn.PlayerAbilities },
|
||||||
|
{ 0x2C, PacketTypesIn.CombatEvent },
|
||||||
|
{ 0x2D, PacketTypesIn.PlayerInfo },
|
||||||
|
{ 0x2E, PacketTypesIn.PlayerPositionAndLook },
|
||||||
|
{ 0x2F, PacketTypesIn.UseBed },
|
||||||
|
{ 0x30, PacketTypesIn.DestroyEntities },
|
||||||
|
{ 0x31, PacketTypesIn.RemoveEntityEffect },
|
||||||
|
{ 0x32, PacketTypesIn.ResourcePackSend },
|
||||||
|
{ 0x33, PacketTypesIn.Respawn },
|
||||||
|
{ 0x34, PacketTypesIn.EntityHeadLook },
|
||||||
|
{ 0x35, PacketTypesIn.WorldBorder },
|
||||||
|
{ 0x36, PacketTypesIn.Camera },
|
||||||
|
{ 0x37, PacketTypesIn.HeldItemChange },
|
||||||
|
{ 0x38, PacketTypesIn.DisplayScoreboard },
|
||||||
|
{ 0x39, PacketTypesIn.EntityMetadata },
|
||||||
|
{ 0x3A, PacketTypesIn.AttachEntity },
|
||||||
|
{ 0x3B, PacketTypesIn.EntityVelocity },
|
||||||
|
{ 0x3C, PacketTypesIn.EntityEquipment },
|
||||||
|
{ 0x3D, PacketTypesIn.SetExperience },
|
||||||
|
{ 0x3E, PacketTypesIn.UpdateHealth },
|
||||||
|
{ 0x3F, PacketTypesIn.ScoreboardObjective },
|
||||||
|
{ 0x40, PacketTypesIn.SetPassengers },
|
||||||
|
{ 0x41, PacketTypesIn.Teams },
|
||||||
|
{ 0x42, PacketTypesIn.UpdateScore },
|
||||||
|
{ 0x43, PacketTypesIn.SpawnPosition },
|
||||||
|
{ 0x44, PacketTypesIn.TimeUpdate },
|
||||||
|
{ 0x45, PacketTypesIn.Title },
|
||||||
|
{ 0x46, PacketTypesIn.UpdateSign },
|
||||||
|
{ 0x47, PacketTypesIn.SoundEffect },
|
||||||
|
{ 0x48, PacketTypesIn.PlayerListHeaderAndFooter },
|
||||||
|
{ 0x49, PacketTypesIn.CollectItem },
|
||||||
|
{ 0x4A, PacketTypesIn.EntityTeleport },
|
||||||
|
{ 0x4B, PacketTypesIn.EntityProperties },
|
||||||
|
{ 0x4C, PacketTypesIn.EntityEffect },
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly Dictionary<int, PacketTypesOut> typeOut = new()
|
||||||
|
{
|
||||||
|
{ 0x00, PacketTypesOut.TeleportConfirm },
|
||||||
|
{ 0x01, PacketTypesOut.TabComplete },
|
||||||
|
{ 0x02, PacketTypesOut.ChatMessage },
|
||||||
|
{ 0x03, PacketTypesOut.ClientStatus },
|
||||||
|
{ 0x04, PacketTypesOut.ClientSettings },
|
||||||
|
{ 0x05, PacketTypesOut.WindowConfirmation },
|
||||||
|
{ 0x06, PacketTypesOut.EnchantItem },
|
||||||
|
{ 0x07, PacketTypesOut.ClickWindow },
|
||||||
|
{ 0x08, PacketTypesOut.CloseWindow },
|
||||||
|
{ 0x09, PacketTypesOut.PluginMessage },
|
||||||
|
{ 0x0A, PacketTypesOut.InteractEntity },
|
||||||
|
{ 0x0B, PacketTypesOut.KeepAlive },
|
||||||
|
{ 0x0C, PacketTypesOut.PlayerPosition },
|
||||||
|
{ 0x0D, PacketTypesOut.PlayerPositionAndRotation },
|
||||||
|
{ 0x0E, PacketTypesOut.PlayerRotation },
|
||||||
|
{ 0x0F, PacketTypesOut.PlayerMovement },
|
||||||
|
{ 0x10, PacketTypesOut.VehicleMove },
|
||||||
|
{ 0x11, PacketTypesOut.SteerBoat },
|
||||||
|
{ 0x12, PacketTypesOut.PlayerAbilities },
|
||||||
|
{ 0x13, PacketTypesOut.PlayerDigging },
|
||||||
|
{ 0x14, PacketTypesOut.EntityAction },
|
||||||
|
{ 0x15, PacketTypesOut.SteerVehicle },
|
||||||
|
{ 0x16, PacketTypesOut.ResourcePackStatus },
|
||||||
|
{ 0x17, PacketTypesOut.HeldItemChange },
|
||||||
|
{ 0x18, PacketTypesOut.CreativeInventoryAction },
|
||||||
|
{ 0x19, PacketTypesOut.UpdateSign },
|
||||||
|
{ 0x1A, PacketTypesOut.Animation },
|
||||||
|
{ 0x1B, PacketTypesOut.Spectate },
|
||||||
|
{ 0x1C, PacketTypesOut.PlayerBlockPlacement },
|
||||||
|
{ 0x1D, PacketTypesOut.UseItem },
|
||||||
|
};
|
||||||
|
|
||||||
|
protected override Dictionary<int, PacketTypesIn> GetListIn() => typeIn;
|
||||||
|
protected override Dictionary<int, PacketTypesOut> GetListOut() => typeOut;
|
||||||
|
protected override Dictionary<int, ConfigurationPacketTypesIn> GetConfigurationListIn() => new();
|
||||||
|
protected override Dictionary<int, ConfigurationPacketTypesOut> GetConfigurationListOut() => new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -56,6 +56,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
<= Protocol18Handler.MC_1_21_5_Version and > Protocol18Handler.MC_1_21_4_Version => new PacketPalette1215(),
|
<= Protocol18Handler.MC_1_21_5_Version and > Protocol18Handler.MC_1_21_4_Version => new PacketPalette1215(),
|
||||||
<= Protocol18Handler.MC_1_21_4_Version and > Protocol18Handler.MC_1_21_2_Version => new PacketPalette1214(),
|
<= Protocol18Handler.MC_1_21_4_Version and > Protocol18Handler.MC_1_21_2_Version => new PacketPalette1214(),
|
||||||
<= Protocol18Handler.MC_1_8_Version => new PacketPalette17(),
|
<= Protocol18Handler.MC_1_8_Version => new PacketPalette17(),
|
||||||
|
<= Protocol18Handler.MC_1_9_2_Version => new PacketPalette19(),
|
||||||
<= Protocol18Handler.MC_1_11_2_Version => new PacketPalette110(),
|
<= Protocol18Handler.MC_1_11_2_Version => new PacketPalette110(),
|
||||||
<= Protocol18Handler.MC_1_12_Version => new PacketPalette112(),
|
<= Protocol18Handler.MC_1_12_Version => new PacketPalette112(),
|
||||||
<= Protocol18Handler.MC_1_12_2_Version => new PacketPalette1122(),
|
<= Protocol18Handler.MC_1_12_2_Version => new PacketPalette1122(),
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
UpdateHealth, //
|
UpdateHealth, //
|
||||||
UpdateLight, //
|
UpdateLight, //
|
||||||
UpdateScore, //
|
UpdateScore, //
|
||||||
UpdateSign, // For 1.8 or below
|
UpdateSign, // For 1.8 or below, and 1.9-1.9.2
|
||||||
UpdateSimulationDistance, //
|
UpdateSimulationDistance, //
|
||||||
UpdateViewDistance, //
|
UpdateViewDistance, //
|
||||||
UpdateViewPosition, //
|
UpdateViewPosition, //
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
internal const int MC_1_8_Version = 47;
|
internal const int MC_1_8_Version = 47;
|
||||||
internal const int MC_1_9_Version = 107;
|
internal const int MC_1_9_Version = 107;
|
||||||
internal const int MC_1_9_1_Version = 108;
|
internal const int MC_1_9_1_Version = 108;
|
||||||
|
internal const int MC_1_9_2_Version = 109;
|
||||||
internal const int MC_1_10_Version = 210;
|
internal const int MC_1_10_Version = 210;
|
||||||
internal const int MC_1_11_Version = 315;
|
internal const int MC_1_11_Version = 315;
|
||||||
internal const int MC_1_11_2_Version = 316;
|
internal const int MC_1_11_2_Version = 316;
|
||||||
|
|
@ -835,15 +836,15 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
dimensionTypeName =
|
dimensionTypeName =
|
||||||
dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
|
dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
|
||||||
break;
|
break;
|
||||||
case >= MC_1_16_2_Version:
|
case >= MC_1_16_2_Version:
|
||||||
dimensionType =
|
dimensionType =
|
||||||
dataTypes.ReadNextNbt(
|
dataTypes.ReadNextNbt(
|
||||||
packetData); // Dimension Type: NBT Tag Compound
|
packetData); // Dimension Type: NBT Tag Compound
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dataTypes.ReadNextString(packetData);
|
dimensionTypeName = dataTypes.ReadNextString(packetData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDimension = 0;
|
currentDimension = 0;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1408,14 +1409,14 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
dimensionTypeNameRespawn =
|
dimensionTypeNameRespawn =
|
||||||
dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
|
dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
|
||||||
break;
|
break;
|
||||||
case >= MC_1_16_2_Version:
|
case >= MC_1_16_2_Version:
|
||||||
dimensionTypeRespawn =
|
dimensionTypeRespawn =
|
||||||
dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound
|
dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dataTypes.ReadNextString(packetData);
|
dimensionTypeNameRespawn = dataTypes.ReadNextString(packetData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDimension = 0;
|
currentDimension = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -4027,6 +4028,21 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
int blockEntityCount = dataTypes.ReadNextVarInt(packetData);
|
int blockEntityCount = dataTypes.ReadNextVarInt(packetData);
|
||||||
for (int i = 0; i < blockEntityCount; i++)
|
for (int i = 0; i < blockEntityCount; i++)
|
||||||
{
|
{
|
||||||
|
if (protocolVersion < MC_1_18_1_Version)
|
||||||
|
{
|
||||||
|
Dictionary<string, object>? blockEntityNbt = dataTypes.ReadNextNbt(packetData);
|
||||||
|
if (blockEntityNbt.TryGetValue("x", out var nbtX)
|
||||||
|
&& blockEntityNbt.TryGetValue("y", out var nbtY)
|
||||||
|
&& blockEntityNbt.TryGetValue("z", out var nbtZ))
|
||||||
|
{
|
||||||
|
handler.OnBlockEntityData(
|
||||||
|
new Location(Convert.ToInt32(nbtX), Convert.ToInt32(nbtY), Convert.ToInt32(nbtZ)),
|
||||||
|
blockEntityNbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int packedXZ = dataTypes.ReadNextByte(packetData);
|
int packedXZ = dataTypes.ReadNextByte(packetData);
|
||||||
int y = dataTypes.ReadNextShort(packetData);
|
int y = dataTypes.ReadNextShort(packetData);
|
||||||
dataTypes.ReadNextVarInt(packetData); // Block entity type registry id
|
dataTypes.ReadNextVarInt(packetData); // Block entity type registry id
|
||||||
|
|
@ -5616,7 +5632,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
private static byte ToLegacyBlockPlacementCursor(float cursor)
|
private static byte ToLegacyBlockPlacementCursor(float cursor)
|
||||||
{
|
{
|
||||||
return (byte)Math.Clamp((int)(cursor * 16.0f), 0, byte.MaxValue);
|
return (byte)Math.Clamp((int)(cursor * 16.0f), 0, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SendHeldItemChange(short slot)
|
public bool SendHeldItemChange(short slot)
|
||||||
|
|
@ -5752,16 +5768,11 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
switch (protocolVersion)
|
switch (protocolVersion)
|
||||||
{
|
{
|
||||||
// 1.18+
|
// 1.17.1+
|
||||||
case >= MC_1_18_1_Version:
|
case >= MC_1_17_1_Version:
|
||||||
packet.AddRange(DataTypes.GetVarInt(stateId)); // State ID
|
packet.AddRange(DataTypes.GetVarInt(stateId)); // State ID
|
||||||
packet.AddRange(dataTypes.GetShort((short)slotId)); // Slot ID
|
packet.AddRange(dataTypes.GetShort((short)slotId)); // Slot ID
|
||||||
break;
|
break;
|
||||||
// 1.17.1
|
|
||||||
case MC_1_17_1_Version:
|
|
||||||
packet.AddRange(dataTypes.GetShort((short)slotId)); // Slot ID
|
|
||||||
packet.AddRange(DataTypes.GetVarInt(stateId)); // State ID
|
|
||||||
break;
|
|
||||||
// Older
|
// Older
|
||||||
default:
|
default:
|
||||||
packet.AddRange(dataTypes.GetShort((short)slotId)); // Slot ID
|
packet.AddRange(dataTypes.GetShort((short)slotId)); // Slot ID
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue