diff --git a/MinecraftClient/Commands/Useblock.cs b/MinecraftClient/Commands/Useblock.cs
index 7e482ba4..d4f964a6 100644
--- a/MinecraftClient/Commands/Useblock.cs
+++ b/MinecraftClient/Commands/Useblock.cs
@@ -1,3 +1,4 @@
+using System;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
@@ -53,8 +54,27 @@ namespace MinecraftClient.Commands
Location current = handler.GetCurrentLocation();
block = block.ToAbsolute(current).ToFloor();
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);
}
+
+ 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;
+ }
}
}
diff --git a/MinecraftClient/Mapping/World.cs b/MinecraftClient/Mapping/World.cs
index aacfe1ec..0b6330ce 100644
--- a/MinecraftClient/Mapping/World.cs
+++ b/MinecraftClient/Mapping/World.cs
@@ -69,7 +69,16 @@ namespace MinecraftClient.Mapping
/// Registry Codec nbt data
public static void StoreDimensionList(Dictionary registryCodec)
{
- var dimensionListNbt = (object[])(((Dictionary)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)dimensionTypeRegistry)["value"]);
foreach (var (dimensionName, dimensionType) in from Dictionary dimensionNbt in dimensionListNbt
let dimensionName = (string)dimensionNbt["name"]
let dimensionType = (Dictionary)dimensionNbt["element"]
@@ -324,19 +333,48 @@ namespace MinecraftClient.Mapping
}
// If not found, check if name lacks 'minecraft:' prefix and try again
- if (!name.StartsWith("minecraft:"))
- {
- string prefixedName = "minecraft:" + name;
- if (dimensionList.TryGetValue(prefixedName, out dimension))
- {
- curDimension = dimension;
- return; // Dimension found with prefixed name
- }
- }
+ if (!name.StartsWith("minecraft:"))
+ {
+ string prefixedName = "minecraft:" + name;
+ if (dimensionList.TryGetValue(prefixedName, out dimension))
+ {
+ curDimension = dimension;
+ 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
- throw new KeyNotFoundException($"Dimension '{name}' not found in dimensions dictionary.");
- }
+ if (TryStoreDefaultVanillaDimension(name)
+ && 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());
+ return true;
+ }
diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs
index cde3ad55..b02e3269 100644
--- a/MinecraftClient/McClient.cs
+++ b/MinecraftClient/McClient.cs
@@ -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;
+ }
+
///
/// Click a slot in the specified window
///
@@ -2748,6 +2832,8 @@ namespace MinecraftClient
changedSlots.Add(new Tuple((short)slotId, null));
break;
}
+
+ SyncPlayerInventorySlotsFromWindow(inventory);
}
return handler.SendWindowAction(windowId, slotId, action, item, changedSlots, inventories[windowId].StateID);
@@ -2764,7 +2850,16 @@ namespace MinecraftClient
/// TRUE if item given successfully
public bool DoCreativeGive(int slot, ItemType itemType, int count, Dictionary? 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;
+ });
}
///
@@ -3780,6 +3875,9 @@ namespace MinecraftClient
{
inventories[inventoryID].Items = itemList;
inventories[inventoryID].StateID = stateId;
+ bool playerInventoryChanged = SyncPlayerInventorySlotsFromWindow(inventories[inventoryID]);
+ if (playerInventoryChanged)
+ DispatchBotEvent(bot => bot.OnInventoryUpdate(0));
DispatchBotEvent(bot => bot.OnInventoryUpdate(inventoryID));
}
}
@@ -3820,6 +3918,9 @@ namespace MinecraftClient
inventories[inventoryID].Items.Remove(slotID);
}
else inventories[inventoryID].Items[slotID] = item;
+
+ if (SyncPlayerInventorySlotFromWindow(inventories[inventoryID], slotID))
+ DispatchBotEvent(bot => bot.OnInventoryUpdate(0));
}
}
DispatchBotEvent(bot => bot.OnInventoryUpdate(inventoryID));
@@ -4676,6 +4777,9 @@ namespace MinecraftClient
{
switch (reason)
{
+ case 3:
+ OnGamemodeUpdate(Guid.Empty, (int)value);
+ break;
case 7:
DispatchBotEvent(bot => bot.OnRainLevelChange(value));
break;
diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj
index 9a9c8baa..4307393e 100644
--- a/MinecraftClient/MinecraftClient.csproj
+++ b/MinecraftClient/MinecraftClient.csproj
@@ -59,32 +59,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette119.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette119.cs
index 0757dcb8..7a7e9eb6 100644
--- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette119.cs
+++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette119.cs
@@ -118,9 +118,9 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes
{ 0x00, PacketTypesOut.TeleportConfirm }, // (Wiki name: Confirm Teleportation)
{ 0x01, PacketTypesOut.QueryBlockNBT }, // (Wiki name: Query Block Entity Tag)
{ 0x02, PacketTypesOut.SetDifficulty }, // (Wiki name: Change Difficutly)
- { 0x03, PacketTypesOut.MessageAcknowledgment }, //
- { 0x04, PacketTypesOut.ChatCommand }, // Added in 1.19
- { 0x05, PacketTypesOut.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Chat)
+ { 0x03, PacketTypesOut.ChatCommand }, // Added in 1.19
+ { 0x04, 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)
{ 0x07, PacketTypesOut.ClientSettings }, // (Wiki name: Client Information)
{ 0x08, PacketTypesOut.TabComplete }, // (Wiki name: Command Suggestions Request)
@@ -147,25 +147,24 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes
{ 0x1D, PacketTypesOut.EntityAction }, // (Wiki name: Player Command)
{ 0x1E, PacketTypesOut.SteerVehicle }, // (Wiki name: Player Input)
{ 0x1F, PacketTypesOut.Pong }, // (Wiki name: Pong (play))
- { 0x20, PacketTypesOut.PlayerSession }, // Added in 1.19.3
- { 0x21, PacketTypesOut.SetDisplayedRecipe }, // (Wiki name: Recipe Book Change Settings)
- { 0x22, PacketTypesOut.SetRecipeBookState }, // (Wiki name: Recipe Book Seen Recipe)
- { 0x23, PacketTypesOut.NameItem }, // (Wiki name: Rename Item)
- { 0x24, PacketTypesOut.ResourcePackStatus }, // (Wiki name: Resource Pack (serverbound))
- { 0x25, PacketTypesOut.AdvancementTab }, // (Wiki name: Seen Advancements)
- { 0x26, PacketTypesOut.SelectTrade }, //
- { 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)
- { 0x28, PacketTypesOut.HeldItemChange }, // (Wiki name: Set Carried Item (serverbound))
- { 0x29, PacketTypesOut.UpdateCommandBlock }, // (Wiki name: Set Command Block)
- { 0x2A, PacketTypesOut.UpdateCommandBlockMinecart }, //
- { 0x2B, PacketTypesOut.CreativeInventoryAction }, // (Wiki name: Set Creative Mode Slot)
- { 0x2C, PacketTypesOut.UpdateJigsawBlock }, // (Wiki name: Set Jigsaw Block)
- { 0x2D, PacketTypesOut.UpdateStructureBlock }, // (Wiki name: Set Structure Block)
- { 0x2E, PacketTypesOut.UpdateSign }, // (Wiki name: Sign Update)
- { 0x2F, PacketTypesOut.Animation }, // (Wiki name: Swing)
- { 0x30, PacketTypesOut.Spectate }, // (Wiki name: Teleport To Entity)
- { 0x31, PacketTypesOut.PlayerBlockPlacement }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item On)
- { 0x32, PacketTypesOut.UseItem }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item)
+ { 0x20, PacketTypesOut.SetDisplayedRecipe }, // (Wiki name: Recipe Book Change Settings)
+ { 0x21, PacketTypesOut.SetRecipeBookState }, // (Wiki name: Recipe Book Seen Recipe)
+ { 0x22, PacketTypesOut.NameItem }, // (Wiki name: Rename Item)
+ { 0x23, PacketTypesOut.ResourcePackStatus }, // (Wiki name: Resource Pack (serverbound))
+ { 0x24, PacketTypesOut.AdvancementTab }, // (Wiki name: Seen Advancements)
+ { 0x25, 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.HeldItemChange }, // (Wiki name: Set Carried Item (serverbound))
+ { 0x28, PacketTypesOut.UpdateCommandBlock }, // (Wiki name: Set Command Block)
+ { 0x29, PacketTypesOut.UpdateCommandBlockMinecart }, //
+ { 0x2A, PacketTypesOut.CreativeInventoryAction }, // (Wiki name: Set Creative Mode Slot)
+ { 0x2B, PacketTypesOut.UpdateJigsawBlock }, // (Wiki name: Set Jigsaw Block)
+ { 0x2C, PacketTypesOut.UpdateStructureBlock }, // (Wiki name: Set Structure Block)
+ { 0x2D, PacketTypesOut.UpdateSign }, // (Wiki name: Sign Update)
+ { 0x2E, PacketTypesOut.Animation }, // (Wiki name: Swing)
+ { 0x2F, 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.UseItem }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item)
};
protected override Dictionary GetListIn() => typeIn;
diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette19.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette19.cs
new file mode 100644
index 00000000..ebffc31a
--- /dev/null
+++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette19.cs
@@ -0,0 +1,127 @@
+using System.Collections.Generic;
+
+namespace MinecraftClient.Protocol.Handlers.PacketPalettes
+{
+ public class PacketPalette19 : PacketTypePalette
+ {
+ private readonly Dictionary 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 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 GetListIn() => typeIn;
+ protected override Dictionary GetListOut() => typeOut;
+ protected override Dictionary GetConfigurationListIn() => new();
+ protected override Dictionary GetConfigurationListOut() => new();
+ }
+}
diff --git a/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs b/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs
index 21515782..82ee6e69 100644
--- a/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs
+++ b/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs
@@ -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_4_Version and > Protocol18Handler.MC_1_21_2_Version => new PacketPalette1214(),
<= 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_12_Version => new PacketPalette112(),
<= Protocol18Handler.MC_1_12_2_Version => new PacketPalette1122(),
diff --git a/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs b/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs
index a36bc4ba..8aee524a 100644
--- a/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs
+++ b/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs
@@ -146,7 +146,7 @@ namespace MinecraftClient.Protocol.Handlers
UpdateHealth, //
UpdateLight, //
UpdateScore, //
- UpdateSign, // For 1.8 or below
+ UpdateSign, // For 1.8 or below, and 1.9-1.9.2
UpdateSimulationDistance, //
UpdateViewDistance, //
UpdateViewPosition, //
diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs
index 9f56a622..5f71b9af 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs
@@ -45,6 +45,7 @@ namespace MinecraftClient.Protocol.Handlers
internal const int MC_1_8_Version = 47;
internal const int MC_1_9_Version = 107;
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_11_Version = 315;
internal const int MC_1_11_2_Version = 316;
@@ -835,15 +836,15 @@ namespace MinecraftClient.Protocol.Handlers
dimensionTypeName =
dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
break;
- case >= MC_1_16_2_Version:
- dimensionType =
- dataTypes.ReadNextNbt(
- packetData); // Dimension Type: NBT Tag Compound
- break;
- default:
- dataTypes.ReadNextString(packetData);
- break;
- }
+ case >= MC_1_16_2_Version:
+ dimensionType =
+ dataTypes.ReadNextNbt(
+ packetData); // Dimension Type: NBT Tag Compound
+ break;
+ default:
+ dimensionTypeName = dataTypes.ReadNextString(packetData);
+ break;
+ }
currentDimension = 0;
break;
@@ -1408,14 +1409,14 @@ namespace MinecraftClient.Protocol.Handlers
dimensionTypeNameRespawn =
dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
break;
- case >= MC_1_16_2_Version:
- dimensionTypeRespawn =
- dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound
- break;
- default:
- dataTypes.ReadNextString(packetData);
- break;
- }
+ case >= MC_1_16_2_Version:
+ dimensionTypeRespawn =
+ dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound
+ break;
+ default:
+ dimensionTypeNameRespawn = dataTypes.ReadNextString(packetData);
+ break;
+ }
currentDimension = 0;
}
@@ -4027,6 +4028,21 @@ namespace MinecraftClient.Protocol.Handlers
int blockEntityCount = dataTypes.ReadNextVarInt(packetData);
for (int i = 0; i < blockEntityCount; i++)
{
+ if (protocolVersion < MC_1_18_1_Version)
+ {
+ Dictionary? 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 y = dataTypes.ReadNextShort(packetData);
dataTypes.ReadNextVarInt(packetData); // Block entity type registry id
@@ -5616,7 +5632,7 @@ namespace MinecraftClient.Protocol.Handlers
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)
@@ -5752,16 +5768,11 @@ namespace MinecraftClient.Protocol.Handlers
switch (protocolVersion)
{
- // 1.18+
- case >= MC_1_18_1_Version:
+ // 1.17.1+
+ case >= MC_1_17_1_Version:
packet.AddRange(DataTypes.GetVarInt(stateId)); // State ID
packet.AddRange(dataTypes.GetShort((short)slotId)); // Slot ID
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
default:
packet.AddRange(dataTypes.GetShort((short)slotId)); // Slot ID