Merge pull request #2930: Further Protocol Adaptation for 1.20.6 / 1.21 / 1.21.2

Further Protocol Adaptation for 1.20.6 / 1.21 / 1.21.2
This commit is contained in:
BruceChen 2026-03-20 22:53:06 +08:00 committed by GitHub
commit e5de803613
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
176 changed files with 15052 additions and 709 deletions

View file

@ -0,0 +1,130 @@
---
name: mcc-version-adaptation
description: Adapt MCC palettes and protocol handling for a new Minecraft version. Use when the user wants to add support for a new MC version, compare version registries, update item/entity/block/metadata palettes, or fix protocol mismatches between MC versions.
---
# MCC Version Adaptation
Systematic workflow for updating Minecraft Console Client to support a new Minecraft version, focusing on palette/registry changes and entity metadata.
## Prerequisites
- Decompiled server source for both the old and new MC versions in `$MCC_REPO/MinecraftOfficial/<version>-decompiled/`
- If missing, decompile first:
```bash
cd $MCC_REPO/MinecraftOfficial
java -jar MinecraftDecompiler.jar --version <ver> --side SERVER \
--decompile --output <ver>-remapped.jar --decompiled-output <ver>-decompiled
```
## Step 1: Run Registry Diff
```bash
python3 $MCC_REPO/tools/diff_registries.py <old_ver> <new_ver>
```
This compares five registries and reports which need palette updates:
| Registry | MCC File | When to Update |
|----------|----------|----------------|
| Items.java | `ItemPalettes/ItemPaletteXXX.cs` | New/removed/reordered items |
| EntityType.java | `EntityPalettes/EntityPaletteXXX.cs` | New/removed/reordered entity types |
| Blocks.java | `BlockPalettes/BlockPaletteXXX.cs` | New/removed/reordered blocks |
| DataComponents.java | `StructuredComponents/StructuredComponentsRegistryXXX.cs` | New/reordered components |
| EntityDataSerializers.java | `EntityMetadataPalettes/EntityMetadataPaletteXXX.cs` | New/reordered serializer types |
## Step 2: Generate Updated Palettes
For registries marked "PALETTE UPDATE NEEDED":
### Item Palette
```bash
python3 $MCC_REPO/tools/gen_item_palette.py <new_ver> <suffix>
# e.g., gen_item_palette.py 1.21.1 121
```
- If new items are reported missing from `ItemType.cs`, add them to the enum in alphabetical order.
- The script auto-generates the C# palette file.
### Entity Metadata Palette
```bash
python3 $MCC_REPO/tools/gen_entity_metadata_palette.py <new_ver> <suffix>
# e.g., gen_entity_metadata_palette.py 1.20.6 1206
```
- If new serializer types appear as UNMAPPED, add them to both:
1. The script's `FIELD_TO_ENUM` dictionary
2. MCC's `EntityMetaDataType.cs` enum
3. `DataTypes.cs` read logic (add a `case` to consume the correct bytes)
### Entity/Block Palettes
No generator script yet — these change rarely. When needed, manually create by following the pattern of existing palette files, using `register("name", ...)` call order from the decompiled source.
### DataComponents / StructuredComponents
Compare `DataComponents.java` registration order. If new components appear, update `StructuredComponentsRegistryXXX.cs`. For new component types, implement corresponding reader in `StructuredComponents/Components/`.
## Step 3: Update Version Routing
After creating palette files, update version selection logic:
| Palette Type | Routing Location |
|-------------|-----------------|
| Item | `Protocol18.cs``itemPalette` switch expression |
| Entity | `Protocol18.cs``entityPalette` switch expression |
| Block | `Protocol18.cs``blockPalette` initialization |
| EntityMetadata | `EntityMetadataPalette.cs``GetPalette()` switch |
| DataComponents | `StructuredComponentsRegistry.cs` → factory/routing |
Pattern: add a new `>= MC_X_Y_Z_Version => new XxxPaletteXYZ()` case.
## Step 4: Check Variant Encoding Changes
For entity types that use variant serializers (Cat, Wolf, Frog, Painting), check if the codec changed between versions by inspecting:
- `EntityDataSerializers.java` — look at how each `*_VARIANT` field is constructed
- Key codecs:
- `ByteBufCodecs.holderRegistry()` → wire format: `VarInt(registry_id)`
- `ByteBufCodecs.holder()` → wire format: `VarInt(id+1)` for registered, `VarInt(0) + inline_data` for direct
- If codec changed, update `DataTypes.cs` entity metadata reading logic accordingly.
## Step 5: Handle New EntityDataSerializer Types
When new serializer types are added (detected in Step 1):
1. Add enum value to `EntityMetaDataType.cs` with XML doc comment
2. Add read logic in `DataTypes.cs` `ReadNextMetadata()`:
- Determine byte consumption from the decompiled codec
- Examples: VarInt read, list of particles, etc.
3. Create the new palette file (Step 2)
4. Update palette routing (Step 3)
## Step 6: Compile and Verify
```bash
dotnet build $MCC_REPO/MinecraftClient.sln -c Release
```
Then connect to a test server of the target version (see `mcc-dev-workflow` skill) and verify:
- Successful connection
- `/give` new items → check inventory
- Summon entities (especially variant types) → no metadata parse errors
- Particle effects → no crashes
## Key Source Files Reference
| Decompiled Java Source | Purpose |
|----------------------|---------|
| `world/item/Items.java` | Item registry (field declaration order = ID) |
| `world/entity/EntityType.java` | Entity type registry (`register()` call order = ID) |
| `world/level/block/Blocks.java` | Block registry (`register()` call order = ID) |
| `core/component/DataComponents.java` | Data component registry |
| `network/syncher/EntityDataSerializers.java` | Entity metadata type registry (static block order = ID) |
## Common Pitfalls
- **ID order matters**: IDs are determined by declaration/registration order, not alphabetical. Always use the decompiled source as ground truth.
- **Cross-version jumps**: When MCC skips versions (e.g., 1.20.4→1.20.6), registries from ALL intermediate versions may have changed. Always diff against the actual last-supported version, not the latest palette.
- **EntityMetadata type shifts**: A single new serializer type shifts all subsequent IDs, causing widespread metadata parse failures. Symptoms: entity rendering glitches, disconnections, or silent data corruption.
- **CUT_STANDSTONE_SLAB**: This is an intentional typo in Minecraft source (should be SANDSTONE). MCC's `ItemType.cs` uses `CutSandstoneSlab` — the gen script handles this via the OVERRIDES dict.
## Reusable Scripts
All scripts are in `$MCC_REPO/tools/`. See `tools/README.md` for detailed usage.

View file

@ -8,7 +8,7 @@ on:
env:
PROJECT: "MinecraftClient"
target-version: "net7.0"
target-version: "net8.0"
compile-flags: "--self-contained=true -c Release -p:UseAppHost=true -p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:DebugType=Embedded"
jobs:
@ -19,7 +19,7 @@ jobs:
timeout-minutes: 15
strategy:
matrix:
target: [win-x86, win-x64, win-arm, win-arm64, linux-x64, linux-arm, linux-arm64, osx-x64, osx-arm64]
target: [win-x86, win-x64, win-arm64, linux-x64, linux-arm, linux-arm64, osx-x64, osx-arm64]
steps:
- name: Checkout

3
.gitignore vendored
View file

@ -387,6 +387,9 @@ FodyWeavers.xsd
!.vscode/extensions.json
*.code-workspace
# Cursor files
!.cursor/
# Local History for Visual Studio Code
.history/

View file

@ -0,0 +1,105 @@
using System;
using System.IO;
using System.Threading;
using MinecraftClient.CommandHandler;
using MinecraftClient.Scripting;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Debug-only ChatBot that monitors a text file for commands.
/// Write lines to the file from any external tool (e.g. Cursor Shell)
/// and this bot will execute them as MCC internal commands.
///
/// Usage from Cursor Shell:
/// Add-Content mcc_input.txt "inventory"
/// Add-Content mcc_input.txt "send /give @s diamond_sword 1"
///
/// Lines starting with "/" are sent as server chat; others are treated
/// as MCC internal commands (same as typing in the MCC console).
/// </summary>
public class FileInputBot : ChatBot
{
private const string BotName = "FileInput";
private string _filePath = string.Empty;
private long _lastPosition;
private int _tickCounter;
public override void Initialize()
{
_filePath = Path.GetFullPath(
Environment.GetEnvironmentVariable("MCC_INPUT_FILE") ?? "mcc_input.txt");
if (File.Exists(_filePath))
_lastPosition = new FileInfo(_filePath).Length;
else
File.WriteAllText(_filePath, "");
LogToConsole(BotName, $"Watching: {_filePath}");
LogToConsole(BotName, "Write commands to this file to execute them.");
}
public override void Update()
{
// Poll every ~500ms (Update is called every ~100ms)
if (++_tickCounter < 5)
return;
_tickCounter = 0;
try
{
if (!File.Exists(_filePath))
return;
var info = new FileInfo(_filePath);
if (info.Length <= _lastPosition)
return;
string newContent;
using (var fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
fs.Seek(_lastPosition, SeekOrigin.Begin);
using var reader = new StreamReader(fs);
newContent = reader.ReadToEnd();
}
_lastPosition = info.Length;
foreach (var rawLine in newContent.Split('\n'))
{
var line = rawLine.Trim();
if (string.IsNullOrEmpty(line))
continue;
LogToConsole(BotName, $"> {line}");
if (line.StartsWith("/"))
{
SendText(line);
}
else
{
CmdResult result = new();
if (PerformInternalCommand(line, ref result))
{
if (!string.IsNullOrEmpty(result.ToString()))
LogToConsole(BotName, result.ToString());
}
else
{
// Not an internal command — send as chat
SendText(line);
}
}
}
}
catch (IOException)
{
// File may be temporarily locked by the writer
}
catch (Exception ex)
{
LogToConsole(BotName, $"Error: {ex.Message}");
}
}
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -344,8 +344,11 @@ namespace MinecraftClient.ChatBots
private static void RenderInConsole(McMap map)
{
StringBuilder sb = new();
int consoleWidth = Math.Max(Console.BufferWidth, Settings.Config.Main.Advanced.MinTerminalWidth) / 2;
int consoleHeight = Math.Max(Console.BufferHeight, Settings.Config.Main.Advanced.MinTerminalHeight) - 1;
int safeBufWidth, safeBufHeight;
try { safeBufWidth = Console.BufferWidth; } catch { safeBufWidth = 120; }
try { safeBufHeight = Console.BufferHeight; } catch { safeBufHeight = 50; }
int consoleWidth = Math.Max(safeBufWidth, Settings.Config.Main.Advanced.MinTerminalWidth) / 2;
int consoleHeight = Math.Max(safeBufHeight, Settings.Config.Main.Advanced.MinTerminalHeight) - 1;
int scaleX = (map.Width + consoleWidth - 1) / consoleWidth;
int scaleY = (map.Height + consoleHeight - 1) / consoleHeight;
int scale = Math.Max(scaleX, scaleY);

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Text;
using Brigadier.NET;
using Brigadier.NET.Builder;
@ -100,11 +100,15 @@ namespace MinecraftClient.Commands
sb.AppendLine(string.Format(Translations.cmd_chunk_chunk_pos, markChunkX, markChunkZ)); ;
}
int consoleHeight = Math.Max(Math.Max(Console.BufferHeight, Settings.Config.Main.Advanced.MinTerminalHeight) - 2, 25);
int safeHeight;
int safeWidth;
try { safeHeight = Console.BufferHeight; } catch { safeHeight = 50; }
try { safeWidth = Console.BufferWidth; } catch { safeWidth = 120; }
int consoleHeight = Math.Max(Math.Max(safeHeight, Settings.Config.Main.Advanced.MinTerminalHeight) - 2, 25);
if (consoleHeight % 2 == 0)
--consoleHeight;
int consoleWidth = Math.Max(Math.Max(Console.BufferWidth, Settings.Config.Main.Advanced.MinTerminalWidth) / 2, 17);
int consoleWidth = Math.Max(Math.Max(safeWidth, Settings.Config.Main.Advanced.MinTerminalWidth) / 2, 17);
if (consoleWidth % 2 == 0)
--consoleWidth;

View file

@ -1,4 +1,4 @@
using Brigadier.NET;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.Mapping;
@ -48,7 +48,7 @@ namespace MinecraftClient.Commands
Location current = handler.GetCurrentLocation();
block = block.ToAbsolute(current).ToFloor();
Location blockCenter = block.ToCenter();
bool res = handler.PlaceBlock(block, Direction.Down);
bool res = handler.PlaceBlock(block, Direction.Down, lookAtBlock: true);
return r.SetAndReturn(string.Format(Translations.cmd_useblock_use, blockCenter.X, blockCenter.Y, blockCenter.Z, res ? "succeeded" : "failed"), res);
}
}

View file

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace MinecraftClient.Inventory;
public record BookPage(
string RawContent,
bool HasFilteredContent,
string? FilteredContent,
Dictionary<string, object>? RawContentNbt = null,
Dictionary<string, object>? FilteredContentNbt = null);

View file

@ -0,0 +1,3 @@
namespace MinecraftClient.Inventory;
public record Enchantment(Enchantments Type, int Level);

View file

@ -2,9 +2,9 @@
{
public class EnchantmentData
{
public Enchantment TopEnchantment { get; set; }
public Enchantment MiddleEnchantment { get; set; }
public Enchantment BottomEnchantment { get; set; }
public Enchantments TopEnchantment { get; set; }
public Enchantments MiddleEnchantment { get; set; }
public Enchantments BottomEnchantment { get; set; }
// Seed for rendering Standard Galactic Language (symbols in the enchanting table) (Useful for poeple who use MCC for the protocol)
public short Seed { get; set; }

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using MinecraftClient.Protocol.Handlers;
@ -10,168 +10,307 @@ namespace MinecraftClient.Inventory
{
#pragma warning disable format // @formatter:off
// 1.14 - 1.15.2
private static Dictionary<short, Enchantment> enchantmentMappings114 = new Dictionary<short, Enchantment>()
private static Dictionary<short, Enchantments> enchantmentMappings114 = new()
{
//id type
{ 0, Enchantment.Protection },
{ 1, Enchantment.FireProtection },
{ 2, Enchantment.FeatherFalling },
{ 3, Enchantment.BlastProtection },
{ 4, Enchantment.ProjectileProtection },
{ 5, Enchantment.Respiration },
{ 6, Enchantment.AquaAffinity },
{ 7, Enchantment.Thorns },
{ 8, Enchantment.DepthStrieder },
{ 9, Enchantment.FrostWalker },
{ 10, Enchantment.BindingCurse },
{ 11, Enchantment.Sharpness },
{ 12, Enchantment.Smite },
{ 13, Enchantment.BaneOfArthropods },
{ 14, Enchantment.Knockback },
{ 15, Enchantment.FireAspect },
{ 16, Enchantment.Looting },
{ 17, Enchantment.Sweeping },
{ 18, Enchantment.Efficency },
{ 19, Enchantment.SilkTouch },
{ 20, Enchantment.Unbreaking },
{ 21, Enchantment.Fortune },
{ 22, Enchantment.Power },
{ 23, Enchantment.Punch },
{ 24, Enchantment.Flame },
{ 25, Enchantment.Infinity },
{ 26, Enchantment.LuckOfTheSea },
{ 27, Enchantment.Lure },
{ 28, Enchantment.Loyality },
{ 29, Enchantment.Impaling },
{ 30, Enchantment.Riptide },
{ 31, Enchantment.Channeling },
{ 32, Enchantment.Mending },
{ 33, Enchantment.VanishingCurse }
{ 0, Enchantments.Protection },
{ 1, Enchantments.FireProtection },
{ 2, Enchantments.FeatherFalling },
{ 3, Enchantments.BlastProtection },
{ 4, Enchantments.ProjectileProtection },
{ 5, Enchantments.Respiration },
{ 6, Enchantments.AquaAffinity },
{ 7, Enchantments.Thorns },
{ 8, Enchantments.DepthStrider },
{ 9, Enchantments.FrostWalker },
{ 10, Enchantments.BindingCurse },
{ 11, Enchantments.Sharpness },
{ 12, Enchantments.Smite },
{ 13, Enchantments.BaneOfArthropods },
{ 14, Enchantments.Knockback },
{ 15, Enchantments.FireAspect },
{ 16, Enchantments.Looting },
{ 17, Enchantments.Sweeping },
{ 18, Enchantments.Efficiency },
{ 19, Enchantments.SilkTouch },
{ 20, Enchantments.Unbreaking },
{ 21, Enchantments.Fortune },
{ 22, Enchantments.Power },
{ 23, Enchantments.Punch },
{ 24, Enchantments.Flame },
{ 25, Enchantments.Infinity },
{ 26, Enchantments.LuckOfTheSea },
{ 27, Enchantments.Lure },
{ 28, Enchantments.Loyalty },
{ 29, Enchantments.Impaling },
{ 30, Enchantments.Riptide },
{ 31, Enchantments.Channeling },
{ 32, Enchantments.Mending },
{ 33, Enchantments.VanishingCurse }
};
// 1.16 - 1.18
private static Dictionary<short, Enchantment> enchantmentMappings116 = new Dictionary<short, Enchantment>()
private static Dictionary<short, Enchantments> enchantmentMappings116 = new()
{
//id type
{ 0, Enchantment.Protection },
{ 1, Enchantment.FireProtection },
{ 2, Enchantment.FeatherFalling },
{ 3, Enchantment.BlastProtection },
{ 4, Enchantment.ProjectileProtection },
{ 5, Enchantment.Respiration },
{ 6, Enchantment.AquaAffinity },
{ 7, Enchantment.Thorns },
{ 8, Enchantment.DepthStrieder },
{ 9, Enchantment.FrostWalker },
{ 10, Enchantment.BindingCurse },
{ 11, Enchantment.SoulSpeed },
{ 12, Enchantment.Sharpness },
{ 13, Enchantment.Smite },
{ 14, Enchantment.BaneOfArthropods },
{ 15, Enchantment.Knockback },
{ 16, Enchantment.FireAspect },
{ 17, Enchantment.Looting },
{ 18, Enchantment.Sweeping },
{ 19, Enchantment.Efficency },
{ 20, Enchantment.SilkTouch },
{ 21, Enchantment.Unbreaking },
{ 22, Enchantment.Fortune },
{ 23, Enchantment.Power },
{ 24, Enchantment.Punch },
{ 25, Enchantment.Flame },
{ 26, Enchantment.Infinity },
{ 27, Enchantment.LuckOfTheSea },
{ 28, Enchantment.Lure },
{ 29, Enchantment.Loyality },
{ 30, Enchantment.Impaling },
{ 31, Enchantment.Riptide },
{ 32, Enchantment.Channeling },
{ 33, Enchantment.Multishot },
{ 34, Enchantment.QuickCharge },
{ 35, Enchantment.Piercing },
{ 36, Enchantment.Mending },
{ 37, Enchantment.VanishingCurse }
{ 0, Enchantments.Protection },
{ 1, Enchantments.FireProtection },
{ 2, Enchantments.FeatherFalling },
{ 3, Enchantments.BlastProtection },
{ 4, Enchantments.ProjectileProtection },
{ 5, Enchantments.Respiration },
{ 6, Enchantments.AquaAffinity },
{ 7, Enchantments.Thorns },
{ 8, Enchantments.DepthStrider },
{ 9, Enchantments.FrostWalker },
{ 10, Enchantments.BindingCurse },
{ 11, Enchantments.SoulSpeed },
{ 12, Enchantments.Sharpness },
{ 13, Enchantments.Smite },
{ 14, Enchantments.BaneOfArthropods },
{ 15, Enchantments.Knockback },
{ 16, Enchantments.FireAspect },
{ 17, Enchantments.Looting },
{ 18, Enchantments.Sweeping },
{ 19, Enchantments.Efficiency },
{ 20, Enchantments.SilkTouch },
{ 21, Enchantments.Unbreaking },
{ 22, Enchantments.Fortune },
{ 23, Enchantments.Power },
{ 24, Enchantments.Punch },
{ 25, Enchantments.Flame },
{ 26, Enchantments.Infinity },
{ 27, Enchantments.LuckOfTheSea },
{ 28, Enchantments.Lure },
{ 29, Enchantments.Loyalty },
{ 30, Enchantments.Impaling },
{ 31, Enchantments.Riptide },
{ 32, Enchantments.Channeling },
{ 33, Enchantments.Multishot },
{ 34, Enchantments.QuickCharge },
{ 35, Enchantments.Piercing },
{ 36, Enchantments.Mending },
{ 37, Enchantments.VanishingCurse }
};
// 1.19+
private static Dictionary<short, Enchantment> enchantmentMappings = new Dictionary<short, Enchantment>()
// 1.19 - 1.20.4
private static Dictionary<short, Enchantments> enchantmentMappings119 = new()
{
//id type
{ 0, Enchantment.Protection },
{ 1, Enchantment.FireProtection },
{ 2, Enchantment.FeatherFalling },
{ 3, Enchantment.BlastProtection },
{ 4, Enchantment.ProjectileProtection },
{ 5, Enchantment.Respiration },
{ 6, Enchantment.AquaAffinity },
{ 7, Enchantment.Thorns },
{ 8, Enchantment.DepthStrieder },
{ 9, Enchantment.FrostWalker },
{ 10, Enchantment.BindingCurse },
{ 11, Enchantment.SoulSpeed },
{ 12, Enchantment.SwiftSneak },
{ 13, Enchantment.Sharpness },
{ 14, Enchantment.Smite },
{ 15, Enchantment.BaneOfArthropods },
{ 16, Enchantment.Knockback },
{ 17, Enchantment.FireAspect },
{ 18, Enchantment.Looting },
{ 19, Enchantment.Sweeping },
{ 20, Enchantment.Efficency },
{ 21, Enchantment.SilkTouch },
{ 22, Enchantment.Unbreaking },
{ 23, Enchantment.Fortune },
{ 24, Enchantment.Power },
{ 25, Enchantment.Punch },
{ 26, Enchantment.Flame },
{ 27, Enchantment.Infinity },
{ 28, Enchantment.LuckOfTheSea },
{ 29, Enchantment.Lure },
{ 30, Enchantment.Loyality },
{ 31, Enchantment.Impaling },
{ 32, Enchantment.Riptide },
{ 33, Enchantment.Channeling },
{ 34, Enchantment.Multishot },
{ 35, Enchantment.QuickCharge },
{ 36, Enchantment.Piercing },
{ 37, Enchantment.Mending },
{ 38, Enchantment.VanishingCurse }
{ 0, Enchantments.Protection },
{ 1, Enchantments.FireProtection },
{ 2, Enchantments.FeatherFalling },
{ 3, Enchantments.BlastProtection },
{ 4, Enchantments.ProjectileProtection },
{ 5, Enchantments.Respiration },
{ 6, Enchantments.AquaAffinity },
{ 7, Enchantments.Thorns },
{ 8, Enchantments.DepthStrider },
{ 9, Enchantments.FrostWalker },
{ 10, Enchantments.BindingCurse },
{ 11, Enchantments.SoulSpeed },
{ 12, Enchantments.SwiftSneak },
{ 13, Enchantments.Sharpness },
{ 14, Enchantments.Smite },
{ 15, Enchantments.BaneOfArthropods },
{ 16, Enchantments.Knockback },
{ 17, Enchantments.FireAspect },
{ 18, Enchantments.Looting },
{ 19, Enchantments.Sweeping },
{ 20, Enchantments.Efficiency },
{ 21, Enchantments.SilkTouch },
{ 22, Enchantments.Unbreaking },
{ 23, Enchantments.Fortune },
{ 24, Enchantments.Power },
{ 25, Enchantments.Punch },
{ 26, Enchantments.Flame },
{ 27, Enchantments.Infinity },
{ 28, Enchantments.LuckOfTheSea },
{ 29, Enchantments.Lure },
{ 30, Enchantments.Loyalty },
{ 31, Enchantments.Impaling },
{ 32, Enchantments.Riptide },
{ 33, Enchantments.Channeling },
{ 34, Enchantments.Multishot },
{ 35, Enchantments.QuickCharge },
{ 36, Enchantments.Piercing },
{ 37, Enchantments.Mending },
{ 38, Enchantments.VanishingCurse }
};
// 1.20.6+
private static Dictionary<short, Enchantments> enchantmentMappings = new()
{
//id type
{ 0, Enchantments.Protection },
{ 1, Enchantments.FireProtection },
{ 2, Enchantments.FeatherFalling },
{ 3, Enchantments.BlastProtection },
{ 4, Enchantments.ProjectileProtection },
{ 5, Enchantments.Respiration },
{ 6, Enchantments.AquaAffinity },
{ 7, Enchantments.Thorns },
{ 8, Enchantments.DepthStrider },
{ 9, Enchantments.FrostWalker },
{ 10, Enchantments.BindingCurse },
{ 11, Enchantments.SoulSpeed },
{ 12, Enchantments.SwiftSneak },
{ 13, Enchantments.Sharpness },
{ 14, Enchantments.Smite },
{ 15, Enchantments.BaneOfArthropods },
{ 16, Enchantments.Knockback },
{ 17, Enchantments.FireAspect },
{ 18, Enchantments.Looting },
{ 19, Enchantments.Sweeping },
{ 20, Enchantments.Efficiency },
{ 21, Enchantments.SilkTouch },
{ 22, Enchantments.Unbreaking },
{ 23, Enchantments.Fortune },
{ 24, Enchantments.Power },
{ 25, Enchantments.Punch },
{ 26, Enchantments.Flame },
{ 27, Enchantments.Infinity },
{ 28, Enchantments.LuckOfTheSea },
{ 29, Enchantments.Lure },
{ 30, Enchantments.Loyalty },
{ 31, Enchantments.Impaling },
{ 32, Enchantments.Riptide },
{ 33, Enchantments.Channeling },
{ 34, Enchantments.Multishot },
{ 35, Enchantments.QuickCharge },
{ 36, Enchantments.Piercing },
{ 37, Enchantments.Density },
{ 38, Enchantments.Breach },
{ 39, Enchantments.WindBurst },
{ 40, Enchantments.Mending },
{ 41, Enchantments.VanishingCurse }
};
#pragma warning restore format // @formatter:on
public static Enchantment GetEnchantmentById(int protocolVersion, short id)
public static Enchantments GetEnchantmentById(int protocolVersion, short id)
{
if (protocolVersion < Protocol18Handler.MC_1_14_Version)
throw new Exception("Enchantments mappings are not implemented bellow 1.14");
Dictionary<short, Enchantment> map = enchantmentMappings;
var map = protocolVersion switch
{
>= Protocol18Handler.MC_1_14_Version and < Protocol18Handler.MC_1_16_Version => enchantmentMappings114,
>= Protocol18Handler.MC_1_16_Version and < Protocol18Handler.MC_1_19_Version => enchantmentMappings116,
>= Protocol18Handler.MC_1_19_Version and < Protocol18Handler.MC_1_21_Version => enchantmentMappings119,
_ => enchantmentMappings
};
if (protocolVersion >= Protocol18Handler.MC_1_14_Version && protocolVersion < Protocol18Handler.MC_1_16_Version)
map = enchantmentMappings114;
else if (protocolVersion >= Protocol18Handler.MC_1_16_Version && protocolVersion < Protocol18Handler.MC_1_19_Version)
map = enchantmentMappings116;
if (!map.TryGetValue(id, out var value))
throw new Exception($"Got an Unknown Enchantment ID {id}, please update the Mappings!");
if (!map.ContainsKey(id))
throw new Exception("Got an Unknown Enchantment ID '" + id + "', please update the Mappings!");
return map[id];
return value;
}
public static string GetEnchantmentName(Enchantment enchantment)
private static Dictionary<Enchantments, short>? reverseEnchantmentMappings;
private static Dictionary<int, Enchantments>? dynamicEnchantmentIdMap;
private static readonly Dictionary<string, Enchantments> nameToEnchantment = new()
{
string? trans = ChatParser.TranslateString("enchantment.minecraft." + enchantment.ToString().ToUnderscoreCase());
if (string.IsNullOrEmpty(trans))
return "Unknown Enchantment with ID: " + ((short)enchantment) + " (Probably not named in the code yet)";
else
return trans;
{ "protection", Enchantments.Protection },
{ "fire_protection", Enchantments.FireProtection },
{ "feather_falling", Enchantments.FeatherFalling },
{ "blast_protection", Enchantments.BlastProtection },
{ "projectile_protection", Enchantments.ProjectileProtection },
{ "respiration", Enchantments.Respiration },
{ "aqua_affinity", Enchantments.AquaAffinity },
{ "thorns", Enchantments.Thorns },
{ "depth_strider", Enchantments.DepthStrider },
{ "frost_walker", Enchantments.FrostWalker },
{ "binding_curse", Enchantments.BindingCurse },
{ "soul_speed", Enchantments.SoulSpeed },
{ "swift_sneak", Enchantments.SwiftSneak },
{ "sharpness", Enchantments.Sharpness },
{ "smite", Enchantments.Smite },
{ "bane_of_arthropods", Enchantments.BaneOfArthropods },
{ "knockback", Enchantments.Knockback },
{ "fire_aspect", Enchantments.FireAspect },
{ "looting", Enchantments.Looting },
{ "sweeping_edge", Enchantments.Sweeping },
{ "efficiency", Enchantments.Efficiency },
{ "silk_touch", Enchantments.SilkTouch },
{ "unbreaking", Enchantments.Unbreaking },
{ "fortune", Enchantments.Fortune },
{ "power", Enchantments.Power },
{ "punch", Enchantments.Punch },
{ "flame", Enchantments.Flame },
{ "infinity", Enchantments.Infinity },
{ "luck_of_the_sea", Enchantments.LuckOfTheSea },
{ "lure", Enchantments.Lure },
{ "loyalty", Enchantments.Loyalty },
{ "impaling", Enchantments.Impaling },
{ "riptide", Enchantments.Riptide },
{ "channeling", Enchantments.Channeling },
{ "multishot", Enchantments.Multishot },
{ "quick_charge", Enchantments.QuickCharge },
{ "piercing", Enchantments.Piercing },
{ "density", Enchantments.Density },
{ "breach", Enchantments.Breach },
{ "wind_burst", Enchantments.WindBurst },
{ "mending", Enchantments.Mending },
{ "vanishing_curse", Enchantments.VanishingCurse },
};
/// <summary>
/// Set the dynamic enchantment ID map from server RegistryData.
/// Called during configuration phase when receiving minecraft:enchantment registry.
/// </summary>
public static void SetDynamicEnchantmentIdMap(Dictionary<int, string> idMap)
{
dynamicEnchantmentIdMap = new Dictionary<int, Enchantments>();
foreach (var kvp in idMap)
{
var name = kvp.Value.StartsWith("minecraft:") ? kvp.Value.Substring("minecraft:".Length) : kvp.Value;
if (nameToEnchantment.TryGetValue(name, out var enchantment))
dynamicEnchantmentIdMap[kvp.Key] = enchantment;
}
reverseEnchantmentMappings = null;
}
public static Enchantments GetEnchantmentByRegistryId1206(int id)
{
if (dynamicEnchantmentIdMap != null && dynamicEnchantmentIdMap.TryGetValue(id, out var dynValue))
return dynValue;
if (enchantmentMappings.TryGetValue((short)id, out var value))
return value;
return (Enchantments)(-1);
}
public static int GetRegistryId1206ByEnchantment(Enchantments enchantment)
{
if (reverseEnchantmentMappings == null)
{
reverseEnchantmentMappings = new Dictionary<Enchantments, short>();
if (dynamicEnchantmentIdMap != null)
{
foreach (var kvp in dynamicEnchantmentIdMap)
reverseEnchantmentMappings[kvp.Value] = (short)kvp.Key;
}
else
{
foreach (var kvp in enchantmentMappings)
reverseEnchantmentMappings[kvp.Value] = kvp.Key;
}
}
return reverseEnchantmentMappings.TryGetValue(enchantment, out var id) ? id : -1;
}
public static string GetEnchantmentName(Enchantments enchantment)
{
var translation = ChatParser.TranslateString("enchantment.minecraft." + enchantment.ToString().ToUnderscoreCase());
return string.IsNullOrEmpty(translation) ? $"Unknown Enchantment with ID: {(short)enchantment} (Probably not named in the code yet)" : translation;
}
public static string ConvertLevelToRomanNumbers(int num)
{
string result = string.Empty;
Dictionary<string, int> romanNumbers = new Dictionary<string, int>
var result = string.Empty;
var romanNumbers = new Dictionary<string, int>
{
{"M", 1000 },
{"M", 1000},
{"CM", 900},
{"D", 500},
{"CD", 400},

View file

@ -1,46 +1,49 @@
namespace MinecraftClient.Inventory
namespace MinecraftClient.Inventory
{
// Not implemented for 1.14
public enum Enchantment : short
public enum Enchantments : short
{
Protection = 0,
FireProtection,
FeatherFalling,
BlastProtection,
ProjectileProtection,
Respiration,
AquaAffinity,
Thorns,
DepthStrieder,
FrostWalker,
BindingCurse,
SoulSpeed,
SwiftSneak,
Sharpness,
Smite,
AquaAffinity = 0,
BaneOfArthropods,
Knockback,
FireAspect,
Looting,
Sweeping,
Efficency,
SilkTouch,
Unbreaking,
Fortune,
Power,
Punch,
Flame,
Infinity,
LuckOfTheSea,
Lure,
Loyality,
Impaling,
Riptide,
BindingCurse,
BlastProtection,
Breach,
Channeling,
Multishot,
QuickCharge,
Piercing,
DepthStrider,
Density,
Efficiency,
FeatherFalling,
FireAspect,
FireProtection,
Flame,
Fortune,
FrostWalker,
Impaling,
Infinity,
Knockback,
Looting,
LuckOfTheSea,
Loyalty,
Lure,
Mending,
VanishingCurse
Multishot,
Piercing,
Power,
ProjectileProtection,
Protection,
Punch,
QuickCharge,
Respiration,
Riptide,
Sharpness,
SilkTouch,
Smite,
SoulSpeed,
Sweeping,
SwiftSneak,
Thorns,
Unbreaking,
VanishingCurse,
WindBurst
}
}

View file

@ -1,8 +1,10 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
using MinecraftClient.Protocol.Message;
namespace MinecraftClient.Inventory
@ -32,6 +34,11 @@ namespace MinecraftClient.Inventory
/// </summary>
public Dictionary<string, object>? NBT;
/// <summary>
/// 1.20.6+ structured components (raw list for round-trip serialization)
/// </summary>
public List<StructuredComponent>? Components;
/// <summary>
/// Create an item with ItemType, Count and Metadata
/// </summary>
@ -50,6 +57,14 @@ namespace MinecraftClient.Inventory
Data = data;
}
/// <summary>
/// Create a shallow clone with a specific count (preserves NBT and Components).
/// </summary>
public Item CloneWithCount(int count)
{
return new Item(Type, count, Data, NBT) { Components = Components };
}
/// <summary>
/// Check if the item slot is empty
/// </summary>
@ -60,12 +75,26 @@ namespace MinecraftClient.Inventory
}
/// <summary>
/// Retrieve item display name from NBT properties. NULL if no display name is defined.
/// Retrieve item display name. For 1.20.6+ reads from structured components
/// (CustomNameComponent, then ItemNameComponent as fallback); for older versions reads from NBT.
/// </summary>
public string? DisplayName
{
get
{
if (Components != null)
{
var customName = Components.OfType<CustomNameComponent>().FirstOrDefault();
if (customName != null && !string.IsNullOrEmpty(customName.CustomName))
return customName.CustomName;
var itemName = Components.OfType<ItemNameComponent>().FirstOrDefault();
if (itemName != null && !string.IsNullOrEmpty(itemName.ItemName))
return itemName.ItemName;
return null;
}
if (NBT != null && NBT.ContainsKey("display"))
{
if (NBT["display"] is Dictionary<string, object> displayProperties &&
@ -82,12 +111,21 @@ namespace MinecraftClient.Inventory
}
/// <summary>
/// Retrieve item lores from NBT properties. Returns null if no lores is defined.
/// Retrieve item lores. For 1.20.6+ reads from LoreNameComponent1206; for older versions reads from NBT.
/// </summary>
public string[]? Lores
{
get
{
if (Components != null)
{
var loreComponent = Components.OfType<LoreNameComponent1206>().FirstOrDefault();
if (loreComponent != null && loreComponent.Lines.Count > 0)
return loreComponent.Lines.ToArray();
return null;
}
List<string> lores = new();
if (NBT != null && NBT.ContainsKey("display"))
{
@ -107,12 +145,21 @@ namespace MinecraftClient.Inventory
}
/// <summary>
/// Retrieve item damage from NBT properties. Returns 0 if no damage is defined.
/// Retrieve item damage. For 1.20.6+ reads from DamageComponent; for older versions reads from NBT.
/// </summary>
public int Damage
{
get
{
if (Components != null)
{
var damageComponent = Components.OfType<DamageComponent>().FirstOrDefault();
if (damageComponent != null)
return damageComponent.Damage;
return 0;
}
if (NBT != null && NBT.ContainsKey("Damage"))
{
object damage = NBT["Damage"];
@ -127,6 +174,26 @@ namespace MinecraftClient.Inventory
}
}
/// <summary>
/// Retrieve enchantments from structured components (1.20.6+). Returns null for older versions.
/// Both normal enchantments (EnchantmentsComponent) and stored enchantments
/// (StoredEnchantmentsComponent, e.g. enchanted books) are checked.
/// </summary>
public List<Enchantment>? EnchantmentList
{
get
{
if (Components == null)
return null;
var enchComp = Components.OfType<EnchantmentsComponent>().FirstOrDefault();
if (enchComp != null && enchComp.Enchantments.Count > 0)
return enchComp.Enchantments;
return null;
}
}
public static string GetTypeString(ItemType type)
{
string type_str = type.ToString();
@ -152,8 +219,18 @@ namespace MinecraftClient.Inventory
try
{
if (NBT != null && (NBT.TryGetValue("Enchantments", out object? enchantments) ||
NBT.TryGetValue("StoredEnchantments", out enchantments)))
var enchList = EnchantmentList;
if (enchList != null)
{
foreach (var ench in enchList)
{
string name = EnchantmentMapping.GetEnchantmentName(ench.Type);
string level = EnchantmentMapping.ConvertLevelToRomanNumbers(ench.Level);
sb.AppendFormat(" | {0} {1}", name, level);
}
}
else if (NBT != null && (NBT.TryGetValue("Enchantments", out object? enchantments) ||
NBT.TryGetValue("StoredEnchantments", out enchantments)))
{
foreach (Dictionary<string, object> enchantment in (object[])enchantments)
{

View file

@ -71,7 +71,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[1835008] = ItemType.DetectorRail;
mappings[1900544] = ItemType.StickyPiston;
mappings[1966080] = ItemType.Cobweb;
mappings[2031617] = ItemType.Grass;
mappings[2031617] = ItemType.ShortGrass;
mappings[2031618] = ItemType.Fern;
mappings[2097152] = ItemType.DeadBush;
mappings[2162688] = ItemType.Piston;

View file

@ -71,7 +71,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[1835008] = ItemType.DetectorRail;
mappings[1900544] = ItemType.StickyPiston;
mappings[1966080] = ItemType.Cobweb;
mappings[2031617] = ItemType.Grass;
mappings[2031617] = ItemType.ShortGrass;
mappings[2031618] = ItemType.Fern;
mappings[2097152] = ItemType.DeadBush;
mappings[2162688] = ItemType.Piston;

View file

@ -62,7 +62,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[1769472] = ItemType.PoweredRail;
mappings[1835008] = ItemType.DetectorRail;
mappings[1900544] = ItemType.StickyPiston;
mappings[2031617] = ItemType.Grass;
mappings[2031617] = ItemType.ShortGrass;
mappings[2031618] = ItemType.Fern;
mappings[2097152] = ItemType.DeadBush;
mappings[2162688] = ItemType.Piston;

View file

@ -88,7 +88,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[73] = ItemType.DetectorRail;
mappings[74] = ItemType.StickyPiston;
mappings[75] = ItemType.Cobweb;
mappings[76] = ItemType.Grass;
mappings[76] = ItemType.ShortGrass;
mappings[77] = ItemType.Fern;
mappings[78] = ItemType.DeadBush;
mappings[79] = ItemType.Seagrass;
@ -531,7 +531,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[516] = ItemType.Jigsaw;
mappings[517] = ItemType.Composter;
mappings[518] = ItemType.TurtleHelmet;
mappings[519] = ItemType.Scute;
mappings[519] = ItemType.TurtleScute;
mappings[520] = ItemType.IronShovel;
mappings[521] = ItemType.IronPickaxe;
mappings[522] = ItemType.IronAxe;

View file

@ -101,7 +101,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[86] = ItemType.DetectorRail;
mappings[87] = ItemType.StickyPiston;
mappings[88] = ItemType.Cobweb;
mappings[89] = ItemType.Grass;
mappings[89] = ItemType.ShortGrass;
mappings[90] = ItemType.Fern;
mappings[91] = ItemType.DeadBush;
mappings[92] = ItemType.Seagrass;
@ -583,7 +583,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[568] = ItemType.StructureBlock;
mappings[569] = ItemType.Jigsaw;
mappings[570] = ItemType.TurtleHelmet;
mappings[571] = ItemType.Scute;
mappings[571] = ItemType.TurtleScute;
mappings[572] = ItemType.IronShovel;
mappings[573] = ItemType.IronPickaxe;
mappings[574] = ItemType.IronAxe;

View file

@ -101,7 +101,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[86] = ItemType.DetectorRail;
mappings[87] = ItemType.StickyPiston;
mappings[88] = ItemType.Cobweb;
mappings[89] = ItemType.Grass;
mappings[89] = ItemType.ShortGrass;
mappings[90] = ItemType.Fern;
mappings[91] = ItemType.DeadBush;
mappings[92] = ItemType.Seagrass;
@ -583,7 +583,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[568] = ItemType.StructureBlock;
mappings[569] = ItemType.Jigsaw;
mappings[570] = ItemType.TurtleHelmet;
mappings[571] = ItemType.Scute;
mappings[571] = ItemType.TurtleScute;
mappings[572] = ItemType.FlintAndSteel;
mappings[573] = ItemType.Apple;
mappings[574] = ItemType.Bow;

View file

@ -158,7 +158,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[147] = ItemType.ChiseledSandstone;
mappings[148] = ItemType.CutSandstone;
mappings[149] = ItemType.Cobweb;
mappings[150] = ItemType.Grass;
mappings[150] = ItemType.ShortGrass;
mappings[151] = ItemType.Fern;
mappings[152] = ItemType.Azalea;
mappings[153] = ItemType.FloweringAzalea;
@ -687,7 +687,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[676] = ItemType.StructureBlock;
mappings[677] = ItemType.Jigsaw;
mappings[678] = ItemType.TurtleHelmet;
mappings[679] = ItemType.Scute;
mappings[679] = ItemType.TurtleScute;
mappings[680] = ItemType.FlintAndSteel;
mappings[681] = ItemType.Apple;
mappings[682] = ItemType.Bow;

View file

@ -158,7 +158,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[147] = ItemType.ChiseledSandstone;
mappings[148] = ItemType.CutSandstone;
mappings[149] = ItemType.Cobweb;
mappings[150] = ItemType.Grass;
mappings[150] = ItemType.ShortGrass;
mappings[151] = ItemType.Fern;
mappings[152] = ItemType.Azalea;
mappings[153] = ItemType.FloweringAzalea;
@ -687,7 +687,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[676] = ItemType.StructureBlock;
mappings[677] = ItemType.Jigsaw;
mappings[678] = ItemType.TurtleHelmet;
mappings[679] = ItemType.Scute;
mappings[679] = ItemType.TurtleScute;
mappings[680] = ItemType.FlintAndSteel;
mappings[681] = ItemType.Apple;
mappings[682] = ItemType.Bow;

View file

@ -449,7 +449,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[598] = ItemType.GraniteSlab;
mappings[581] = ItemType.GraniteStairs;
mappings[355] = ItemType.GraniteWall;
mappings[160] = ItemType.Grass;
mappings[160] = ItemType.ShortGrass;
mappings[14] = ItemType.GrassBlock;
mappings[42] = ItemType.Gravel;
mappings[1032] = ItemType.GrayBanner;
@ -927,7 +927,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[626] = ItemType.SculkSensor;
mappings[329] = ItemType.SculkShrieker;
mappings[327] = ItemType.SculkVein;
mappings[715] = ItemType.Scute;
mappings[715] = ItemType.TurtleScute;
mappings[461] = ItemType.SeaLantern;
mappings[166] = ItemType.SeaPickle;
mappings[165] = ItemType.Seagrass;

View file

@ -473,7 +473,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[608] = ItemType.GraniteSlab;
mappings[591] = ItemType.GraniteStairs;
mappings[365] = ItemType.GraniteWall;
mappings[164] = ItemType.Grass;
mappings[164] = ItemType.ShortGrass;
mappings[14] = ItemType.GrassBlock;
mappings[44] = ItemType.Gravel;
mappings[1066] = ItemType.GrayBanner;
@ -956,7 +956,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[636] = ItemType.SculkSensor;
mappings[337] = ItemType.SculkShrieker;
mappings[335] = ItemType.SculkVein;
mappings[732] = ItemType.Scute;
mappings[732] = ItemType.TurtleScute;
mappings[471] = ItemType.SeaLantern;
mappings[170] = ItemType.SeaPickle;
mappings[169] = ItemType.Seagrass;

View file

@ -495,7 +495,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[622] = ItemType.GraniteSlab;
mappings[605] = ItemType.GraniteStairs;
mappings[379] = ItemType.GraniteWall;
mappings[172] = ItemType.Grass;
mappings[172] = ItemType.ShortGrass;
mappings[14] = ItemType.GrassBlock;
mappings[47] = ItemType.Gravel;
mappings[1090] = ItemType.GrayBanner;
@ -985,7 +985,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[650] = ItemType.SculkSensor;
mappings[350] = ItemType.SculkShrieker;
mappings[348] = ItemType.SculkVein;
mappings[753] = ItemType.Scute;
mappings[753] = ItemType.TurtleScute;
mappings[485] = ItemType.SeaLantern;
mappings[178] = ItemType.SeaPickle;
mappings[177] = ItemType.Seagrass;

View file

@ -505,7 +505,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[625] = ItemType.GraniteSlab;
mappings[608] = ItemType.GraniteStairs;
mappings[381] = ItemType.GraniteWall;
mappings[173] = ItemType.Grass;
mappings[173] = ItemType.ShortGrass;
mappings[14] = ItemType.GrassBlock;
mappings[48] = ItemType.Gravel;
mappings[1094] = ItemType.GrayBanner;
@ -1003,7 +1003,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[653] = ItemType.SculkSensor;
mappings[352] = ItemType.SculkShrieker;
mappings[350] = ItemType.SculkVein;
mappings[757] = ItemType.Scute;
mappings[757] = ItemType.TurtleScute;
mappings[487] = ItemType.SeaLantern;
mappings[179] = ItemType.SeaPickle;
mappings[178] = ItemType.Seagrass;

View file

@ -1025,7 +1025,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[674] = ItemType.SculkSensor;
mappings[373] = ItemType.SculkShrieker;
mappings[371] = ItemType.SculkVein;
mappings[794] = ItemType.Scute;
mappings[794] = ItemType.TurtleScute;
mappings[508] = ItemType.SeaLantern;
mappings[200] = ItemType.SeaPickle;
mappings[199] = ItemType.Seagrass;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -70,7 +70,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[1769472] = ItemType.PoweredRail;
mappings[1835008] = ItemType.DetectorRail;
mappings[1900544] = ItemType.StickyPiston;
mappings[2031617] = ItemType.Grass;
mappings[2031617] = ItemType.ShortGrass;
mappings[2031618] = ItemType.Fern;
mappings[2097152] = ItemType.DeadBush;
mappings[2162688] = ItemType.Piston;

View file

@ -66,7 +66,7 @@ namespace MinecraftClient.Inventory.ItemPalettes
mappings[1769472] = ItemType.PoweredRail;
mappings[1835008] = ItemType.DetectorRail;
mappings[1900544] = ItemType.StickyPiston;
mappings[2031617] = ItemType.Grass;
mappings[2031617] = ItemType.ShortGrass;
mappings[2031618] = ItemType.Fern;
mappings[2097152] = ItemType.DeadBush;
mappings[2293760] = ItemType.WhiteWool;

View file

@ -0,0 +1,9 @@
namespace MinecraftClient.Inventory;
public enum ItemRarity : int
{
Common = 0,
Uncommon,
Rare,
Epic
}

View file

@ -1,4 +1,4 @@
namespace MinecraftClient.Inventory
namespace MinecraftClient.Inventory
{
/// <summary>
/// Generated using the --generator flag on the client
@ -47,6 +47,8 @@
Anvil,
Apple,
ArcherPotterySherd,
ArmadilloScute,
ArmadilloSpawnEgg,
ArmorStand,
ArmsUpPotterySherd,
Arrow,
@ -119,6 +121,7 @@
BlackStainedGlassPane,
BlackTerracotta,
BlackWool,
BlackBundle,
Blackstone,
BlackstoneSlab,
BlackstoneStairs,
@ -143,17 +146,22 @@
BlueStainedGlassPane,
BlueTerracotta,
BlueWool,
BlueBundle,
BoggedSpawnEgg,
BoltArmorTrimSmithingTemplate,
Bone,
BoneBlock,
BoneMeal,
Book,
Bookshelf,
BordureIndentedBannerPattern,
Bow,
Bowl,
BrainCoral,
BrainCoralBlock,
BrainCoralFan,
Bread,
BreezeRod,
BreezeSpawnEgg,
BrewerPotterySherd,
BrewingStand,
@ -177,6 +185,7 @@
BrownStainedGlassPane,
BrownTerracotta,
BrownWool,
BrownBundle,
Brush,
BubbleCoral,
BubbleCoralBlock,
@ -293,6 +302,8 @@
CrackedStoneBricks,
Crafter,
CraftingTable,
CreakingHeart,
CreakingSpawnEgg,
CreeperBannerPattern,
CreeperHead,
CreeperSpawnEgg,
@ -334,6 +345,7 @@
CyanStainedGlassPane,
CyanTerracotta,
CyanWool,
CyanBundle,
DamagedAnvil,
Dandelion,
DangerPotterySherd,
@ -467,6 +479,7 @@
Feather,
FermentedSpiderEye,
Fern,
FieldMasonedBannerPattern,
FilledMap,
FireCharge,
FireCoral,
@ -478,6 +491,9 @@
FletchingTable,
Flint,
FlintAndSteel,
FlowArmorTrimSmithingTemplate,
FlowBannerPattern,
FlowPotterySherd,
FlowerBannerPattern,
FlowerPot,
FloweringAzalea,
@ -525,7 +541,6 @@
GraniteSlab,
GraniteStairs,
GraniteWall,
Grass, // 1.20.3+ renamed to ShortGrass
GrassBlock,
Gravel,
GrayBanner,
@ -541,6 +556,7 @@
GrayStainedGlassPane,
GrayTerracotta,
GrayWool,
GrayBundle,
GreenBanner,
GreenBed,
GreenCandle,
@ -554,14 +570,18 @@
GreenStainedGlassPane,
GreenTerracotta,
GreenWool,
GreenBundle,
Grindstone,
GuardianSpawnEgg,
Gunpowder,
GusterBannerPattern,
GusterPotterySherd,
HangingRoots,
HayBlock,
HeartOfTheSea,
HeartPotterySherd,
HeartbreakPotterySherd,
HeavyCore,
HeavyWeightedPressurePlate,
HoglinSpawnEgg,
HoneyBlock,
@ -658,6 +678,7 @@
LightBlueStainedGlassPane,
LightBlueTerracotta,
LightBlueWool,
LightBlueBundle,
LightGrayBanner,
LightGrayBed,
LightGrayCandle,
@ -671,6 +692,7 @@
LightGrayStainedGlassPane,
LightGrayTerracotta,
LightGrayWool,
LightGrayBundle,
LightWeightedPressurePlate,
LightningRod,
Lilac,
@ -689,10 +711,12 @@
LimeStainedGlassPane,
LimeTerracotta,
LimeWool,
LimeBundle,
LingeringPotion,
LlamaSpawnEgg,
Lodestone,
Loom,
Mace,
MagentaBanner,
MagentaBed,
MagentaCandle,
@ -706,6 +730,7 @@
MagentaStainedGlassPane,
MagentaTerracotta,
MagentaWool,
MagentaBundle,
MagmaBlock,
MagmaCream,
MagmaCubeSpawnEgg,
@ -763,11 +788,14 @@
MusicDiscBlocks,
MusicDiscCat,
MusicDiscChirp,
MusicDiscCreator,
MusicDiscCreatorMusicBox,
MusicDiscFar,
MusicDiscMall,
MusicDiscMellohi,
MusicDiscOtherside,
MusicDiscPigstep,
MusicDiscPrecipice,
MusicDiscRelic,
MusicDiscStal,
MusicDiscStrad,
@ -825,6 +853,8 @@
Obsidian,
OcelotSpawnEgg,
OchreFroglight,
OminousBottle,
OminousTrialKey,
OrangeBanner,
OrangeBed,
OrangeCandle,
@ -839,6 +869,7 @@
OrangeTerracotta,
OrangeTulip,
OrangeWool,
OrangeBundle,
OxeyeDaisy,
OxidizedChiseledCopper,
OxidizedCopper,
@ -852,6 +883,26 @@
PackedIce,
PackedMud,
Painting,
PaleHangingMoss,
PaleMossBlock,
PaleMossCarpet,
PaleOakBoat,
PaleOakButton,
PaleOakChestBoat,
PaleOakDoor,
PaleOakFence,
PaleOakFenceGate,
PaleOakHangingSign,
PaleOakLeaves,
PaleOakLog,
PaleOakPlanks,
PaleOakPressurePlate,
PaleOakSapling,
PaleOakSign,
PaleOakSlab,
PaleOakStairs,
PaleOakTrapdoor,
PaleOakWood,
PandaSpawnEgg,
Paper,
ParrotSpawnEgg,
@ -881,6 +932,7 @@
PinkTerracotta,
PinkTulip,
PinkWool,
PinkBundle,
Piston,
PitcherPlant,
PitcherPod,
@ -954,6 +1006,7 @@
PurpleStainedGlassPane,
PurpleTerracotta,
PurpleWool,
PurpleBundle,
PurpurBlock,
PurpurPillar,
PurpurSlab,
@ -1004,6 +1057,7 @@
RedTerracotta,
RedTulip,
RedWool,
RedBundle,
Redstone,
RedstoneBlock,
RedstoneLamp,
@ -1027,12 +1081,12 @@
SandstoneStairs,
SandstoneWall,
Scaffolding,
ScrapePotterySherd,
Sculk,
SculkCatalyst,
SculkSensor,
SculkShrieker,
SculkVein,
Scute,
SeaLantern,
SeaPickle,
Seagrass,
@ -1151,6 +1205,8 @@
StrippedMangroveWood,
StrippedOakLog,
StrippedOakWood,
StrippedPaleOakLog,
StrippedPaleOakWood,
StrippedSpruceLog,
StrippedSpruceWood,
StrippedWarpedHyphae,
@ -1200,8 +1256,10 @@
TuffWall,
TurtleEgg,
TurtleHelmet,
TurtleScute,
TurtleSpawnEgg,
TwistingVines,
Vault,
VerdantFroglight,
VexArmorTrimSmithingTemplate,
VexSpawnEgg,
@ -1294,12 +1352,15 @@
WhiteTerracotta,
WhiteTulip,
WhiteWool,
WhiteBundle,
WildArmorTrimSmithingTemplate,
WindCharge,
WitchSpawnEgg,
WitherRose,
WitherSkeletonSkull,
WitherSkeletonSpawnEgg,
WitherSpawnEgg,
WolfArmor,
WolfSpawnEgg,
WoodenAxe,
WoodenHoe,
@ -1321,6 +1382,7 @@
YellowStainedGlassPane,
YellowTerracotta,
YellowWool,
YellowBundle,
ZoglinSpawnEgg,
ZombieHead,
ZombieHorseSpawnEgg,

View file

@ -0,0 +1,3 @@
namespace MinecraftClient.Inventory;
public record SuspiciousStewEffect(int TypeId, int Duration);

View file

@ -0,0 +1,3 @@
namespace MinecraftClient.Inventory;
public record TrimAssetOverride(int ArmorMaterialType, string AssetName);

View file

@ -641,7 +641,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
materials[i] = Material.GraniteStairs;
for (int i = 15315; i <= 15638; i++)
materials[i] = Material.GraniteWall;
materials[2005] = Material.Grass;
materials[2005] = Material.ShortGrass;
for (int i = 8; i <= 9; i++)
materials[i] = Material.GrassBlock;
materials[118] = Material.Gravel;

View file

@ -43,7 +43,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
{ 28, Material.DetectorRail },
{ 29, Material.StickyPiston }, // PistonStickyBase
{ 30, Material.Cobweb }, // Web
{ 31, Material.Grass }, // LongGrass
{ 31, Material.TallGrass }, // LongGrass
{ 32, Material.DeadBush },
{ 33, Material.Piston }, // PistonBase
{ 34, Material.PistonHead }, // PistonExtension

View file

@ -167,7 +167,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
for (int i = 1028; i <= 1039; i++)
materials[i] = Material.StickyPiston;
materials[1040] = Material.Cobweb;
materials[1041] = Material.Grass;
materials[1041] = Material.ShortGrass;
materials[1042] = Material.Fern;
materials[1043] = Material.DeadBush;
materials[1044] = Material.Seagrass;

View file

@ -167,7 +167,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
for (int i = 1328; i <= 1339; i++)
materials[i] = Material.StickyPiston;
materials[1340] = Material.Cobweb;
materials[1341] = Material.Grass;
materials[1341] = Material.ShortGrass;
materials[1342] = Material.Fern;
materials[1343] = Material.DeadBush;
materials[1344] = Material.Seagrass;

View file

@ -167,7 +167,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
for (int i = 1328; i <= 1339; i++)
materials[i] = Material.StickyPiston;
materials[1340] = Material.Cobweb;
materials[1341] = Material.Grass;
materials[1341] = Material.ShortGrass;
materials[1342] = Material.Fern;
materials[1343] = Material.DeadBush;
materials[1344] = Material.Seagrass;

View file

@ -164,7 +164,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
for (int i = 1329; i <= 1340; i++)
materials[i] = Material.StickyPiston;
materials[1341] = Material.Cobweb;
materials[1342] = Material.Grass;
materials[1342] = Material.ShortGrass;
materials[1343] = Material.Fern;
materials[1344] = Material.DeadBush;
materials[1345] = Material.Seagrass;

View file

@ -172,7 +172,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
for (int i = 1385; i <= 1396; i++)
materials[i] = Material.StickyPiston;
materials[1397] = Material.Cobweb;
materials[1398] = Material.Grass;
materials[1398] = Material.ShortGrass;
materials[1399] = Material.Fern;
materials[1400] = Material.DeadBush;
materials[1401] = Material.Seagrass;

View file

@ -554,7 +554,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
materials[i] = Material.GraniteStairs;
for (int i = 13044; i <= 13367; i++)
materials[i] = Material.GraniteWall;
materials[1596] = Material.Grass;
materials[1596] = Material.ShortGrass;
for (int i = 8; i <= 9; i++)
materials[i] = Material.GrassBlock;
materials[109] = Material.Gravel;

View file

@ -604,7 +604,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
materials[i] = Material.GraniteStairs;
for (int i = 14828; i <= 15151; i++)
materials[i] = Material.GraniteWall;
materials[1954] = Material.Grass;
materials[1954] = Material.ShortGrass;
for (int i = 8; i <= 9; i++)
materials[i] = Material.GrassBlock;
materials[111] = Material.Gravel;

View file

@ -639,7 +639,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
materials[i] = Material.GraniteStairs;
for (int i = 15297; i <= 15620; i++)
materials[i] = Material.GraniteWall;
materials[2001] = Material.Grass;
materials[2001] = Material.ShortGrass;
for (int i = 8; i <= 9; i++)
materials[i] = Material.GrassBlock;
materials[118] = Material.Gravel;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -36,6 +36,10 @@ public enum EntityMetaDataType
Nbt,
Particle,
/// <summary>
/// List of Particle (1.20.6+)
/// </summary>
Particles,
/// <summary>
/// VarInt x3
/// </summary>
VillagerData,
@ -48,6 +52,10 @@ public enum EntityMetaDataType
/// VarInt
/// </summary>
CatVariant,
/// <summary>
/// VarInt (1.20.6+)
/// </summary>
WolfVariant,
FrogVariant,
/// <summary>
/// String + Position
@ -66,6 +74,10 @@ public enum EntityMetaDataType
/// </summary>
SnifferState,
/// <summary>
/// VarInt (1.20.6+)
/// </summary>
ArmadilloState,
/// <summary>
/// Float x3
/// </summary>
Vector3,

View file

@ -22,7 +22,8 @@ public abstract class EntityMetadataPalette
<= Protocol18Handler.MC_1_12_2_Version => new EntityMetadataPalette1122(), // 1.9 - 1.12.2
<= Protocol18Handler.MC_1_19_2_Version => new EntityMetadataPalette1191(), // 1.13 - 1.19.2
<= Protocol18Handler.MC_1_19_3_Version => new EntityMetadataPalette1193(), // 1.19.3
<= Protocol18Handler.MC_1_20_4_Version => new EntityMetadataPalette1194(), // 1.19.4 - 1.20.4 +
< Protocol18Handler.MC_1_20_6_Version => new EntityMetadataPalette1194(), // 1.19.4 - 1.20.4
<= Protocol18Handler.MC_1_21_2_Version => new EntityMetadataPalette1206(), // 1.20.6 - 1.21.2
_ => throw new NotImplementedException()
};
}

View file

@ -0,0 +1,51 @@
using System.Collections.Generic;
namespace MinecraftClient.Mapping.EntityMetadataPalettes;
/// <summary>
/// For 1.20.6+
/// Added PARTICLES (id 18), WOLF_VARIANT (id 23), ARMADILLO_STATE (id 28)
/// compared to 1.19.4 palette.
/// </summary>
public class EntityMetadataPalette1206 : EntityMetadataPalette
{
private readonly Dictionary<int, EntityMetaDataType> entityMetadataMappings = new()
{
{ 0, EntityMetaDataType.Byte },
{ 1, EntityMetaDataType.VarInt },
{ 2, EntityMetaDataType.VarLong },
{ 3, EntityMetaDataType.Float },
{ 4, EntityMetaDataType.String },
{ 5, EntityMetaDataType.Chat },
{ 6, EntityMetaDataType.OptionalChat },
{ 7, EntityMetaDataType.Slot },
{ 8, EntityMetaDataType.Boolean },
{ 9, EntityMetaDataType.Rotation },
{ 10, EntityMetaDataType.Position },
{ 11, EntityMetaDataType.OptionalPosition },
{ 12, EntityMetaDataType.Direction },
{ 13, EntityMetaDataType.OptionalUuid },
{ 14, EntityMetaDataType.BlockId },
{ 15, EntityMetaDataType.OptionalBlockId },
{ 16, EntityMetaDataType.Nbt },
{ 17, EntityMetaDataType.Particle },
{ 18, EntityMetaDataType.Particles },
{ 19, EntityMetaDataType.VillagerData },
{ 20, EntityMetaDataType.OptionalVarInt },
{ 21, EntityMetaDataType.Pose },
{ 22, EntityMetaDataType.CatVariant },
{ 23, EntityMetaDataType.WolfVariant },
{ 24, EntityMetaDataType.FrogVariant },
{ 25, EntityMetaDataType.OptionalGlobalPosition },
{ 26, EntityMetaDataType.PaintingVariant },
{ 27, EntityMetaDataType.SnifferState },
{ 28, EntityMetaDataType.ArmadilloState },
{ 29, EntityMetaDataType.Vector3 },
{ 30, EntityMetaDataType.Quaternion },
};
public override Dictionary<int, EntityMetaDataType> GetEntityMetadataMappingsList()
{
return entityMetadataMappings;
}
}

View file

@ -0,0 +1,148 @@
using System.Collections.Generic;
namespace MinecraftClient.Mapping.EntityPalettes
{
public class EntityPalette1206 : EntityPalette
{
private static readonly Dictionary<int, EntityType> mappings = new();
static EntityPalette1206()
{
mappings[0] = EntityType.Allay;
mappings[1] = EntityType.AreaEffectCloud;
mappings[2] = EntityType.Armadillo;
mappings[3] = EntityType.ArmorStand;
mappings[4] = EntityType.Arrow;
mappings[5] = EntityType.Axolotl;
mappings[6] = EntityType.Bat;
mappings[7] = EntityType.Bee;
mappings[8] = EntityType.Blaze;
mappings[9] = EntityType.BlockDisplay;
mappings[10] = EntityType.Boat;
mappings[11] = EntityType.Bogged;
mappings[12] = EntityType.Breeze;
mappings[13] = EntityType.BreezeWindCharge;
mappings[14] = EntityType.Camel;
mappings[15] = EntityType.Cat;
mappings[16] = EntityType.CaveSpider;
mappings[17] = EntityType.ChestBoat;
mappings[18] = EntityType.ChestMinecart;
mappings[19] = EntityType.Chicken;
mappings[20] = EntityType.Cod;
mappings[21] = EntityType.CommandBlockMinecart;
mappings[22] = EntityType.Cow;
mappings[23] = EntityType.Creeper;
mappings[24] = EntityType.Dolphin;
mappings[25] = EntityType.Donkey;
mappings[26] = EntityType.DragonFireball;
mappings[27] = EntityType.Drowned;
mappings[28] = EntityType.Egg;
mappings[29] = EntityType.ElderGuardian;
mappings[30] = EntityType.EndCrystal;
mappings[31] = EntityType.EnderDragon;
mappings[32] = EntityType.EnderPearl;
mappings[33] = EntityType.Enderman;
mappings[34] = EntityType.Endermite;
mappings[35] = EntityType.Evoker;
mappings[36] = EntityType.EvokerFangs;
mappings[37] = EntityType.ExperienceBottle;
mappings[38] = EntityType.ExperienceOrb;
mappings[39] = EntityType.EyeOfEnder;
mappings[40] = EntityType.FallingBlock;
mappings[62] = EntityType.Fireball;
mappings[41] = EntityType.FireworkRocket;
mappings[129] = EntityType.FishingBobber;
mappings[42] = EntityType.Fox;
mappings[43] = EntityType.Frog;
mappings[44] = EntityType.FurnaceMinecart;
mappings[45] = EntityType.Ghast;
mappings[46] = EntityType.Giant;
mappings[47] = EntityType.GlowItemFrame;
mappings[48] = EntityType.GlowSquid;
mappings[49] = EntityType.Goat;
mappings[50] = EntityType.Guardian;
mappings[51] = EntityType.Hoglin;
mappings[52] = EntityType.HopperMinecart;
mappings[53] = EntityType.Horse;
mappings[54] = EntityType.Husk;
mappings[55] = EntityType.Illusioner;
mappings[56] = EntityType.Interaction;
mappings[57] = EntityType.IronGolem;
mappings[58] = EntityType.Item;
mappings[59] = EntityType.ItemDisplay;
mappings[60] = EntityType.ItemFrame;
mappings[63] = EntityType.LeashKnot;
mappings[64] = EntityType.LightningBolt;
mappings[65] = EntityType.Llama;
mappings[66] = EntityType.LlamaSpit;
mappings[67] = EntityType.MagmaCube;
mappings[68] = EntityType.Marker;
mappings[69] = EntityType.Minecart;
mappings[70] = EntityType.Mooshroom;
mappings[71] = EntityType.Mule;
mappings[72] = EntityType.Ocelot;
mappings[61] = EntityType.OminousItemSpawner;
mappings[73] = EntityType.Painting;
mappings[74] = EntityType.Panda;
mappings[75] = EntityType.Parrot;
mappings[76] = EntityType.Phantom;
mappings[77] = EntityType.Pig;
mappings[78] = EntityType.Piglin;
mappings[79] = EntityType.PiglinBrute;
mappings[80] = EntityType.Pillager;
mappings[128] = EntityType.Player;
mappings[81] = EntityType.PolarBear;
mappings[82] = EntityType.Potion;
mappings[83] = EntityType.Pufferfish;
mappings[84] = EntityType.Rabbit;
mappings[85] = EntityType.Ravager;
mappings[86] = EntityType.Salmon;
mappings[87] = EntityType.Sheep;
mappings[88] = EntityType.Shulker;
mappings[89] = EntityType.ShulkerBullet;
mappings[90] = EntityType.Silverfish;
mappings[91] = EntityType.Skeleton;
mappings[92] = EntityType.SkeletonHorse;
mappings[93] = EntityType.Slime;
mappings[94] = EntityType.SmallFireball;
mappings[95] = EntityType.Sniffer;
mappings[96] = EntityType.SnowGolem;
mappings[97] = EntityType.Snowball;
mappings[98] = EntityType.SpawnerMinecart;
mappings[99] = EntityType.SpectralArrow;
mappings[100] = EntityType.Spider;
mappings[101] = EntityType.Squid;
mappings[102] = EntityType.Stray;
mappings[103] = EntityType.Strider;
mappings[104] = EntityType.Tadpole;
mappings[105] = EntityType.TextDisplay;
mappings[106] = EntityType.Tnt;
mappings[107] = EntityType.TntMinecart;
mappings[108] = EntityType.TraderLlama;
mappings[109] = EntityType.Trident;
mappings[110] = EntityType.TropicalFish;
mappings[111] = EntityType.Turtle;
mappings[112] = EntityType.Vex;
mappings[113] = EntityType.Villager;
mappings[114] = EntityType.Vindicator;
mappings[115] = EntityType.WanderingTrader;
mappings[116] = EntityType.Warden;
mappings[117] = EntityType.WindCharge;
mappings[118] = EntityType.Witch;
mappings[119] = EntityType.Wither;
mappings[120] = EntityType.WitherSkeleton;
mappings[121] = EntityType.WitherSkull;
mappings[122] = EntityType.Wolf;
mappings[123] = EntityType.Zoglin;
mappings[124] = EntityType.Zombie;
mappings[125] = EntityType.ZombieHorse;
mappings[126] = EntityType.ZombieVillager;
mappings[127] = EntityType.ZombifiedPiglin;
}
protected override Dictionary<int, EntityType> GetDict()
{
return mappings;
}
}
}

View file

@ -0,0 +1,168 @@
using System.Collections.Generic;
namespace MinecraftClient.Mapping.EntityPalettes
{
public class EntityPalette1212 : EntityPalette
{
private static readonly Dictionary<int, EntityType> mappings = new();
static EntityPalette1212()
{
mappings[0] = EntityType.AcaciaBoat;
mappings[1] = EntityType.AcaciaChestBoat;
mappings[2] = EntityType.Allay;
mappings[3] = EntityType.AreaEffectCloud;
mappings[4] = EntityType.Armadillo;
mappings[5] = EntityType.ArmorStand;
mappings[6] = EntityType.Arrow;
mappings[7] = EntityType.Axolotl;
mappings[8] = EntityType.BambooChestRaft;
mappings[9] = EntityType.BambooRaft;
mappings[10] = EntityType.Bat;
mappings[11] = EntityType.Bee;
mappings[12] = EntityType.BirchBoat;
mappings[13] = EntityType.BirchChestBoat;
mappings[14] = EntityType.Blaze;
mappings[15] = EntityType.BlockDisplay;
mappings[16] = EntityType.Bogged;
mappings[17] = EntityType.Breeze;
mappings[18] = EntityType.BreezeWindCharge;
mappings[19] = EntityType.Camel;
mappings[20] = EntityType.Cat;
mappings[21] = EntityType.CaveSpider;
mappings[22] = EntityType.CherryBoat;
mappings[23] = EntityType.CherryChestBoat;
mappings[24] = EntityType.ChestMinecart;
mappings[25] = EntityType.Chicken;
mappings[26] = EntityType.Cod;
mappings[27] = EntityType.CommandBlockMinecart;
mappings[28] = EntityType.Cow;
mappings[29] = EntityType.Creaking;
mappings[30] = EntityType.CreakingTransient;
mappings[31] = EntityType.Creeper;
mappings[32] = EntityType.DarkOakBoat;
mappings[33] = EntityType.DarkOakChestBoat;
mappings[34] = EntityType.Dolphin;
mappings[35] = EntityType.Donkey;
mappings[36] = EntityType.DragonFireball;
mappings[37] = EntityType.Drowned;
mappings[38] = EntityType.Egg;
mappings[39] = EntityType.ElderGuardian;
mappings[40] = EntityType.Enderman;
mappings[41] = EntityType.Endermite;
mappings[42] = EntityType.EnderDragon;
mappings[43] = EntityType.EnderPearl;
mappings[44] = EntityType.EndCrystal;
mappings[45] = EntityType.Evoker;
mappings[46] = EntityType.EvokerFangs;
mappings[47] = EntityType.ExperienceBottle;
mappings[48] = EntityType.ExperienceOrb;
mappings[49] = EntityType.EyeOfEnder;
mappings[50] = EntityType.FallingBlock;
mappings[51] = EntityType.Fireball;
mappings[52] = EntityType.FireworkRocket;
mappings[53] = EntityType.Fox;
mappings[54] = EntityType.Frog;
mappings[55] = EntityType.FurnaceMinecart;
mappings[56] = EntityType.Ghast;
mappings[57] = EntityType.Giant;
mappings[58] = EntityType.GlowItemFrame;
mappings[59] = EntityType.GlowSquid;
mappings[60] = EntityType.Goat;
mappings[61] = EntityType.Guardian;
mappings[62] = EntityType.Hoglin;
mappings[63] = EntityType.HopperMinecart;
mappings[64] = EntityType.Horse;
mappings[65] = EntityType.Husk;
mappings[66] = EntityType.Illusioner;
mappings[67] = EntityType.Interaction;
mappings[68] = EntityType.IronGolem;
mappings[69] = EntityType.Item;
mappings[70] = EntityType.ItemDisplay;
mappings[71] = EntityType.ItemFrame;
mappings[72] = EntityType.JungleBoat;
mappings[73] = EntityType.JungleChestBoat;
mappings[74] = EntityType.LeashKnot;
mappings[75] = EntityType.LightningBolt;
mappings[76] = EntityType.Llama;
mappings[77] = EntityType.LlamaSpit;
mappings[78] = EntityType.MagmaCube;
mappings[79] = EntityType.MangroveBoat;
mappings[80] = EntityType.MangroveChestBoat;
mappings[81] = EntityType.Marker;
mappings[82] = EntityType.Minecart;
mappings[83] = EntityType.Mooshroom;
mappings[84] = EntityType.Mule;
mappings[85] = EntityType.OakBoat;
mappings[86] = EntityType.OakChestBoat;
mappings[87] = EntityType.Ocelot;
mappings[88] = EntityType.OminousItemSpawner;
mappings[89] = EntityType.Painting;
mappings[90] = EntityType.PaleOakBoat;
mappings[91] = EntityType.PaleOakChestBoat;
mappings[92] = EntityType.Panda;
mappings[93] = EntityType.Parrot;
mappings[94] = EntityType.Phantom;
mappings[95] = EntityType.Pig;
mappings[96] = EntityType.Piglin;
mappings[97] = EntityType.PiglinBrute;
mappings[98] = EntityType.Pillager;
mappings[99] = EntityType.PolarBear;
mappings[100] = EntityType.Potion;
mappings[101] = EntityType.Pufferfish;
mappings[102] = EntityType.Rabbit;
mappings[103] = EntityType.Ravager;
mappings[104] = EntityType.Salmon;
mappings[105] = EntityType.Sheep;
mappings[106] = EntityType.Shulker;
mappings[107] = EntityType.ShulkerBullet;
mappings[108] = EntityType.Silverfish;
mappings[109] = EntityType.Skeleton;
mappings[110] = EntityType.SkeletonHorse;
mappings[111] = EntityType.Slime;
mappings[112] = EntityType.SmallFireball;
mappings[113] = EntityType.Sniffer;
mappings[114] = EntityType.Snowball;
mappings[115] = EntityType.SnowGolem;
mappings[116] = EntityType.SpawnerMinecart;
mappings[117] = EntityType.SpectralArrow;
mappings[118] = EntityType.Spider;
mappings[119] = EntityType.SpruceBoat;
mappings[120] = EntityType.SpruceChestBoat;
mappings[121] = EntityType.Squid;
mappings[122] = EntityType.Stray;
mappings[123] = EntityType.Strider;
mappings[124] = EntityType.Tadpole;
mappings[125] = EntityType.TextDisplay;
mappings[126] = EntityType.Tnt;
mappings[127] = EntityType.TntMinecart;
mappings[128] = EntityType.TraderLlama;
mappings[129] = EntityType.Trident;
mappings[130] = EntityType.TropicalFish;
mappings[131] = EntityType.Turtle;
mappings[132] = EntityType.Vex;
mappings[133] = EntityType.Villager;
mappings[134] = EntityType.Vindicator;
mappings[135] = EntityType.WanderingTrader;
mappings[136] = EntityType.Warden;
mappings[137] = EntityType.WindCharge;
mappings[138] = EntityType.Witch;
mappings[139] = EntityType.Wither;
mappings[140] = EntityType.WitherSkeleton;
mappings[141] = EntityType.WitherSkull;
mappings[142] = EntityType.Wolf;
mappings[143] = EntityType.Zoglin;
mappings[144] = EntityType.Zombie;
mappings[145] = EntityType.ZombieHorse;
mappings[146] = EntityType.ZombieVillager;
mappings[147] = EntityType.ZombifiedPiglin;
mappings[148] = EntityType.Player;
mappings[149] = EntityType.FishingBobber;
}
protected override Dictionary<int, EntityType> GetDict()
{
return mappings;
}
}
}

View file

@ -1,4 +1,4 @@
namespace MinecraftClient.Mapping
namespace MinecraftClient.Mapping
{
/// <summary>
/// Represents Minecraft Entity Types
@ -14,27 +14,42 @@
/// </remarks>
public enum EntityType
{
AcaciaBoat,
AcaciaChestBoat,
Allay,
AreaEffectCloud,
Armadillo,
ArmorStand,
Arrow,
Axolotl,
BambooChestRaft,
BambooRaft,
Bat,
Bee,
BirchBoat,
BirchChestBoat,
Blaze,
BlockDisplay,
Boat,
Bogged,
Breeze,
BreezeWindCharge,
Camel,
Cat,
CaveSpider,
CherryBoat,
CherryChestBoat,
ChestBoat,
ChestMinecart,
Chicken,
Cod,
CommandBlockMinecart,
Cow,
Creaking,
CreakingTransient,
Creeper,
DarkOakBoat,
DarkOakChestBoat,
Dolphin,
Donkey,
DragonFireball,
@ -74,17 +89,26 @@
Item,
ItemDisplay,
ItemFrame,
JungleBoat,
JungleChestBoat,
LeashKnot,
LightningBolt,
Llama,
LlamaSpit,
MagmaCube,
MangroveBoat,
MangroveChestBoat,
Marker,
Minecart,
Mooshroom,
Mule,
OakBoat,
OakChestBoat,
Ocelot,
OminousItemSpawner,
Painting,
PaleOakBoat,
PaleOakChestBoat,
Panda,
Parrot,
Phantom,
@ -113,6 +137,8 @@
SpawnerMinecart,
SpectralArrow,
Spider,
SpruceBoat,
SpruceChestBoat,
Squid,
Stray,
Strider,

View file

@ -1,4 +1,4 @@
namespace MinecraftClient.Mapping
namespace MinecraftClient.Mapping
{
/// <summary>
/// Represents Minecraft Materials
@ -242,6 +242,7 @@
CrackedStoneBricks,
Crafter,
CraftingTable,
CreakingHeart,
CreeperHead,
CreeperWallHead,
CrimsonButton,
@ -409,7 +410,6 @@
GraniteSlab,
GraniteStairs,
GraniteWall,
Grass, // 1.20.3+ renamed to ShortGrass
GrassBlock,
Gravel,
GrayBanner,
@ -443,6 +443,7 @@
Grindstone,
HangingRoots,
HayBlock,
HeavyCore,
HeavyWeightedPressurePlate,
HoneyBlock,
HoneycombBlock,
@ -662,6 +663,26 @@
OxidizedCutCopperStairs,
PackedIce,
PackedMud,
PaleHangingMoss,
PaleMossBlock,
PaleMossCarpet,
PaleOakButton,
PaleOakDoor,
PaleOakFence,
PaleOakFenceGate,
PaleOakHangingSign,
PaleOakLeaves,
PaleOakLog,
PaleOakPlanks,
PaleOakPressurePlate,
PaleOakSapling,
PaleOakSign,
PaleOakSlab,
PaleOakStairs,
PaleOakTrapdoor,
PaleOakWallHangingSign,
PaleOakWallSign,
PaleOakWood,
PearlescentFroglight,
Peony,
PetrifiedOakSlab,
@ -745,6 +766,7 @@
PottedOakSapling,
PottedOrangeTulip,
PottedOxeyeDaisy,
PottedPaleOakSapling,
PottedPinkTulip,
PottedPoppy,
PottedRedMushroom,
@ -926,6 +948,8 @@
StrippedMangroveWood,
StrippedOakLog,
StrippedOakWood,
StrippedPaleOakLog,
StrippedPaleOakWood,
StrippedSpruceLog,
StrippedSpruceWood,
StrippedWarpedHyphae,
@ -965,6 +989,7 @@
TurtleEgg,
TwistingVines,
TwistingVinesPlant,
Vault,
VerdantFroglight,
Vine,
VoidAir,

View file

@ -365,7 +365,7 @@ namespace MinecraftClient.Mapping
Material.CyanConcretePowder,
Material.Dirt,
Material.Farmland,
Material.Grass,
Material.ShortGrass,
Material.GrassBlock,
Material.DirtPath,
Material.Gravel,
@ -374,6 +374,7 @@ namespace MinecraftClient.Mapping
Material.LightBlueConcretePowder,
Material.LightGrayConcretePowder,
Material.LimeConcretePowder,
Material.TallGrass,
Material.MagentaConcretePowder,
Material.Mycelium,
Material.OrangeConcretePowder,

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@ -23,6 +23,16 @@ namespace MinecraftClient.Mapping
private static readonly Dictionary<string, Dimension> dimensionList = new();
/// <summary>
/// VarInt ID → dimension name mapping, populated from RegistryData in 1.20.6+
/// </summary>
private static Dictionary<int, string> dimensionIdMap = new();
/// <summary>
/// VarInt ID → attribute name mapping, populated from RegistryData (minecraft:attribute) in 1.20.6+
/// </summary>
private static Dictionary<int, string> attributeIdMap = new();
/// <summary>
/// Chunk data parsing progress
/// </summary>
@ -69,6 +79,223 @@ namespace MinecraftClient.Mapping
}
}
public static void LoadDefaultDimensions1206Plus()
{
// TODO: Move this to a JSON file.
var defaultRegistryCodec = new Dictionary<string, object>
{
{ "minecraft:dimension_type", new Dictionary<string, object>
{
{ "value", new object[]
{
new Dictionary<string, object>
{
{ "name", "minecraft:overworld" },
{ "id", 0 },
{ "element", new Dictionary<string, object>
{
{ "piglin_safe", (byte)0 },
{ "natural", 1 },
{ "ambient_light", 0.0 },
{ "monster_spawn_block_light_limit", 0 },
{ "infiniburn", "#minecraft:infiniburn_overworld" },
{ "respawn_anchor_works", 0 },
{ "has_skylight", 1 },
{ "bed_works", 1 },
{ "effects", "minecraft:overworld" },
{ "has_raids", 1 },
{ "logical_height", 384 },
{ "coordinate_scale", 1.0 },
{ "monster_spawn_light_level", new Dictionary<string, object>
{
{ "min_inclusive", 0 },
{ "max_inclusive", 7 },
{ "type", "minecraft:uniform" }
}
},
{ "min_y", -64 },
{ "ultrawarm", 0 },
{ "has_ceiling", 0 },
{ "height", 384 }
}
}
},
new Dictionary<string, object>
{
{ "name", "minecraft:overworld_caves" },
{ "id", 1 },
{ "element", new Dictionary<string, object>
{
{ "piglin_safe", (byte)0 },
{ "natural", 1 },
{ "ambient_light", 0.0 },
{ "monster_spawn_block_light_limit", 0 },
{ "infiniburn", "#minecraft:infiniburn_overworld" },
{ "respawn_anchor_works", 0 },
{ "has_skylight", 1 },
{ "bed_works", 1 },
{ "effects", "minecraft:overworld" },
{ "has_raids", 1 },
{ "logical_height", 384 },
{ "coordinate_scale", 1.0 },
{ "monster_spawn_light_level", new Dictionary<string, object>
{
{ "min_inclusive", 0 },
{ "max_inclusive", 7 },
{ "type", "minecraft:uniform" }
}
},
{ "min_y", -64 },
{ "ultrawarm", 0 },
{ "has_ceiling", 1 },
{ "height", 384 }
}
}
},
new Dictionary<string, object>
{
{ "name", "minecraft:the_end" },
{ "id", 2 },
{ "element", new Dictionary<string, object>
{
{ "piglin_safe", (byte)0 },
{ "natural", 0 },
{ "ambient_light", 0.0 },
{ "monster_spawn_block_light_limit", 0 },
{ "infiniburn", "#minecraft:infiniburn_end" },
{ "respawn_anchor_works", 0 },
{ "has_skylight", 0 },
{ "bed_works", 0 },
{ "effects", "minecraft:the_end" },
{ "fixed_time", 6000 },
{ "has_raids", 1 },
{ "logical_height", 256 },
{ "coordinate_scale", 1.0 },
{ "monster_spawn_light_level", new Dictionary<string, object>
{
{ "min_inclusive", 0 },
{ "max_inclusive", 7 },
{ "type", "minecraft:uniform" }
}
},
{ "min_y", 0 },
{ "ultrawarm", 0 },
{ "has_ceiling", 0 },
{ "height", 256 }
}
}
},
new Dictionary<string, object>
{
{ "name", "minecraft:the_nether" },
{ "id", 3 },
{ "element", new Dictionary<string, object>
{
{ "piglin_safe", (byte)1 },
{ "natural", 0 },
{ "ambient_light", 0.1 },
{ "monster_spawn_block_light_limit", 15 },
{ "infiniburn", "#minecraft:infiniburn_nether" },
{ "respawn_anchor_works", 1 },
{ "has_skylight", 0 },
{ "bed_works", 0 },
{ "effects", "minecraft:the_nether" },
{ "fixed_time", 18000 },
{ "has_raids", 0 },
{ "logical_height", 128 },
{ "coordinate_scale", 8.0 },
{ "monster_spawn_light_level", 7 },
{ "min_y", 0 },
{ "ultrawarm", 1 },
{ "has_ceiling", 1 },
{ "height", 256 }
}
}
}
}
}
}
}
};
StoreDimensionList(defaultRegistryCodec);
}
public static void SetDimensionIdMap(Dictionary<int, string> idMap)
{
dimensionIdMap = idMap;
}
public static string GetDimensionNameById(int id)
{
return dimensionIdMap.TryGetValue(id, out var name) ? name : "minecraft:overworld";
}
public static bool HasAnyDimension()
{
return dimensionList.Count > 0;
}
public static void SetAttributeIdMap(Dictionary<int, string> idMap)
{
attributeIdMap = idMap;
}
/// <summary>
/// Get attribute name by its registry VarInt ID. Returns null if the ID is unknown.
/// When KnownDataPacks negotiation tells the server we already have vanilla data,
/// the server skips sending the attribute registry. In that case we fall back to
/// the built-in vanilla 1.20.6 attribute order (22 entries).
/// </summary>
public static string? GetAttributeNameById(int id)
{
if (attributeIdMap.Count == 0)
LoadDefaultAttributes();
return attributeIdMap.TryGetValue(id, out var name) ? name : null;
}
private static void LoadDefaultAttributes()
{
// Fallback for when the server doesn't send attribute registry via RegistryData.
// Matches 1.21.1 Attributes.java registration order.
// For 1.20.6+ servers, SetAttributeIdMap() overrides this with the actual registry.
attributeIdMap = new Dictionary<int, string>
{
{ 0, "generic.armor" },
{ 1, "generic.armor_toughness" },
{ 2, "generic.attack_damage" },
{ 3, "generic.attack_knockback" },
{ 4, "generic.attack_speed" },
{ 5, "player.block_break_speed" },
{ 6, "player.block_interaction_range" },
{ 7, "generic.burning_time" },
{ 8, "generic.explosion_knockback_resistance" },
{ 9, "player.entity_interaction_range" },
{ 10, "generic.fall_damage_multiplier" },
{ 11, "generic.flying_speed" },
{ 12, "generic.follow_range" },
{ 13, "generic.gravity" },
{ 14, "generic.jump_strength" },
{ 15, "generic.knockback_resistance" },
{ 16, "generic.luck" },
{ 17, "generic.max_absorption" },
{ 18, "generic.max_health" },
{ 19, "player.mining_efficiency" },
{ 20, "generic.movement_efficiency" },
{ 21, "generic.movement_speed" },
{ 22, "generic.oxygen_bonus" },
{ 23, "generic.safe_fall_distance" },
{ 24, "generic.scale" },
{ 25, "player.sneaking_speed" },
{ 26, "zombie.spawn_reinforcements" },
{ 27, "generic.step_height" },
{ 28, "player.submerged_mining_speed" },
{ 29, "player.sweeping_damage_ratio" },
{ 30, "generic.water_movement_efficiency" }
};
}
/// <summary>
/// Store one dimension - Directly used in 1.16.2 to 1.18.2
/// </summary>
@ -114,7 +341,6 @@ namespace MinecraftClient.Mapping
/// <summary>
/// Get current dimension
/// </summary>

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
@ -119,6 +119,9 @@ namespace MinecraftClient
// ChatBot OnNetworkPacket event
private bool networkPacketCaptureEnabled = false;
// Cookies
private Dictionary<string, byte[]> Cookies { get; set; } = new();
public int GetServerPort() { return port; }
public string GetServerHost() { return host; }
@ -144,9 +147,13 @@ namespace MinecraftClient
public ILogger GetLogger() { return Log; }
public int GetPlayerEntityID() { return playerEntityID; }
public List<ChatBot> GetLoadedChatBots() { return new List<ChatBot>(bots); }
public void GetCookie(string key, out byte[]? data) => Cookies.TryGetValue(key, out data);
public void SetCookie(string key, byte[] data) => Cookies[key] = data;
public void DeleteCookie(string key) => Cookies.Remove(key, out var data);
readonly TcpClient client;
readonly IMinecraftCom handler;
TcpClient client;
IMinecraftCom handler;
SessionToken _sessionToken;
CancellationTokenSource? cmdprompt = null;
Tuple<Thread, CancellationTokenSource>? timeoutdetector = null;
@ -182,6 +189,7 @@ namespace MinecraftClient
this.port = port;
this.protocolversion = protocolversion;
this.playerKeyPair = playerKeyPair;
_sessionToken = session;
Log = Settings.Config.Logging.LogToFile
? new FileLogLogger(Config.AppVar.ExpandVars(Settings.Config.Logging.LogFile), Settings.Config.Logging.PrependTimestamp)
@ -317,6 +325,77 @@ namespace MinecraftClient
}
}
}
public void Transfer(string newHost, int newPort)
{
try
{
Log.Info($"Initiating a transfer to: {host}:{port}");
// Unload bots
UnloadAllBots();
bots.Clear();
// Close existing connection
client.Close();
// Establish new connection
client = ProxyHandler.NewTcpClient(newHost, newPort);
client.ReceiveBufferSize = 1024 * 1024;
client.ReceiveTimeout = Config.Main.Advanced.TcpTimeout * 1000;
// Reinitialize the protocol handler
handler = Protocol.ProtocolHandler.GetProtocolHandler(client, protocolversion, null, this);
Log.Info($"Connected to {host}:{port}");
// Retry login process
if (handler.Login(playerKeyPair, _sessionToken))
{
foreach (var bot in botsOnHold)
BotLoad(bot, false);
botsOnHold.Clear();
Log.Info("Successfully transferred connection and logged in.");
cmdprompt = new CancellationTokenSource();
ConsoleInteractive.ConsoleReader.BeginReadThread();
ConsoleInteractive.ConsoleReader.MessageReceived += ConsoleReaderOnMessageReceived;
ConsoleInteractive.ConsoleReader.OnInputChange += ConsoleIO.AutocompleteHandler;
}
else
{
Log.Error("Failed to login to the new host.");
throw new Exception("Login failed after transfer.");
}
}
catch (Exception ex)
{
Log.Error($"Transfer to {newHost}:{newPort} failed: {ex.Message}");
// Handle reconnection attempts
if (timeoutdetector != null)
{
timeoutdetector.Item2.Cancel();
timeoutdetector = null;
}
if (ReconnectionAttemptsLeft > 0)
{
Log.Info($"Reconnecting... Attempts left: {ReconnectionAttemptsLeft}");
Thread.Sleep(5000);
ReconnectionAttemptsLeft--;
Program.Restart();
}
else if (InternalConfig.InteractiveMode)
{
ConsoleInteractive.ConsoleReader.StopReadThread();
ConsoleInteractive.ConsoleReader.MessageReceived -= ConsoleReaderOnMessageReceived;
ConsoleInteractive.ConsoleReader.OnInputChange -= ConsoleIO.AutocompleteHandler;
Program.HandleFailure();
}
throw new Exception("Transfer failed and reconnection attempts exhausted.");
}
}
/// <summary>
/// Register bots
@ -346,8 +425,8 @@ namespace MinecraftClient
if (Config.ChatBot.ScriptScheduler.Enabled) { BotLoad(new ScriptScheduler()); }
if (Config.ChatBot.TelegramBridge.Enabled) { BotLoad(new TelegramBridge()); }
if (Config.ChatBot.ItemsCollector.Enabled) { BotLoad(new ItemsCollector()); }
//Add your ChatBot here by uncommenting and adapting
//BotLoad(new ChatBots.YourBot());
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MCC_FILE_INPUT")))
BotLoad(new FileInputBot());
}
/// <summary>
@ -1470,7 +1549,7 @@ namespace MinecraftClient
/// <param name="changedSlots">Record changes</param>
private static void StoreInNewSlot(Container inventory, Item item, int slotId, int newSlotId, List<Tuple<short, Item?>> changedSlots)
{
Item newItem = new(item.Type, item.Count, item.NBT);
Item newItem = item.CloneWithCount(item.Count);
inventory.Items[newSlotId] = newItem;
inventory.Items.Remove(slotId);
@ -1593,7 +1672,7 @@ namespace MinecraftClient
{
// Drop 1 item count from cursor
Item itemTmp = playerInventory.Items[-1];
Item itemClone = new(itemTmp.Type, 1, itemTmp.NBT);
Item itemClone = itemTmp.CloneWithCount(1);
inventory.Items[slotId] = itemClone;
playerInventory.Items[-1].Count--;
}
@ -1622,14 +1701,14 @@ namespace MinecraftClient
{
// Can be evenly divided
Item itemTmp = inventory.Items[slotId];
playerInventory.Items[-1] = new Item(itemTmp.Type, itemTmp.Count / 2, itemTmp.NBT);
playerInventory.Items[-1] = itemTmp.CloneWithCount(itemTmp.Count / 2);
inventory.Items[slotId].Count = itemTmp.Count / 2;
}
else
{
// Cannot be evenly divided. item count on cursor is always larger than item on inventory
Item itemTmp = inventory.Items[slotId];
playerInventory.Items[-1] = new Item(itemTmp.Type, (itemTmp.Count + 1) / 2, itemTmp.NBT);
playerInventory.Items[-1] = itemTmp.CloneWithCount((itemTmp.Count + 1) / 2);
inventory.Items[slotId].Count = (itemTmp.Count - 1) / 2;
}
}
@ -2313,10 +2392,19 @@ namespace MinecraftClient
/// </summary>
/// <param name="location">Location to place block to</param>
/// <param name="blockFace">Block face (e.g. Direction.Down when clicking on the block below to place this block)</param>
/// <param name="lookAtBlock">Also look at the block before interacting</param>
/// <returns>TRUE if successfully placed</returns>
public bool PlaceBlock(Location location, Direction blockFace, Hand hand = Hand.MainHand)
public bool PlaceBlock(Location location, Direction blockFace, Hand hand = Hand.MainHand, bool lookAtBlock = false)
{
return InvokeOnMainThread(() => handler.SendPlayerBlockPlacement((int)hand, location, blockFace, sequenceId++));
return InvokeOnMainThread(() =>
{
if (lookAtBlock)
{
UpdateLocation(GetCurrentLocation(), location.ToCenter());
handler.SendLocationUpdate(GetCurrentLocation(), Movement.IsOnGround(world, GetCurrentLocation()), _yaw, _pitch);
}
return handler.SendPlayerBlockPlacement((int)hand, location, blockFace, sequenceId++);
});
}
@ -2877,27 +2965,27 @@ namespace MinecraftClient
// We got the last property for enchantment
if (propertyId == 9 && propertyValue != -1)
{
short topEnchantmentLevelRequirement = inventory.Properties[0];
short middleEnchantmentLevelRequirement = inventory.Properties[1];
short bottomEnchantmentLevelRequirement = inventory.Properties[2];
var topEnchantmentLevelRequirement = inventory.Properties[0];
var middleEnchantmentLevelRequirement = inventory.Properties[1];
var bottomEnchantmentLevelRequirement = inventory.Properties[2];
Enchantment topEnchantment = EnchantmentMapping.GetEnchantmentById(
var topEnchantment = EnchantmentMapping.GetEnchantmentById(
GetProtocolVersion(),
inventory.Properties[4]);
Enchantment middleEnchantment = EnchantmentMapping.GetEnchantmentById(
var middleEnchantment = EnchantmentMapping.GetEnchantmentById(
GetProtocolVersion(),
inventory.Properties[5]);
Enchantment bottomEnchantment = EnchantmentMapping.GetEnchantmentById(
var bottomEnchantment = EnchantmentMapping.GetEnchantmentById(
GetProtocolVersion(),
inventory.Properties[6]);
short topEnchantmentLevel = inventory.Properties[7];
short middleEnchantmentLevel = inventory.Properties[8];
short bottomEnchantmentLevel = inventory.Properties[9];
var topEnchantmentLevel = inventory.Properties[7];
var middleEnchantmentLevel = inventory.Properties[8];
var bottomEnchantmentLevel = inventory.Properties[9];
StringBuilder sb = new();
var sb = new StringBuilder();
sb.AppendLine(Translations.Enchantment_enchantments_available + ":");

View file

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<PublishUrl>publish\</PublishUrl>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
@ -34,6 +34,7 @@
<PackageReference Include="DynamicExpresso.Core" Version="2.13.0" />
<PackageReference Include="FuzzySharp" Version="2.0.2" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="13.3.0" />
<PackageReference Include="MessagePack" Version="3.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@ -17,7 +17,6 @@ using MinecraftClient.Protocol.Session;
using MinecraftClient.Scripting;
using MinecraftClient.WinAPI;
using Sentry;
using Tomlet;
using static MinecraftClient.Settings;
using static MinecraftClient.Settings.ConsoleConfigHealper.ConsoleConfig;
using static MinecraftClient.Settings.MainConfigHelper.MainConfig.AdvancedConfig;
@ -47,7 +46,7 @@ namespace MinecraftClient
public const string Version = MCHighestVersion;
public const string MCLowestVersion = "1.4.6";
public const string MCHighestVersion = "1.20.4";
public const string MCHighestVersion = "1.21.2";
public static readonly string? BuildInfo = null;
private static Tuple<Thread, CancellationTokenSource>? offlinePrompt = null;
@ -360,7 +359,7 @@ namespace MinecraftClient
ConsoleColorModeType.vt100_8bit)).Append(i);
}
sb.Append(ColorHelper.GetResetEscapeCode()).Append(']');
ConsoleIO.WriteLine(string.Format(Translations.debug_color_test, sb.ToString()));
ConsoleIO.WriteLine(string.Format(Translations.debug_color_test, sb));
}
{ // Test 24 bit color
StringBuilder sb = new();
@ -374,7 +373,7 @@ namespace MinecraftClient
ConsoleColorModeType.vt100_24bit)).Append(i);
}
sb.Append(ColorHelper.GetResetEscapeCode()).Append(']');
ConsoleIO.WriteLine(string.Format(Translations.debug_color_test, sb.ToString()));
ConsoleIO.WriteLine(string.Format(Translations.debug_color_test, sb));
}
}
@ -387,7 +386,7 @@ namespace MinecraftClient
}
// Setup exit cleaning code
ExitCleanUp.Add(() => { DoExit(0); });
ExitCleanUp.Add(() => { DoExit(); });
//Asking the user to type in missing data such as Username and Password
bool useBrowser = Config.Main.General.AccountType == LoginType.microsoft && Config.Main.General.Method == LoginMethod.browser;
@ -531,10 +530,10 @@ namespace MinecraftClient
worldId = availableWorlds[worldIndex];
if (availableWorlds.Contains(worldId))
{
string RealmsAddress = ProtocolHandler.GetRealmsWorldServerAddress(worldId, InternalConfig.Username, session.PlayerID, session.ID);
if (RealmsAddress != "")
string realmsAddress = ProtocolHandler.GetRealmsWorldServerAddress(worldId, InternalConfig.Username, session.PlayerID, session.ID);
if (realmsAddress != "")
{
addressInput = RealmsAddress;
addressInput = realmsAddress;
isRealms = true;
InternalConfig.MinecraftVersion = MCHighestVersion;
}
@ -552,7 +551,7 @@ namespace MinecraftClient
}
else
{
HandleFailure(Translations.error_realms_disabled, false, null);
HandleFailure(Translations.error_realms_disabled);
return;
}
}
@ -565,7 +564,7 @@ namespace MinecraftClient
if (InternalConfig.MinecraftVersion != "" && Settings.ToLowerIfNeed(InternalConfig.MinecraftVersion) != "auto")
{
protocolversion = Protocol.ProtocolHandler.MCVer2ProtocolVersion(InternalConfig.MinecraftVersion);
protocolversion = ProtocolHandler.MCVer2ProtocolVersion(InternalConfig.MinecraftVersion);
if (protocolversion != 0)
ConsoleIO.WriteLineFormatted(string.Format(Translations.mcc_use_version, InternalConfig.MinecraftVersion, protocolversion));
@ -589,7 +588,7 @@ namespace MinecraftClient
ConsoleIO.WriteLine(Translations.mcc_retrieve);
if (!ProtocolHandler.GetServerInfo(InternalConfig.ServerIP, InternalConfig.ServerPort, ref protocolversion, ref forgeInfo))
{
HandleFailure(Translations.error_ping, true, ChatBots.AutoRelog.DisconnectReason.ConnectionLost);
HandleFailure(Translations.error_ping, true, ChatBot.DisconnectReason.ConnectionLost);
return;
}
}
@ -637,7 +636,7 @@ namespace MinecraftClient
}
else
{
HandleFailure(Translations.error_forgeforce, true, ChatBots.AutoRelog.DisconnectReason.ConnectionLost);
HandleFailure(Translations.error_forgeforce, true, ChatBot.DisconnectReason.ConnectionLost);
return;
}
}
@ -677,8 +676,7 @@ namespace MinecraftClient
else
{
string failureMessage = Translations.error_login;
string failureReason = string.Empty;
failureReason = result switch
string failureReason = result switch
{
#pragma warning disable format // @formatter:off
ProtocolHandler.LoginResult.AccountMigrated => Translations.error_login_migrated,
@ -719,6 +717,7 @@ namespace MinecraftClient
/// Disconnect the current client from the server and restart it
/// </summary>
/// <param name="delaySeconds">Optional delay, in seconds, before restarting</param>
/// <param name="keepAccountAndServerSettings">Optional, keep account and server settings</param>
public static void Restart(int delaySeconds = 0, bool keepAccountAndServerSettings = false)
{
ConsoleInteractive.ConsoleReader.StopReadThread();
@ -739,7 +738,7 @@ namespace MinecraftClient
public static void DoExit(int exitcode = 0)
{
WriteBackSettings(true);
WriteBackSettings();
ConsoleInteractive.ConsoleSuggestion.ClearSuggestions();
ConsoleIO.WriteLineFormatted("§a" + string.Format(Translations.config_saving, settingsIniPath));
@ -754,7 +753,7 @@ namespace MinecraftClient
/// </summary>
public static void Exit(int exitcode = 0)
{
new Thread(new ThreadStart(() => { DoExit(exitcode); })).Start();
new Thread(() => { DoExit(exitcode); }).Start();
}
/// <summary>
@ -764,13 +763,15 @@ namespace MinecraftClient
/// <param name="errorMessage">Error message to display and optionally pass to AutoRelog bot</param>
/// <param name="versionError">Specify if the error is related to an incompatible or unkown server version</param>
/// <param name="disconnectReason">If set, the error message will be processed by the AutoRelog bot</param>
public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBots.AutoRelog.DisconnectReason? disconnectReason = null)
public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBot.DisconnectReason? disconnectReason = null)
{
if (!String.IsNullOrEmpty(errorMessage))
{
ConsoleIO.Reset();
while (Console.KeyAvailable)
Console.ReadKey(true);
try {
while (Console.KeyAvailable)
Console.ReadKey(true);
} catch { }
ConsoleIO.WriteLine(errorMessage);
if (disconnectReason.HasValue)

View file

@ -2,16 +2,23 @@ namespace MinecraftClient.Protocol.Handlers;
public enum ConfigurationPacketTypesIn
{
PluginMessage,
CookieRequest,
CustomReportDetails,
Disconnect,
FeatureFlags,
FinishConfiguration,
KeepAlive,
KnownDataPacks,
Ping,
PluginMessage,
RegistryData,
ResourcePack,
RemoveResourcePack,
FeatureFlags,
ResetChat,
ResourcePack,
ServerLinks,
StoreCookie,
Transfer,
UpdateTags,
Unknown
}
}

View file

@ -8,6 +8,8 @@ public enum ConfigurationPacketTypesOut
KeepAlive,
Pong,
ResourcePackResponse,
CookieResponse,
KnownDataPacks,
Unknown
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
@ -6,6 +6,8 @@ using MinecraftClient.Inventory;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Mapping;
using MinecraftClient.Mapping.EntityPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
using MinecraftClient.Protocol.Message;
namespace MinecraftClient.Protocol.Handlers
@ -13,7 +15,7 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary>
/// Handle data types encoding / decoding
/// </summary>
class DataTypes
public class DataTypes
{
/// <summary>
/// Protocol version for adjusting data types
@ -419,37 +421,90 @@ namespace MinecraftClient.Protocol.Handlers
/// <returns>The item that was read or NULL for an empty slot</returns>
public Item? ReadNextItemSlot(Queue<byte> cache, ItemPalette itemPalette)
{
// MC 1.13.2 and greater
if (protocolversion >= Protocol18Handler.MC_1_13_Version)
var itemId = -1;
var itemCount = 0;
var nbt = null as Dictionary<string, object>;
var item = null as Item;
var strcturedComponentsToAdd = new List<StructuredComponent>();
switch (protocolversion)
{
var itemPresent = ReadNextBool(cache);
// MC 1.13.2 and greater
case >= Protocol18Handler.MC_1_20_6_Version:
itemCount = ReadNextVarInt(cache);
if (!itemPresent)
return null;
if (itemCount <= 0) return null;
itemId = ReadNextVarInt(cache);
item = new Item(itemPalette.FromId(itemId), itemCount, null);
var numberOfComponentsToAdd = ReadNextVarInt(cache);
var numberofComponentsToRemove = ReadNextVarInt(cache);
var itemId = ReadNextVarInt(cache);
for (var i = 0; i < numberOfComponentsToAdd; i++)
{
var componentTypeId = ReadNextVarInt(cache);
if (itemId == -1)
return null;
var strcuturedComponentHandler = new StructuredComponentsHandler(protocolversion, this, itemPalette);
strcturedComponentsToAdd.Add(strcuturedComponentHandler.Parse(componentTypeId, cache));
}
var type = itemPalette.FromId(itemId);
var itemCount = ReadNextByte(cache);
var nbt = ReadNextNbt(cache);
return new Item(type, itemCount, nbt);
for (var i = 0; i < numberofComponentsToRemove; i++)
ReadNextVarInt(cache);
if (strcturedComponentsToAdd.Count > 0)
item.Components = strcturedComponentsToAdd;
return item;
case >= Protocol18Handler.MC_1_13_Version:
{
var itemPresent = ReadNextBool(cache);
if (!itemPresent)
return null;
itemId = ReadNextVarInt(cache);
if (itemId == -1)
return null;
var type = itemPalette.FromId(itemId);
itemCount = ReadNextByte(cache);
nbt = ReadNextNbt(cache);
return new Item(type, itemCount, nbt);
}
default:
{
itemId = ReadNextShort(cache);
if (itemId == -1)
return null;
itemCount = ReadNextByte(cache);
var data = ReadNextShort(cache);
nbt = ReadNextNbt(cache);
// For 1.8 - 1.12.2 we combine Item Id and Item Data/Damage to a single value using: (id << 16) | data
return new Item(itemPalette.FromId((itemId << 16) | (ushort)data), itemCount, data, nbt);
}
}
else
}
private void ReadNextDetail(Queue<byte> cache)
{
var potionEffectId = ReadNextVarInt(cache);
// Details
var potionEffectAmplifier = ReadNextVarInt(cache);
var duration = ReadNextVarInt(cache); // -1 for infinite
var ambient = ReadNextBool(cache);
var showParticles = ReadNextBool(cache);
var showIcon = ReadNextBool(cache);
var hasHiddenEffect = ReadNextBool(cache);
if (hasHiddenEffect)
{
var itemId = ReadNextShort(cache);
if (itemId == -1)
return null;
var itemCount = ReadNextByte(cache);
var data = ReadNextShort(cache);
var nbt = ReadNextNbt(cache);
// For 1.8 - 1.12.2 we combine Item Id and Item Data/Damage to a single value using: (id << 16) | data
return new Item(itemPalette.FromId((itemId << 16) | (ushort)data), itemCount, data, nbt);
ReadNextDetail(cache);
}
}
@ -674,188 +729,208 @@ namespace MinecraftClient.Protocol.Handlers
public Dictionary<int, object?> ReadNextMetadata(Queue<byte> cache, ItemPalette itemPalette,
EntityMetadataPalette metadataPalette)
{
Dictionary<int, object?> data = new();
byte key = ReadNextByte(cache);
byte terminteValue = protocolversion <= Protocol18Handler.MC_1_8_Version
? (byte)0x7f // 1.8 (https://wiki.vg/index.php?title=Entity_metadata&oldid=6220#Entity_Metadata_Format)
: (byte)0xff; // 1.9+
while (key != terminteValue)
try
{
int typeId = protocolversion <= Protocol18Handler.MC_1_8_Version
? key >> 5 // 1.8
: ReadNextVarInt(cache); // 1.9+
Dictionary<int, object?> data = new();
byte key = ReadNextByte(cache);
byte terminteValue = protocolversion <= Protocol18Handler.MC_1_8_Version
? (byte)0x7f // 1.8 (https://wiki.vg/index.php?title=Entity_metadata&oldid=6220#Entity_Metadata_Format)
: (byte)0xff; // 1.9+
EntityMetaDataType type;
try
while (key != terminteValue)
{
type = metadataPalette.GetDataType(typeId);
}
catch (KeyNotFoundException)
{
throw new System.IO.InvalidDataException("Unknown Metadata Type ID " + typeId +
". Is this up to date for new MC Version?");
}
int typeId = protocolversion <= Protocol18Handler.MC_1_8_Version
? key >> 5 // 1.8
: ReadNextVarInt(cache); // 1.9+
if (protocolversion <= Protocol18Handler.MC_1_8_Version)
key = (byte)(key & 0x1f);
EntityMetaDataType type;
try
{
type = metadataPalette.GetDataType(typeId);
}
catch (KeyNotFoundException)
{
throw new System.IO.InvalidDataException("Unknown Metadata Type ID " + typeId +
". Is this up to date for new MC Version?");
}
// Value's data type is depended on Type
object? value = null;
if (protocolversion <= Protocol18Handler.MC_1_8_Version)
key = (byte)(key & 0x1f);
switch (type)
{
case EntityMetaDataType.Short: // 1.8 only
value = ReadNextShort(cache);
break;
case EntityMetaDataType.Int: // 1.8 only
value = ReadNextInt(cache);
break;
case EntityMetaDataType.Vector3Int: // 1.8 only
value = new List<int>()
{
ReadNextInt(cache),
ReadNextInt(cache),
ReadNextInt(cache),
};
break;
case EntityMetaDataType.Byte: // byte
value = ReadNextByte(cache);
break;
case EntityMetaDataType.VarInt: // VarInt
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.VarLong: // Long
value = ReadNextVarLong(cache);
break;
case EntityMetaDataType.Float: // Float
value = ReadNextFloat(cache);
break;
case EntityMetaDataType.String: // String
value = ReadNextString(cache);
break;
case EntityMetaDataType.Chat: // Chat
value = ReadNextChat(cache);
break;
case EntityMetaDataType.OptionalChat: // Optional Chat
if (ReadNextBool(cache))
value = ReadNextChat(cache);
break;
case EntityMetaDataType.Slot: // Slot
value = ReadNextItemSlot(cache, itemPalette);
break;
case EntityMetaDataType.Boolean: // Boolean
value = ReadNextBool(cache);
break;
case EntityMetaDataType.Rotation: // Rotation (3x floats)
value = new List<float>
{
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache)
};
break;
case EntityMetaDataType.Position: // Position
value = ReadNextLocation(cache);
break;
case EntityMetaDataType.OptionalPosition: // Optional Position
if (ReadNextBool(cache))
{
value = ReadNextLocation(cache);
}
// Value's data type is depended on Type
object? value = null;
break;
case EntityMetaDataType.Direction: // Direction (VarInt)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.OptionalUuid: // Optional UUID
if (ReadNextBool(cache))
{
value = ReadNextUUID(cache);
}
break;
case EntityMetaDataType.BlockId: // BlockID (VarInt)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.OptionalBlockId: // Optional BlockID (VarInt)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.Nbt: // NBT
value = ReadNextNbt(cache);
break;
case EntityMetaDataType.Particle: // Particle
// Skip data only, not used
ReadParticleData(cache, itemPalette);
break;
case EntityMetaDataType.VillagerData: // Villager Data (3x VarInt)
value = new List<int>
{
ReadNextVarInt(cache),
ReadNextVarInt(cache),
ReadNextVarInt(cache)
};
break;
case EntityMetaDataType.OptionalVarInt: // Optional VarInt
if (ReadNextBool(cache))
{
switch (type)
{
case EntityMetaDataType.Short: // 1.8 only
value = ReadNextShort(cache);
break;
case EntityMetaDataType.Int: // 1.8 only
value = ReadNextInt(cache);
break;
case EntityMetaDataType.Vector3Int: // 1.8 only
value = new List<int>()
{
ReadNextInt(cache),
ReadNextInt(cache),
ReadNextInt(cache),
};
break;
case EntityMetaDataType.Byte: // byte
value = ReadNextByte(cache);
break;
case EntityMetaDataType.VarInt: // VarInt
value = ReadNextVarInt(cache);
}
break;
case EntityMetaDataType.VarLong: // Long
value = ReadNextVarLong(cache);
break;
case EntityMetaDataType.Float: // Float
value = ReadNextFloat(cache);
break;
case EntityMetaDataType.String: // String
value = ReadNextString(cache);
break;
case EntityMetaDataType.Chat: // Chat
value = ReadNextChat(cache);
break;
case EntityMetaDataType.OptionalChat: // Optional Chat
if (ReadNextBool(cache))
value = ReadNextChat(cache);
break;
case EntityMetaDataType.Slot: // Slot
value = ReadNextItemSlot(cache, itemPalette);
break;
case EntityMetaDataType.Boolean: // Boolean
value = ReadNextBool(cache);
break;
case EntityMetaDataType.Rotation: // Rotation (3x floats)
value = new List<float>
{
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache)
};
break;
case EntityMetaDataType.Position: // Position
value = ReadNextLocation(cache);
break;
case EntityMetaDataType.OptionalPosition: // Optional Position
if (ReadNextBool(cache))
{
value = ReadNextLocation(cache);
}
break;
case EntityMetaDataType.Pose: // Pose
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.CatVariant: // Cat Variant
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.FrogVariant: // Frog Varint
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.GlobalPosition: // GlobalPos
// Dimension and blockPos, currently not in use
value = new Tuple<string, Location>(ReadNextString(cache), ReadNextLocation(cache));
break;
case EntityMetaDataType.OptionalGlobalPosition:
// FIXME: wiki.vg is bool + string + location
// but minecraft-data is bool + string
if (ReadNextBool(cache))
{
break;
case EntityMetaDataType.Direction: // Direction (VarInt)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.OptionalUuid: // Optional UUID
if (ReadNextBool(cache))
{
value = ReadNextUUID(cache);
}
break;
case EntityMetaDataType.BlockId: // BlockID (VarInt)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.OptionalBlockId: // Optional BlockID (VarInt)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.Nbt: // NBT
value = ReadNextNbt(cache);
break;
case EntityMetaDataType.Particle: // Particle
ReadParticleData(cache, itemPalette);
break;
case EntityMetaDataType.Particles: // List of Particle (1.20.6+)
int particleCount = ReadNextVarInt(cache);
for (int i = 0; i < particleCount; i++)
ReadParticleData(cache, itemPalette);
break;
case EntityMetaDataType.VillagerData: // Villager Data (3x VarInt)
value = new List<int>
{
ReadNextVarInt(cache),
ReadNextVarInt(cache),
ReadNextVarInt(cache)
};
break;
case EntityMetaDataType.OptionalVarInt: // Optional VarInt
if (protocolversion < Protocol18Handler.MC_1_20_6_Version)
{
if (ReadNextBool(cache))
value = ReadNextVarInt(cache);
}
else value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.Pose: // Pose
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.CatVariant: // Cat Variant
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.WolfVariant: // Wolf Variant (1.20.6+)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.FrogVariant: // Frog Variant
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.GlobalPosition: // GlobalPos
// Dimension and blockPos, currently not in use
value = new Tuple<string, Location>(ReadNextString(cache), ReadNextLocation(cache));
}
break;
case EntityMetaDataType.OptionalGlobalPosition:
// FIXME: wiki.vg is bool + string + location
// but minecraft-data is bool + string
if (ReadNextBool(cache))
{
// Dimension and blockPos, currently not in use
value = new Tuple<string, Location>(ReadNextString(cache), ReadNextLocation(cache));
}
break;
case EntityMetaDataType.PaintingVariant: // Painting Variant
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.SnifferState: // Sniffer state
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.Vector3: // Vector 3f
value = new List<float>
{
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache)
};
break;
case EntityMetaDataType.Quaternion: // Quaternion
value = new List<float>
{
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache)
};
break;
break;
case EntityMetaDataType.PaintingVariant: // Painting Variant
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.SnifferState: // Sniffer state
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.ArmadilloState: // Armadillo state (1.20.6+)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.Vector3: // Vector 3f
value = new List<float>
{
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache)
};
break;
case EntityMetaDataType.Quaternion: // Quaternion
value = new List<float>
{
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache)
};
break;
}
data[key] = value;
key = ReadNextByte(cache);
}
data[key] = value;
key = ReadNextByte(cache);
return data;
}
catch(Exception ex)
{
return new Dictionary<int, object?>();
}
return data;
}
/// <summary>
@ -879,15 +954,21 @@ namespace MinecraftClient.Protocol.Handlers
switch (particleId)
{
case 1: // 1.20.6+
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
ReadNextVarInt(cache); // BlockState (minecraft:block)
break;
case 2:
// 1.18 +
// 1.18
if (protocolversion > Protocol18Handler.MC_1_17_1_Version)
ReadNextVarInt(cache); // Block state (minecraft:block)
ReadNextVarInt(cache); // Block state (minecraft:block before 1.20.6, minecraft:block_marker in 1.20.6+)
break;
case 3:
if (protocolversion is < Protocol18Handler.MC_1_17_Version or > Protocol18Handler.MC_1_17_1_Version)
if (protocolversion is (< Protocol18Handler.MC_1_17_Version or > Protocol18Handler.MC_1_17_1_Version)
and < Protocol18Handler.MC_1_20_6_Version)
ReadNextVarInt(
cache); // Block State (minecraft:block before 1.18, minecraft:block_marker after 1.18)
cache); // Block State (minecraft:block before 1.18, minecraft:block_marker after 1.18 up to 1.20.6)
break;
case 4:
if (protocolversion is Protocol18Handler.MC_1_17_Version or Protocol18Handler.MC_1_17_1_Version)
@ -898,11 +979,24 @@ namespace MinecraftClient.Protocol.Handlers
if (protocolversion < Protocol18Handler.MC_1_15_Version)
ReadDustParticle(cache);
break;
case 13:
// 1.20.6+ - minecraft:dust
ReadDustParticle(cache);
break;
case 14:
// 1.15 - 1.16.5 and 1.18 - 1.19.4
if (protocolversion is >= Protocol18Handler.MC_1_15_Version and < Protocol18Handler.MC_1_17_Version
or > Protocol18Handler.MC_1_17_1_Version)
ReadDustParticle(cache);
switch (protocolversion)
{
// 1.15 - 1.16.5 and 1.18 - 1.20.4
case >= Protocol18Handler.MC_1_15_Version and < Protocol18Handler.MC_1_17_Version
or > Protocol18Handler.MC_1_17_1_Version and < Protocol18Handler.MC_1_20_6_Version:
ReadDustParticle(cache);
break;
// 1.20.6+
case >= Protocol18Handler.MC_1_20_6_Version:
ReadDustParticleColorTransition(cache);
break;
}
break;
case 15:
switch (protocolversion)
@ -910,7 +1004,8 @@ namespace MinecraftClient.Protocol.Handlers
case Protocol18Handler.MC_1_17_Version or Protocol18Handler.MC_1_17_1_Version:
ReadDustParticle(cache);
break;
case > Protocol18Handler.MC_1_17_1_Version:
// 1.18 - 1.20.4
case > Protocol18Handler.MC_1_17_1_Version and < Protocol18Handler.MC_1_20_6_Version:
ReadDustParticleColorTransition(cache);
break;
}
@ -920,21 +1015,26 @@ namespace MinecraftClient.Protocol.Handlers
if (protocolversion is Protocol18Handler.MC_1_17_Version or Protocol18Handler.MC_1_17_1_Version)
ReadDustParticleColorTransition(cache);
break;
case 20:
// 1.20.6+
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
ReadNextInt(cache); // minecraft:entity_effect
break;
case 23:
// 1.15 - 1.16.5
if (protocolversion is >= Protocol18Handler.MC_1_15_Version and < Protocol18Handler.MC_1_17_Version)
ReadNextVarInt(cache); // Block State (minecraft:falling_dust)
break;
case 24:
// 1.18 - 1.19.2 onwards
// 1.18 - 1.19.3
if (protocolversion is > Protocol18Handler.MC_1_17_1_Version
and < Protocol18Handler.MC_1_19_3_Version)
ReadNextVarInt(cache); // Block State (minecraft:falling_dust)
break;
case 25:
// 1.17 - 1.17.1 and 1.19.3 onwards
// 1.17 - 1.17.1 and 1.19.3 - 1.20.4
if (protocolversion is Protocol18Handler.MC_1_17_Version or Protocol18Handler.MC_1_17_1_Version
or >= Protocol18Handler.MC_1_19_3_Version)
or (>= Protocol18Handler.MC_1_19_3_Version and < Protocol18Handler.MC_1_20_6_Version))
ReadNextVarInt(cache); // Block State (minecraft:falling_dust)
break;
case 27:
@ -942,8 +1042,14 @@ namespace MinecraftClient.Protocol.Handlers
if (protocolversion < Protocol18Handler.MC_1_15_Version)
ReadNextItemSlot(cache, itemPalette); // Item (minecraft:item)
break;
case 28:
// 1.20.6+
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
ReadNextVarInt(cache); // minecraft:falling_dust (BlockState)
break;
case 30:
if (protocolversion >= Protocol18Handler.MC_1_19_3_Version)
// 1.19.3 - 1.20.4
if (protocolversion is >= Protocol18Handler.MC_1_19_3_Version and < Protocol18Handler.MC_1_20_6_Version)
ReadNextFloat(cache); // Roll (minecraft:sculk_charge)
break;
case 32:
@ -951,6 +1057,11 @@ namespace MinecraftClient.Protocol.Handlers
if (protocolversion is >= Protocol18Handler.MC_1_15_Version and < Protocol18Handler.MC_1_17_Version)
ReadNextItemSlot(cache, itemPalette); // Item (minecraft:item)
break;
case 35:
// 1.20.6+
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
ReadNextFloat(cache); // minecraft:sculk_charge (Roll)
break;
case 36:
switch (protocolversion)
{
@ -958,6 +1069,7 @@ namespace MinecraftClient.Protocol.Handlers
case Protocol18Handler.MC_1_17_Version or Protocol18Handler.MC_1_17_1_Version:
ReadNextItemSlot(cache, itemPalette); // Item (minecraft:item)
break;
// 1.18 - 1.19.2
case > Protocol18Handler.MC_1_17_1_Version and < Protocol18Handler.MC_1_19_3_Version:
// minecraft:vibration
ReadNextLocation(cache); // Origin (Starting Position)
@ -968,7 +1080,7 @@ namespace MinecraftClient.Protocol.Handlers
break;
case 37:
// minecraft:vibration
// minecraft:vibration - 1.17 - 1.17.1
if (protocolversion is Protocol18Handler.MC_1_17_Version or Protocol18Handler.MC_1_17_1_Version)
{
ReadNextDouble(cache); // Origin X
@ -982,11 +1094,13 @@ namespace MinecraftClient.Protocol.Handlers
break;
case 39:
if (protocolversion >= Protocol18Handler.MC_1_19_3_Version)
// 1.19.3 - 1.20.4
if (protocolversion is >= Protocol18Handler.MC_1_19_3_Version and < Protocol18Handler.MC_1_20_6_Version)
ReadNextItemSlot(cache, itemPalette); // Item (minecraft:item)
break;
case 40:
if (protocolversion >= Protocol18Handler.MC_1_19_3_Version)
// 1.19.3 - 1.20.4
if (protocolversion is >= Protocol18Handler.MC_1_19_3_Version and < Protocol18Handler.MC_1_20_6_Version)
{
var positionSourceType = ReadNextString(cache);
switch (positionSourceType)
@ -1004,6 +1118,26 @@ namespace MinecraftClient.Protocol.Handlers
}
break;
case 44:
// 1.20.6+
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
ReadNextItemSlot(cache, itemPalette); // minecraft:item (Item)
break;
case 45:
// 1.21+
if(protocolversion >= Protocol18Handler.MC_1_21_Version)
ReadVibration(cache);
break;
case 99:
// 1.20.6+
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
ReadNextVarInt(cache); // minecraft:shriek (Delay)
break;
case 105:
// 1.20.6+
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
ReadNextVarInt(cache); // minecraft:dust_pillar (BlockState)
break;
}
}
@ -1020,12 +1154,21 @@ namespace MinecraftClient.Protocol.Handlers
ReadNextFloat(cache); // From red
ReadNextFloat(cache); // From green
ReadNextFloat(cache); // From blue
ReadNextFloat(cache); // Scale
ReadNextFloat(cache); // To red
ReadNextFloat(cache); // To green
ReadNextFloat(cache); // To Blue
ReadNextFloat(cache); // To blue
ReadNextFloat(cache); // Scale
}
private void ReadVibration(Queue<byte> cache)
{
ReadNextVarInt(cache); // Position Source Type
ReadNextLocation(cache); // Block Position
ReadNextVarInt(cache); // Entity ID
ReadNextFloat(cache); // Entity eye height
ReadNextVarInt(cache); // Ticks
}
/// <summary>
/// Read a single villager trade from a cache of bytes and remove it from the cache
/// </summary>
@ -1098,18 +1241,31 @@ namespace MinecraftClient.Protocol.Handlers
if (root)
{
if (protocolversion >= Protocol18Handler.MC_1_20_4_Version
&& nbt.Count == 1
&& nbt.TryGetValue("", out var rootVal) && rootVal is string rootStr)
{
bytes.Add(8); // TAG_String
var strBytes = Encoding.UTF8.GetBytes(rootStr);
bytes.AddRange(GetUShort((ushort)strBytes.Length));
bytes.AddRange(strBytes);
return bytes.ToArray();
}
bytes.Add(10); // TAG_Compound
// NBT root name
string? rootName = null;
if (protocolversion < Protocol18Handler.MC_1_20_2_Version)
{
string? rootName = null;
if (nbt.ContainsKey(""))
rootName = nbt[""] as string;
if (nbt.ContainsKey(""))
rootName = nbt[""] as string;
rootName ??= "";
rootName ??= "";
bytes.AddRange(GetUShort((ushort)rootName.Length));
bytes.AddRange(Encoding.ASCII.GetBytes(rootName));
bytes.AddRange(GetUShort((ushort)rootName.Length));
bytes.AddRange(Encoding.ASCII.GetBytes(rootName));
}
}
foreach (var item in nbt)
@ -1425,14 +1581,43 @@ namespace MinecraftClient.Protocol.Handlers
public byte[] GetItemSlot(Item? item, ItemPalette itemPalette)
{
List<byte> slotData = new();
if (protocolversion > Protocol18Handler.MC_1_13_Version)
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
{
// MC 1.13 and greater
if (item == null || item.IsEmpty)
slotData.AddRange(GetBool(false)); // No item
{
slotData.AddRange(GetVarInt(0));
}
else
{
slotData.AddRange(GetBool(true)); // Item is present
slotData.AddRange(GetVarInt(item.Count));
slotData.AddRange(GetVarInt(itemPalette.ToId(item.Type)));
if (item.Components != null && item.Components.Count > 0)
{
slotData.AddRange(GetVarInt(item.Components.Count));
slotData.AddRange(GetVarInt(0)); // components to remove
foreach (var component in item.Components)
{
slotData.AddRange(GetVarInt(component.TypeId));
var serialized = component.Serialize();
slotData.AddRange(serialized);
}
}
else
{
slotData.AddRange(GetVarInt(0)); // no components to add
slotData.AddRange(GetVarInt(0)); // no components to remove
}
}
}
else if (protocolversion > Protocol18Handler.MC_1_13_Version)
{
if (item == null || item.IsEmpty)
slotData.AddRange(GetBool(false));
else
{
slotData.AddRange(GetBool(true));
slotData.AddRange(GetVarInt(itemPalette.ToId(item.Type)));
slotData.Add((byte)item.Count);
slotData.AddRange(GetNbt(item.NBT));
@ -1440,13 +1625,10 @@ namespace MinecraftClient.Protocol.Handlers
}
else
{
// MC 1.12.2 and lower
if (item == null || item.IsEmpty)
slotData.AddRange(GetShort(-1));
else
{
// For 1.8 - 1.12.2 we combine Item Id and Item Data to a single value using: (id << 16) | data
// Thus to get an ID we do a right shift by 16 bits
slotData.AddRange(GetShort((short)(itemPalette.ToId(item.Type) >> 16)));
slotData.Add((byte)item.Count);
slotData.Add((byte)item.Data);

View file

@ -10,6 +10,12 @@ namespace MinecraftClient.Protocol.Handlers.packet.s2c
public static void Read(DataTypes dataTypes, Queue<byte> packetData, int protocolVersion)
{
// TODO: Fix this
// It crashes in 1.20.6+ , could not figure out why
// it's hard to debug, so I'll just disable it for now
if(protocolVersion > Protocol18Handler.MC_1_20_4_Version)
return;
int count = dataTypes.ReadNextVarInt(packetData);
Nodes = new CommandNode[count];
for (int i = 0; i < count; ++i)
@ -103,7 +109,8 @@ namespace MinecraftClient.Protocol.Handlers.packet.s2c
new ParserEmpty(dataTypes, packetData),
_ => new ParserEmpty(dataTypes, packetData),
};
else // 1.20.3+
else if (protocolVersion is > Protocol18Handler.MC_1_20_2_Version and < Protocol18Handler.MC_1_20_6_Version)
// 1.20.3 - 1.20.4
parser = parserId switch
{
1 => new ParserFloat(dataTypes, packetData),
@ -127,6 +134,24 @@ namespace MinecraftClient.Protocol.Handlers.packet.s2c
52 => new ParserForgeEnum(dataTypes, packetData),
_ => new ParserEmpty(dataTypes, packetData),
};
else // 1.20.6+
parser = parserId switch
{
1 => new ParserFloat(dataTypes, packetData),
2 => new ParserDouble(dataTypes, packetData),
3 => new ParserInteger(dataTypes, packetData),
4 => new ParserLong(dataTypes, packetData),
5 => new ParserString(dataTypes, packetData),
6 => new ParserEntity(dataTypes, packetData),
30 => new ParserScoreHolder(dataTypes, packetData),
41 => new ParserTime(dataTypes, packetData),
42 => new ParserResourceOrTag(dataTypes, packetData),
43 => new ParserResourceOrTag(dataTypes, packetData),
44 => new ParserResource(dataTypes, packetData),
45 => new ParserResource(dataTypes, packetData),
52 => new ParserForgeEnum(dataTypes, packetData),
_ => new ParserEmpty(dataTypes, packetData),
};
}
string? suggestionsType = ((flags & 0x10) == 0x10) ? dataTypes.ReadNextString(packetData) : null;

View file

@ -0,0 +1,230 @@
using System.Collections.Generic;
namespace MinecraftClient.Protocol.Handlers.PacketPalettes;
public class PacketPalette1206 : PacketTypePalette
{
private readonly Dictionary<int, PacketTypesIn> typeIn = new()
{
{ 0x00, PacketTypesIn.Bundle }, // Added in 1.19.4
{ 0x01, PacketTypesIn.SpawnEntity }, // Changed in 1.19 (Wiki name: Spawn Entity)
{ 0x02, PacketTypesIn.SpawnExperienceOrb }, // (Wiki name: Spawn Exeprience Orb)
{ 0x03, PacketTypesIn.EntityAnimation }, // (Wiki name: Entity Animation (clientbound))
{ 0x04, PacketTypesIn.Statistics }, // (Wiki name: Award Statistics)
{ 0x05, PacketTypesIn.BlockChangedAck }, // Added 1.19 (Wiki name: Acknowledge Block Change)
{ 0x06, PacketTypesIn.BlockBreakAnimation }, // (Wiki name: Set Block Destroy Stage)
{ 0x07, PacketTypesIn.BlockEntityData }, //
{ 0x08, PacketTypesIn.BlockAction }, //
{ 0x09, PacketTypesIn.BlockChange }, // (Wiki name: Block Update)
{ 0x0A, PacketTypesIn.BossBar }, //
{ 0x0B, PacketTypesIn.ServerDifficulty }, // (Wiki name: Change Difficulty)
{ 0x0C, PacketTypesIn.ChunkBatchFinished }, // Added in 1.20.2
{ 0x0D, PacketTypesIn.ChunkBatchStarted }, // Added in 1.20.2
{ 0x0E, PacketTypesIn.ChunksBiomes }, // Added in 1.19.4
{ 0x0F, PacketTypesIn.ClearTiles }, //
{ 0x10, PacketTypesIn.TabComplete }, // (Wiki name: Command Suggestions Response)
{ 0x11, PacketTypesIn.DeclareCommands }, // (Wiki name: Commands)
{ 0x12, PacketTypesIn.CloseWindow }, // (Wiki name: Close Container (clientbound))
{ 0x13, PacketTypesIn.WindowItems }, // (Wiki name: Set Container Content)
{ 0x14, PacketTypesIn.WindowProperty }, // (Wiki name: Set Container Property)
{ 0x15, PacketTypesIn.SetSlot }, // (Wiki name: Set Container Slot)
{ 0x16, PacketTypesIn.CookieRequest }, // Added in 1.20.6
{ 0x17, PacketTypesIn.SetCooldown }, //
{ 0x18, PacketTypesIn.ChatSuggestions }, // Added in 1.19.1
{ 0x19, PacketTypesIn.PluginMessage }, // (Wiki name: Plugin Message (clientbound))
{ 0x1A, PacketTypesIn.DamageEvent }, // Added in 1.19.4
{ 0x1B, PacketTypesIn.DebugSample }, // Added in 1.20.6
{ 0x1C, PacketTypesIn.HideMessage }, // Added in 1.19.1
{ 0x1D, PacketTypesIn.Disconnect }, //
{ 0x1E, PacketTypesIn.ProfilelessChatMessage }, // Added in 1.19.3 (Wiki name: Disguised Chat Message)
{ 0x1F, PacketTypesIn.EntityStatus }, // (Wiki name: Entity Event)
{ 0x20, PacketTypesIn.Explosion }, // Changed in 1.19 (Location fields are now Double instead of Float) (Wiki name: Explosion)
{ 0x21, PacketTypesIn.UnloadChunk }, // (Wiki name: Forget Chunk)
{ 0x22, PacketTypesIn.ChangeGameState }, // (Wiki name: Game Event)
{ 0x23, PacketTypesIn.OpenHorseWindow }, // (Wiki name: Horse Screen Open)
{ 0x24, PacketTypesIn.HurtAnimation }, // Added in 1.19.4
{ 0x25, PacketTypesIn.InitializeWorldBorder }, //
{ 0x26, PacketTypesIn.KeepAlive }, //
{ 0x27, PacketTypesIn.ChunkData }, //
{ 0x28, PacketTypesIn.Effect }, // (Wiki name: World Event)
{ 0x29, PacketTypesIn.Particle }, // Changed in 1.19 (Wiki name: Level Particle) (No need to be implemented)
{ 0x2A, PacketTypesIn.UpdateLight }, // (Wiki name: Light Update)
{ 0x2B, PacketTypesIn.JoinGame }, // Changed in 1.20.2 (Wiki name: Login (play))
{ 0x2C, PacketTypesIn.MapData }, // (Wiki name: Map Item Data)
{ 0x2D, PacketTypesIn.TradeList }, // (Wiki name: Merchant Offers)
{ 0x2E, PacketTypesIn.EntityPosition }, // (Wiki name: Move Entity Position)
{ 0x2F, PacketTypesIn.EntityPositionAndRotation }, // (Wiki name: Move Entity Position and Rotation)
{ 0x30, PacketTypesIn.EntityRotation }, // (Wiki name: Move Entity Rotation)
{ 0x31, PacketTypesIn.VehicleMove }, // (Wiki name: Move Vehicle)
{ 0x32, PacketTypesIn.OpenBook }, //
{ 0x33, PacketTypesIn.OpenWindow }, // (Wiki name: Open Screen)
{ 0x34, PacketTypesIn.OpenSignEditor }, //
{ 0x35, PacketTypesIn.Ping }, // (Wiki name: Ping (play))
{ 0x36, PacketTypesIn.PingResponse }, // Added in 1.20.2
{ 0x37, PacketTypesIn.CraftRecipeResponse }, // (Wiki name: Place Ghost Recipe)
{ 0x38, PacketTypesIn.PlayerAbilities }, //
{ 0x39, PacketTypesIn.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Player Chat Message)
{ 0x3A, PacketTypesIn.EndCombatEvent }, // (Wiki name: End Combat)
{ 0x3B, PacketTypesIn.EnterCombatEvent }, // (Wiki name: Enter Combat)
{ 0x3C, PacketTypesIn.DeathCombatEvent }, // (Wiki name: Combat Death)
{ 0x3D, PacketTypesIn.PlayerRemove }, // Added in 1.19.3 (Not used)
{ 0x3E, PacketTypesIn.PlayerInfo }, // Changed in 1.19 (Heavy changes)
{ 0x3F, PacketTypesIn.FacePlayer }, // (Wiki name: Player Look At)
{ 0x40, PacketTypesIn.PlayerPositionAndLook }, // (Wiki name: Synchronize Player Position)
{ 0x41, PacketTypesIn.UnlockRecipes }, // (Wiki name: Update Recipe Book)
{ 0x42, PacketTypesIn.DestroyEntities }, // (Wiki name: Remove Entites)
{ 0x43, PacketTypesIn.RemoveEntityEffect }, //
{ 0x44, PacketTypesIn.ResetScore }, // Added in 1.20.3
{ 0x45, PacketTypesIn.RemoveResourcePack }, // Added in 1.20.3
{ 0x46, PacketTypesIn.ResourcePackSend }, // (Wiki name: Add Resource pack (play))
{ 0x47, PacketTypesIn.Respawn }, // Changed in 1.20.2
{ 0x48, PacketTypesIn.EntityHeadLook }, // (Wiki name: Set Head Rotation)
{ 0x49, PacketTypesIn.MultiBlockChange }, // (Wiki name: Update Section Blocks)
{ 0x4A, PacketTypesIn.SelectAdvancementTab }, //
{ 0x4B, PacketTypesIn.ServerData }, // Added in 1.19
{ 0x4C, PacketTypesIn.ActionBar }, // (Wiki name: Set Action Bar Text)
{ 0x4D, PacketTypesIn.WorldBorderCenter }, // (Wiki name: Set Border Center)
{ 0x4E, PacketTypesIn.WorldBorderLerpSize }, //
{ 0x4F, PacketTypesIn.WorldBorderSize }, // (Wiki name: Set World Border Size)
{ 0x50, PacketTypesIn.WorldBorderWarningDelay }, // (Wiki name: Set World Border Warning Delay)
{ 0x51, PacketTypesIn.WorldBorderWarningReach }, // (Wiki name: Set Border Warning Distance)
{ 0x52, PacketTypesIn.Camera }, // (Wiki name: Set Camera)
{ 0x53, PacketTypesIn.HeldItemChange }, // (Wiki name: Set Held Item)
{ 0x54, PacketTypesIn.UpdateViewPosition }, // (Wiki name: Set Center Chunk)
{ 0x55, PacketTypesIn.UpdateViewDistance }, // (Wiki name: Set Render Distance)
{ 0x56, PacketTypesIn.SpawnPosition }, // (Wiki name: Set Default Spawn Position)
{ 0x57, PacketTypesIn.DisplayScoreboard }, // (Wiki name: Set Display Objective)
{ 0x58, PacketTypesIn.EntityMetadata }, // (Wiki name: Set Entity Metadata)
{ 0x59, PacketTypesIn.AttachEntity }, // (Wiki name: Link Entities)
{ 0x5A, PacketTypesIn.EntityVelocity }, // (Wiki name: Set Entity Velocity)
{ 0x5B, PacketTypesIn.EntityEquipment }, // (Wiki name: Set Equipment)
{ 0x5C, PacketTypesIn.SetExperience }, // Changed in 1.20.2
{ 0x5D, PacketTypesIn.UpdateHealth }, // (Wiki name: Set Health)
{ 0x5E, PacketTypesIn.ScoreboardObjective }, // (Wiki name: Update Objectives) - Changed in 1.20.3
{ 0x5F, PacketTypesIn.SetPassengers }, //
{ 0x60, PacketTypesIn.Teams }, // (Wiki name: Update Teams)
{ 0x61, PacketTypesIn.UpdateScore }, // (Wiki name: Update Score)
{ 0x62, PacketTypesIn.UpdateSimulationDistance }, // (Wiki name: Set Simulation Distance)
{ 0x63, PacketTypesIn.SetTitleSubTitle }, // (Wiki name: Set Subtitle Test)
{ 0x64, PacketTypesIn.TimeUpdate }, // (Wiki name: Set Time)
{ 0x65, PacketTypesIn.SetTitleText }, // (Wiki name: Set Title)
{ 0x66, PacketTypesIn.SetTitleTime }, // (Wiki name: Set Title Animation Times)
{ 0x67, PacketTypesIn.EntitySoundEffect }, // (Wiki name: Sound Entity)
{ 0x68, PacketTypesIn.SoundEffect }, // Changed in 1.19 (Added "Seed" field) (Wiki name: Sound Effect) (No need to be implemented)
{ 0x69, PacketTypesIn.StartConfiguration }, // Added in 1.20.2
{ 0x6A, PacketTypesIn.StopSound }, //
{ 0x6B, PacketTypesIn.StoreCookie }, // Added in 1.20.6
{ 0x6C, PacketTypesIn.SystemChat }, // Added in 1.19 (Wiki name: System Chat Message)
{ 0x6D, PacketTypesIn.PlayerListHeaderAndFooter }, // (Wiki name: Set Tab List Header And Footer)
{ 0x6E, PacketTypesIn.NBTQueryResponse }, // (Wiki name: Tag Query Response)
{ 0x6F, PacketTypesIn.CollectItem }, // (Wiki name: Pickup Item)
{ 0x70, PacketTypesIn.EntityTeleport }, // (Wiki name: Teleport Entity)
{ 0x71, PacketTypesIn.SetTickingState }, // Added in 1.20.3
{ 0x72, PacketTypesIn.StepTick }, // Added in 1.20.3
{ 0x73, PacketTypesIn.Transfer }, // Added in 1.20.6
{ 0x74, PacketTypesIn.Advancements }, // (Wiki name: Update Advancements) (Unused)
{ 0x75, PacketTypesIn.EntityProperties }, // (Wiki name: Update Attributes)
{ 0x76, PacketTypesIn.EntityEffect }, // Changed in 1.19 (Added "Has Factor Data" and "Factor Codec" fields) (Wiki name: Entity Effect)
{ 0x77, PacketTypesIn.DeclareRecipes }, // (Wiki name: Update Recipes) (Unused)
{ 0x78, PacketTypesIn.Tags }, // (Wiki name: Update Tags)
{ 0x79, PacketTypesIn.ProjectilePower }, // Added in 1.20.6
};
private readonly Dictionary<int, PacketTypesOut> typeOut = new()
{
{ 0x00, PacketTypesOut.TeleportConfirm }, // (Wiki name: Confirm Teleportation)
{ 0x01, PacketTypesOut.QueryBlockNBT }, // (Wiki name: Query Block Entity Tag)
{ 0x02, PacketTypesOut.SetDifficulty }, // (Wiki name: Change Difficulty)
{ 0x03, PacketTypesOut.MessageAcknowledgment }, // Added in 1.19.1
{ 0x04, PacketTypesOut.ChatCommand }, // Added in 1.19
{ 0x05, PacketTypesOut.SignedChatCommand }, // Added in 1.20.6
{ 0x06, PacketTypesOut.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Chat)
{ 0x07, PacketTypesOut.PlayerSession }, // Added in 1.19.3
{ 0x08, PacketTypesOut.ChunkBatchReceived }, // Added in 1.20.2
{ 0x09, PacketTypesOut.ClientStatus }, // (Wiki name: Client Command)
{ 0x0A, PacketTypesOut.ClientSettings }, // (Wiki name: Client Information)
{ 0x0B, PacketTypesOut.TabComplete }, // (Wiki name: Command Suggestions Request)
{ 0x0C, PacketTypesOut.AcknowledgeConfiguration }, // Added in 1.20.2
{ 0x0D, PacketTypesOut.ClickWindowButton }, // (Wiki name: Click Container Button)
{ 0x0E, PacketTypesOut.ClickWindow }, // (Wiki name: Click Container)
{ 0x0F, PacketTypesOut.CloseWindow }, // (Wiki name: Close Container (serverbound))
{ 0x10, PacketTypesOut.ChangeContainerSlotState }, // Added in 1.20.3
{ 0x11, PacketTypesOut.CookieResponse }, // Added in 1.20.6
{ 0x12, PacketTypesOut.PluginMessage }, // (Wiki name: Serverbound Plugin Message)
{ 0x13, PacketTypesOut.DebugSampleSubscription }, // Added in 1.20.6
{ 0x14, PacketTypesOut.EditBook }, //
{ 0x15, PacketTypesOut.EntityNBTRequest }, // (Wiki name: Query Entity Tag)
{ 0x16, PacketTypesOut.InteractEntity }, // (Wiki name: Interact)
{ 0x17, PacketTypesOut.GenerateStructure }, // (Wiki name: Jigsaw Generate)
{ 0x18, PacketTypesOut.KeepAlive }, // (Wiki name: Serverbound Keep Alive (play))
{ 0x19, PacketTypesOut.LockDifficulty }, //
{ 0x1A, PacketTypesOut.PlayerPosition }, // (Wiki name: Move Player Position)
{ 0x1B, PacketTypesOut.PlayerPositionAndRotation }, // (Wiki name: Set Player Position and Rotation)
{ 0x1C, PacketTypesOut.PlayerRotation }, // (Wiki name: Set Player Rotation)
{ 0x1D, PacketTypesOut.PlayerMovement }, // (Wiki name: Set Player On Ground)
{ 0x1E, PacketTypesOut.VehicleMove }, // (Wiki name: Move Vehicle (serverbound))
{ 0x1F, PacketTypesOut.SteerBoat }, // (Wiki name: Paddle Boat)
{ 0x20, PacketTypesOut.PickItem }, //
{ 0x21, PacketTypesOut.PingRequest }, // Added in 1.20.2
{ 0x22, PacketTypesOut.CraftRecipeRequest }, // (Wiki name: Place recipe)
{ 0x23, PacketTypesOut.PlayerAbilities }, //
{ 0x24, PacketTypesOut.PlayerDigging }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Player Action)
{ 0x25, PacketTypesOut.EntityAction }, // (Wiki name: Player Command)
{ 0x26, PacketTypesOut.SteerVehicle }, // (Wiki name: Player Input)
{ 0x27, PacketTypesOut.Pong }, // (Wiki name: Pong (play))
{ 0x28, PacketTypesOut.SetDisplayedRecipe }, // (Wiki name: Recipe Book Change Settings)
{ 0x29, PacketTypesOut.SetRecipeBookState }, // (Wiki name: Recipe Book Seen Recipe)
{ 0x2A, PacketTypesOut.NameItem }, // (Wiki name: Rename Item)
{ 0x2B, PacketTypesOut.ResourcePackStatus }, // (Wiki name: Resource Pack (serverbound))
{ 0x2C, PacketTypesOut.AdvancementTab }, // (Wiki name: Seen Advancements)
{ 0x2D, PacketTypesOut.SelectTrade }, //
{ 0x2E, PacketTypesOut.SetBeaconEffect }, // Changed in 1.19 (No need to be implemented yet)
{ 0x2F, PacketTypesOut.HeldItemChange }, // (Wiki name: Set Carried Item (serverbound))
{ 0x30, PacketTypesOut.UpdateCommandBlock }, // (Wiki name: Program Command Block)
{ 0x31, PacketTypesOut.UpdateCommandBlockMinecart }, // (Wiki name: Program Command Block Minecart)
{ 0x32, PacketTypesOut.CreativeInventoryAction }, // (Wiki name: Set Creative Mode Slot)
{ 0x33, PacketTypesOut.UpdateJigsawBlock }, // (Wiki name: Program Jigsaw Block)
{ 0x34, PacketTypesOut.UpdateStructureBlock }, // (Wiki name: Program Structure Block)
{ 0x35, PacketTypesOut.UpdateSign }, // (Wiki name: Update Sign)
{ 0x36, PacketTypesOut.Animation }, // (Wiki name: Swing Arm)
{ 0x37, PacketTypesOut.Spectate }, // (Wiki name: Teleport To Entity)
{ 0x38, PacketTypesOut.PlayerBlockPlacement }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item On)
{ 0x39, PacketTypesOut.UseItem }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item)
};
private readonly Dictionary<int, ConfigurationPacketTypesIn> configurationTypesIn = new()
{
{ 0x00, ConfigurationPacketTypesIn.CookieRequest },
{ 0x01, ConfigurationPacketTypesIn.PluginMessage },
{ 0x02, ConfigurationPacketTypesIn.Disconnect },
{ 0x03, ConfigurationPacketTypesIn.FinishConfiguration },
{ 0x04, ConfigurationPacketTypesIn.KeepAlive },
{ 0x05, ConfigurationPacketTypesIn.Ping },
{ 0x06, ConfigurationPacketTypesIn.ResetChat },
{ 0x07, ConfigurationPacketTypesIn.RegistryData },
{ 0x08, ConfigurationPacketTypesIn.RemoveResourcePack },
{ 0x09, ConfigurationPacketTypesIn.ResourcePack },
{ 0x0A, ConfigurationPacketTypesIn.StoreCookie },
{ 0x0B, ConfigurationPacketTypesIn.Transfer },
{ 0x0C, ConfigurationPacketTypesIn.FeatureFlags },
{ 0x0D, ConfigurationPacketTypesIn.UpdateTags },
{ 0x0E, ConfigurationPacketTypesIn.KnownDataPacks }
};
private readonly Dictionary<int, ConfigurationPacketTypesOut> configurationTypesOut = new()
{
{ 0x00, ConfigurationPacketTypesOut.ClientInformation },
{ 0x01, ConfigurationPacketTypesOut.CookieResponse },
{ 0x02, ConfigurationPacketTypesOut.PluginMessage },
{ 0x03, ConfigurationPacketTypesOut.FinishConfiguration },
{ 0x04, ConfigurationPacketTypesOut.KeepAlive },
{ 0x05, ConfigurationPacketTypesOut.Pong },
{ 0x06, ConfigurationPacketTypesOut.ResourcePackResponse },
{ 0x07, ConfigurationPacketTypesOut.KnownDataPacks }
};
protected override Dictionary<int, PacketTypesIn> GetListIn() => typeIn;
protected override Dictionary<int, PacketTypesOut> GetListOut() => typeOut;
protected override Dictionary<int, ConfigurationPacketTypesIn> GetConfigurationListIn() => configurationTypesIn!;
protected override Dictionary<int, ConfigurationPacketTypesOut> GetConfigurationListOut() => configurationTypesOut!;
}

View file

@ -0,0 +1,234 @@
using System.Collections.Generic;
namespace MinecraftClient.Protocol.Handlers.PacketPalettes;
public class PacketPalette121 : PacketTypePalette
{
private readonly Dictionary<int, PacketTypesIn> typeIn = new()
{
{ 0x00, PacketTypesIn.Bundle }, // Added in 1.19.4
{ 0x01, PacketTypesIn.SpawnEntity }, // Changed in 1.19 (Wiki name: Spawn Entity)
{ 0x02, PacketTypesIn.SpawnExperienceOrb }, // (Wiki name: Spawn Exeprience Orb)
{ 0x03, PacketTypesIn.EntityAnimation }, // (Wiki name: Entity Animation (clientbound))
{ 0x04, PacketTypesIn.Statistics }, // (Wiki name: Award Statistics)
{ 0x05, PacketTypesIn.BlockChangedAck }, // Added 1.19 (Wiki name: Acknowledge Block Change)
{ 0x06, PacketTypesIn.BlockBreakAnimation }, // (Wiki name: Set Block Destroy Stage)
{ 0x07, PacketTypesIn.BlockEntityData }, //
{ 0x08, PacketTypesIn.BlockAction }, //
{ 0x09, PacketTypesIn.BlockChange }, // (Wiki name: Block Update)
{ 0x0A, PacketTypesIn.BossBar }, //
{ 0x0B, PacketTypesIn.ServerDifficulty }, // (Wiki name: Change Difficulty)
{ 0x0C, PacketTypesIn.ChunkBatchFinished }, // Added in 1.20.2
{ 0x0D, PacketTypesIn.ChunkBatchStarted }, // Added in 1.20.2
{ 0x0E, PacketTypesIn.ChunksBiomes }, // Added in 1.19.4
{ 0x0F, PacketTypesIn.ClearTiles }, //
{ 0x10, PacketTypesIn.TabComplete }, // (Wiki name: Command Suggestions Response)
{ 0x11, PacketTypesIn.DeclareCommands }, // (Wiki name: Commands)
{ 0x12, PacketTypesIn.CloseWindow }, // (Wiki name: Close Container (clientbound))
{ 0x13, PacketTypesIn.WindowItems }, // (Wiki name: Set Container Content)
{ 0x14, PacketTypesIn.WindowProperty }, // (Wiki name: Set Container Property)
{ 0x15, PacketTypesIn.SetSlot }, // (Wiki name: Set Container Slot)
{ 0x16, PacketTypesIn.CookieRequest }, // Added in 1.20.6
{ 0x17, PacketTypesIn.SetCooldown }, //
{ 0x18, PacketTypesIn.ChatSuggestions }, // Added in 1.19.1
{ 0x19, PacketTypesIn.PluginMessage }, // (Wiki name: Plugin Message (clientbound))
{ 0x1A, PacketTypesIn.DamageEvent }, // Added in 1.19.4
{ 0x1B, PacketTypesIn.DebugSample }, // Added in 1.20.6
{ 0x1C, PacketTypesIn.HideMessage }, // Added in 1.19.1
{ 0x1D, PacketTypesIn.Disconnect }, //
{ 0x1E, PacketTypesIn.ProfilelessChatMessage }, // Added in 1.19.3 (Wiki name: Disguised Chat Message)
{ 0x1F, PacketTypesIn.EntityStatus }, // (Wiki name: Entity Event)
{ 0x20, PacketTypesIn.Explosion }, // Changed in 1.19 (Location fields are now Double instead of Float) (Wiki name: Explosion)
{ 0x21, PacketTypesIn.UnloadChunk }, // (Wiki name: Forget Chunk)
{ 0x22, PacketTypesIn.ChangeGameState }, // (Wiki name: Game Event)
{ 0x23, PacketTypesIn.OpenHorseWindow }, // (Wiki name: Horse Screen Open)
{ 0x24, PacketTypesIn.HurtAnimation }, // Added in 1.19.4
{ 0x25, PacketTypesIn.InitializeWorldBorder }, //
{ 0x26, PacketTypesIn.KeepAlive }, //
{ 0x27, PacketTypesIn.ChunkData }, //
{ 0x28, PacketTypesIn.Effect }, // (Wiki name: World Event)
{ 0x29, PacketTypesIn.Particle }, // Changed in 1.19 (Wiki name: Level Particle) (No need to be implemented)
{ 0x2A, PacketTypesIn.UpdateLight }, // (Wiki name: Light Update)
{ 0x2B, PacketTypesIn.JoinGame }, // Changed in 1.20.2 (Wiki name: Login (play))
{ 0x2C, PacketTypesIn.MapData }, // (Wiki name: Map Item Data)
{ 0x2D, PacketTypesIn.TradeList }, // (Wiki name: Merchant Offers)
{ 0x2E, PacketTypesIn.EntityPosition }, // (Wiki name: Move Entity Position)
{ 0x2F, PacketTypesIn.EntityPositionAndRotation }, // (Wiki name: Move Entity Position and Rotation)
{ 0x30, PacketTypesIn.EntityRotation }, // (Wiki name: Move Entity Rotation)
{ 0x31, PacketTypesIn.VehicleMove }, // (Wiki name: Move Vehicle)
{ 0x32, PacketTypesIn.OpenBook }, //
{ 0x33, PacketTypesIn.OpenWindow }, // (Wiki name: Open Screen)
{ 0x34, PacketTypesIn.OpenSignEditor }, //
{ 0x35, PacketTypesIn.Ping }, // (Wiki name: Ping (play))
{ 0x36, PacketTypesIn.PingResponse }, // Added in 1.20.2
{ 0x37, PacketTypesIn.CraftRecipeResponse }, // (Wiki name: Place Ghost Recipe)
{ 0x38, PacketTypesIn.PlayerAbilities }, //
{ 0x39, PacketTypesIn.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Player Chat Message)
{ 0x3A, PacketTypesIn.EndCombatEvent }, // (Wiki name: End Combat)
{ 0x3B, PacketTypesIn.EnterCombatEvent }, // (Wiki name: Enter Combat)
{ 0x3C, PacketTypesIn.DeathCombatEvent }, // (Wiki name: Combat Death)
{ 0x3D, PacketTypesIn.PlayerRemove }, // Added in 1.19.3 (Not used)
{ 0x3E, PacketTypesIn.PlayerInfo }, // Changed in 1.19 (Heavy changes)
{ 0x3F, PacketTypesIn.FacePlayer }, // (Wiki name: Player Look At)
{ 0x40, PacketTypesIn.PlayerPositionAndLook }, // (Wiki name: Synchronize Player Position)
{ 0x41, PacketTypesIn.UnlockRecipes }, // (Wiki name: Update Recipe Book)
{ 0x42, PacketTypesIn.DestroyEntities }, // (Wiki name: Remove Entites)
{ 0x43, PacketTypesIn.RemoveEntityEffect }, //
{ 0x44, PacketTypesIn.ResetScore }, // Added in 1.20.3
{ 0x45, PacketTypesIn.RemoveResourcePack }, // Added in 1.20.3
{ 0x46, PacketTypesIn.ResourcePackSend }, // (Wiki name: Add Resource pack (play))
{ 0x47, PacketTypesIn.Respawn }, // Changed in 1.20.2
{ 0x48, PacketTypesIn.EntityHeadLook }, // (Wiki name: Set Head Rotation)
{ 0x49, PacketTypesIn.MultiBlockChange }, // (Wiki name: Update Section Blocks)
{ 0x4A, PacketTypesIn.SelectAdvancementTab }, //
{ 0x4B, PacketTypesIn.ServerData }, // Added in 1.19
{ 0x4C, PacketTypesIn.ActionBar }, // (Wiki name: Set Action Bar Text)
{ 0x4D, PacketTypesIn.WorldBorderCenter }, // (Wiki name: Set Border Center)
{ 0x4E, PacketTypesIn.WorldBorderLerpSize }, //
{ 0x4F, PacketTypesIn.WorldBorderSize }, // (Wiki name: Set World Border Size)
{ 0x50, PacketTypesIn.WorldBorderWarningDelay }, // (Wiki name: Set World Border Warning Delay)
{ 0x51, PacketTypesIn.WorldBorderWarningReach }, // (Wiki name: Set Border Warning Distance)
{ 0x52, PacketTypesIn.Camera }, // (Wiki name: Set Camera)
{ 0x53, PacketTypesIn.HeldItemChange }, // (Wiki name: Set Held Item)
{ 0x54, PacketTypesIn.UpdateViewPosition }, // (Wiki name: Set Center Chunk)
{ 0x55, PacketTypesIn.UpdateViewDistance }, // (Wiki name: Set Render Distance)
{ 0x56, PacketTypesIn.SpawnPosition }, // (Wiki name: Set Default Spawn Position)
{ 0x57, PacketTypesIn.DisplayScoreboard }, // (Wiki name: Set Display Objective)
{ 0x58, PacketTypesIn.EntityMetadata }, // (Wiki name: Set Entity Metadata)
{ 0x59, PacketTypesIn.AttachEntity }, // (Wiki name: Link Entities)
{ 0x5A, PacketTypesIn.EntityVelocity }, // (Wiki name: Set Entity Velocity)
{ 0x5B, PacketTypesIn.EntityEquipment }, // (Wiki name: Set Equipment)
{ 0x5C, PacketTypesIn.SetExperience }, // Changed in 1.20.2
{ 0x5D, PacketTypesIn.UpdateHealth }, // (Wiki name: Set Health)
{ 0x5E, PacketTypesIn.ScoreboardObjective }, // (Wiki name: Update Objectives) - Changed in 1.20.3
{ 0x5F, PacketTypesIn.SetPassengers }, //
{ 0x60, PacketTypesIn.Teams }, // (Wiki name: Update Teams)
{ 0x61, PacketTypesIn.UpdateScore }, // (Wiki name: Update Score)
{ 0x62, PacketTypesIn.UpdateSimulationDistance }, // (Wiki name: Set Simulation Distance)
{ 0x63, PacketTypesIn.SetTitleSubTitle }, // (Wiki name: Set Subtitle Test)
{ 0x64, PacketTypesIn.TimeUpdate }, // (Wiki name: Set Time)
{ 0x65, PacketTypesIn.SetTitleText }, // (Wiki name: Set Title)
{ 0x66, PacketTypesIn.SetTitleTime }, // (Wiki name: Set Title Animation Times)
{ 0x67, PacketTypesIn.EntitySoundEffect }, // (Wiki name: Sound Entity)
{ 0x68, PacketTypesIn.SoundEffect }, // Changed in 1.19 (Added "Seed" field) (Wiki name: Sound Effect) (No need to be implemented)
{ 0x69, PacketTypesIn.StartConfiguration }, // Added in 1.20.2
{ 0x6A, PacketTypesIn.StopSound }, //
{ 0x6B, PacketTypesIn.StoreCookie }, // Added in 1.20.6
{ 0x6C, PacketTypesIn.SystemChat }, // Added in 1.19 (Wiki name: System Chat Message)
{ 0x6D, PacketTypesIn.PlayerListHeaderAndFooter }, // (Wiki name: Set Tab List Header And Footer)
{ 0x6E, PacketTypesIn.NBTQueryResponse }, // (Wiki name: Tag Query Response)
{ 0x6F, PacketTypesIn.CollectItem }, // (Wiki name: Pickup Item)
{ 0x70, PacketTypesIn.EntityTeleport }, // (Wiki name: Teleport Entity)
{ 0x71, PacketTypesIn.SetTickingState }, // Added in 1.20.3
{ 0x72, PacketTypesIn.StepTick }, // Added in 1.20.3
{ 0x73, PacketTypesIn.Transfer }, // Added in 1.20.6
{ 0x74, PacketTypesIn.Advancements }, // (Wiki name: Update Advancements) (Unused)
{ 0x75, PacketTypesIn.EntityProperties }, // (Wiki name: Update Attributes)
{ 0x76, PacketTypesIn.EntityEffect }, // Changed in 1.19 (Added "Has Factor Data" and "Factor Codec" fields) (Wiki name: Entity Effect)
{ 0x77, PacketTypesIn.DeclareRecipes }, // (Wiki name: Update Recipes) (Unused)
{ 0x78, PacketTypesIn.Tags }, // (Wiki name: Update Tags)
{ 0x79, PacketTypesIn.ProjectilePower }, // Added in 1.20.6
{ 0x7A, PacketTypesIn.CustomReportDetails }, // Added in 1.21
{ 0x7B, PacketTypesIn.ServerLinks } // Added in 1.21
};
private readonly Dictionary<int, PacketTypesOut> typeOut = new()
{
{ 0x00, PacketTypesOut.TeleportConfirm }, // (Wiki name: Confirm Teleportation)
{ 0x01, PacketTypesOut.QueryBlockNBT }, // (Wiki name: Query Block Entity Tag)
{ 0x02, PacketTypesOut.SetDifficulty }, // (Wiki name: Change Difficulty)
{ 0x03, PacketTypesOut.MessageAcknowledgment }, // Added in 1.19.1
{ 0x04, PacketTypesOut.ChatCommand }, // Added in 1.19
{ 0x05, PacketTypesOut.SignedChatCommand }, // Added in 1.20.6
{ 0x06, PacketTypesOut.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Chat)
{ 0x07, PacketTypesOut.PlayerSession }, // Added in 1.19.3
{ 0x08, PacketTypesOut.ChunkBatchReceived }, // Added in 1.20.2
{ 0x09, PacketTypesOut.ClientStatus }, // (Wiki name: Client Command)
{ 0x0A, PacketTypesOut.ClientSettings }, // (Wiki name: Client Information)
{ 0x0B, PacketTypesOut.TabComplete }, // (Wiki name: Command Suggestions Request)
{ 0x0C, PacketTypesOut.AcknowledgeConfiguration }, // Added in 1.20.2
{ 0x0D, PacketTypesOut.ClickWindowButton }, // (Wiki name: Click Container Button)
{ 0x0E, PacketTypesOut.ClickWindow }, // (Wiki name: Click Container)
{ 0x0F, PacketTypesOut.CloseWindow }, // (Wiki name: Close Container (serverbound))
{ 0x10, PacketTypesOut.ChangeContainerSlotState }, // Added in 1.20.3
{ 0x11, PacketTypesOut.CookieResponse }, // Added in 1.20.6
{ 0x12, PacketTypesOut.PluginMessage }, // (Wiki name: Serverbound Plugin Message)
{ 0x13, PacketTypesOut.DebugSampleSubscription }, // Added in 1.20.6
{ 0x14, PacketTypesOut.EditBook }, //
{ 0x15, PacketTypesOut.EntityNBTRequest }, // (Wiki name: Query Entity Tag)
{ 0x16, PacketTypesOut.InteractEntity }, // (Wiki name: Interact)
{ 0x17, PacketTypesOut.GenerateStructure }, // (Wiki name: Jigsaw Generate)
{ 0x18, PacketTypesOut.KeepAlive }, // (Wiki name: Serverbound Keep Alive (play))
{ 0x19, PacketTypesOut.LockDifficulty }, //
{ 0x1A, PacketTypesOut.PlayerPosition }, // (Wiki name: Move Player Position)
{ 0x1B, PacketTypesOut.PlayerPositionAndRotation }, // (Wiki name: Set Player Position and Rotation)
{ 0x1C, PacketTypesOut.PlayerRotation }, // (Wiki name: Set Player Rotation)
{ 0x1D, PacketTypesOut.PlayerMovement }, // (Wiki name: Set Player On Ground)
{ 0x1E, PacketTypesOut.VehicleMove }, // (Wiki name: Move Vehicle (serverbound))
{ 0x1F, PacketTypesOut.SteerBoat }, // (Wiki name: Paddle Boat)
{ 0x20, PacketTypesOut.PickItem }, //
{ 0x21, PacketTypesOut.PingRequest }, // Added in 1.20.2
{ 0x22, PacketTypesOut.CraftRecipeRequest }, // (Wiki name: Place recipe)
{ 0x23, PacketTypesOut.PlayerAbilities }, //
{ 0x24, PacketTypesOut.PlayerDigging }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Player Action)
{ 0x25, PacketTypesOut.EntityAction }, // (Wiki name: Player Command)
{ 0x26, PacketTypesOut.SteerVehicle }, // (Wiki name: Player Input)
{ 0x27, PacketTypesOut.Pong }, // (Wiki name: Pong (play))
{ 0x28, PacketTypesOut.SetDisplayedRecipe }, // (Wiki name: Recipe Book Change Settings)
{ 0x29, PacketTypesOut.SetRecipeBookState }, // (Wiki name: Recipe Book Seen Recipe)
{ 0x2A, PacketTypesOut.NameItem }, // (Wiki name: Rename Item)
{ 0x2B, PacketTypesOut.ResourcePackStatus }, // (Wiki name: Resource Pack (serverbound))
{ 0x2C, PacketTypesOut.AdvancementTab }, // (Wiki name: Seen Advancements)
{ 0x2D, PacketTypesOut.SelectTrade }, //
{ 0x2E, PacketTypesOut.SetBeaconEffect }, // Changed in 1.19 (No need to be implemented yet)
{ 0x2F, PacketTypesOut.HeldItemChange }, // (Wiki name: Set Carried Item (serverbound))
{ 0x30, PacketTypesOut.UpdateCommandBlock }, // (Wiki name: Program Command Block)
{ 0x31, PacketTypesOut.UpdateCommandBlockMinecart }, // (Wiki name: Program Command Block Minecart)
{ 0x32, PacketTypesOut.CreativeInventoryAction }, // (Wiki name: Set Creative Mode Slot)
{ 0x33, PacketTypesOut.UpdateJigsawBlock }, // (Wiki name: Program Jigsaw Block)
{ 0x34, PacketTypesOut.UpdateStructureBlock }, // (Wiki name: Program Structure Block)
{ 0x35, PacketTypesOut.UpdateSign }, // (Wiki name: Update Sign)
{ 0x36, PacketTypesOut.Animation }, // (Wiki name: Swing Arm)
{ 0x37, PacketTypesOut.Spectate }, // (Wiki name: Teleport To Entity)
{ 0x38, PacketTypesOut.PlayerBlockPlacement }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item On)
{ 0x39, PacketTypesOut.UseItem }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item)
};
private readonly Dictionary<int, ConfigurationPacketTypesIn> configurationTypesIn = new()
{
{ 0x00, ConfigurationPacketTypesIn.CookieRequest },
{ 0x01, ConfigurationPacketTypesIn.PluginMessage },
{ 0x02, ConfigurationPacketTypesIn.Disconnect },
{ 0x03, ConfigurationPacketTypesIn.FinishConfiguration },
{ 0x04, ConfigurationPacketTypesIn.KeepAlive },
{ 0x05, ConfigurationPacketTypesIn.Ping },
{ 0x06, ConfigurationPacketTypesIn.ResetChat },
{ 0x07, ConfigurationPacketTypesIn.RegistryData },
{ 0x08, ConfigurationPacketTypesIn.RemoveResourcePack },
{ 0x09, ConfigurationPacketTypesIn.ResourcePack },
{ 0x0A, ConfigurationPacketTypesIn.StoreCookie },
{ 0x0B, ConfigurationPacketTypesIn.Transfer },
{ 0x0C, ConfigurationPacketTypesIn.FeatureFlags },
{ 0x0D, ConfigurationPacketTypesIn.UpdateTags },
{ 0x0E, ConfigurationPacketTypesIn.KnownDataPacks },
{ 0x0F, ConfigurationPacketTypesIn.CustomReportDetails }, // Added in 1.21 (Not used)
{ 0x10, ConfigurationPacketTypesIn.ServerLinks } // Added in 1.21 (Not used)
};
private readonly Dictionary<int, ConfigurationPacketTypesOut> configurationTypesOut = new()
{
{ 0x00, ConfigurationPacketTypesOut.ClientInformation },
{ 0x01, ConfigurationPacketTypesOut.CookieResponse },
{ 0x02, ConfigurationPacketTypesOut.PluginMessage },
{ 0x03, ConfigurationPacketTypesOut.FinishConfiguration },
{ 0x04, ConfigurationPacketTypesOut.KeepAlive },
{ 0x05, ConfigurationPacketTypesOut.Pong },
{ 0x06, ConfigurationPacketTypesOut.ResourcePackResponse },
{ 0x07, ConfigurationPacketTypesOut.KnownDataPacks }
};
protected override Dictionary<int, PacketTypesIn> GetListIn() => typeIn;
protected override Dictionary<int, PacketTypesOut> GetListOut() => typeOut;
protected override Dictionary<int, ConfigurationPacketTypesIn> GetConfigurationListIn() => configurationTypesIn!;
protected override Dictionary<int, ConfigurationPacketTypesOut> GetConfigurationListOut() => configurationTypesOut!;
}

View file

@ -0,0 +1,243 @@
using System.Collections.Generic;
namespace MinecraftClient.Protocol.Handlers.PacketPalettes;
public class PacketPalette1212 : PacketTypePalette
{
private readonly Dictionary<int, PacketTypesIn> typeIn = new()
{
{ 0x00, PacketTypesIn.Bundle }, // Bundle delimiter
{ 0x01, PacketTypesIn.SpawnEntity }, // Add Entity
{ 0x02, PacketTypesIn.SpawnExperienceOrb }, // Add Experience Orb
{ 0x03, PacketTypesIn.EntityAnimation }, // Animate
{ 0x04, PacketTypesIn.Statistics }, // Award Stats
{ 0x05, PacketTypesIn.BlockChangedAck }, // Block Changed Ack
{ 0x06, PacketTypesIn.BlockBreakAnimation }, // Block Destruction
{ 0x07, PacketTypesIn.BlockEntityData }, // Block Entity Data
{ 0x08, PacketTypesIn.BlockAction }, // Block Event
{ 0x09, PacketTypesIn.BlockChange }, // Block Update
{ 0x0A, PacketTypesIn.BossBar }, // Boss Event
{ 0x0B, PacketTypesIn.ServerDifficulty }, // Change Difficulty
{ 0x0C, PacketTypesIn.ChunkBatchFinished }, // Chunk Batch Finished
{ 0x0D, PacketTypesIn.ChunkBatchStarted }, // Chunk Batch Start
{ 0x0E, PacketTypesIn.ChunksBiomes }, // Chunks Biomes
{ 0x0F, PacketTypesIn.ClearTiles }, // Clear Titles
{ 0x10, PacketTypesIn.TabComplete }, // Command Suggestions
{ 0x11, PacketTypesIn.DeclareCommands }, // Commands
{ 0x12, PacketTypesIn.CloseWindow }, // Container Close
{ 0x13, PacketTypesIn.WindowItems }, // Container Set Content
{ 0x14, PacketTypesIn.WindowProperty }, // Container Set Data
{ 0x15, PacketTypesIn.SetSlot }, // Container Set Slot
{ 0x16, PacketTypesIn.CookieRequest }, // Cookie Request
{ 0x17, PacketTypesIn.SetCooldown }, // Cooldown
{ 0x18, PacketTypesIn.ChatSuggestions }, // Custom Chat Completions
{ 0x19, PacketTypesIn.PluginMessage }, // Custom Payload
{ 0x1A, PacketTypesIn.DamageEvent }, // Damage Event
{ 0x1B, PacketTypesIn.DebugSample }, // Debug Sample
{ 0x1C, PacketTypesIn.HideMessage }, // Delete Chat
{ 0x1D, PacketTypesIn.Disconnect }, // Disconnect
{ 0x1E, PacketTypesIn.ProfilelessChatMessage }, // Disguised Chat
{ 0x1F, PacketTypesIn.EntityStatus }, // Entity Event
{ 0x20, PacketTypesIn.EntityPositionSync }, // Entity Position Sync (new in 1.21.2)
{ 0x21, PacketTypesIn.Explosion }, // Explode
{ 0x22, PacketTypesIn.UnloadChunk }, // Forget Level Chunk
{ 0x23, PacketTypesIn.ChangeGameState }, // Game Event
{ 0x24, PacketTypesIn.OpenHorseWindow }, // Horse Screen Open
{ 0x25, PacketTypesIn.HurtAnimation }, // Hurt Animation
{ 0x26, PacketTypesIn.InitializeWorldBorder }, // Initialize Border
{ 0x27, PacketTypesIn.KeepAlive }, // Keep Alive
{ 0x28, PacketTypesIn.ChunkData }, // Level Chunk With Light
{ 0x29, PacketTypesIn.Effect }, // Level Event
{ 0x2A, PacketTypesIn.Particle }, // Level Particles
{ 0x2B, PacketTypesIn.UpdateLight }, // Light Update
{ 0x2C, PacketTypesIn.JoinGame }, // Login
{ 0x2D, PacketTypesIn.MapData }, // Map Item Data
{ 0x2E, PacketTypesIn.TradeList }, // Merchant Offers
{ 0x2F, PacketTypesIn.EntityPosition }, // Move Entity Pos
{ 0x30, PacketTypesIn.EntityPositionAndRotation }, // Move Entity Pos Rot
{ 0x31, PacketTypesIn.MoveMinecartAlongTrack }, // Move Minecart Along Track (new in 1.21.2)
{ 0x32, PacketTypesIn.EntityRotation }, // Move Entity Rot
{ 0x33, PacketTypesIn.VehicleMove }, // Move Vehicle
{ 0x34, PacketTypesIn.OpenBook }, // Open Book
{ 0x35, PacketTypesIn.OpenWindow }, // Open Screen
{ 0x36, PacketTypesIn.OpenSignEditor }, // Open Sign Editor
{ 0x37, PacketTypesIn.Ping }, // Ping
{ 0x38, PacketTypesIn.PingResponse }, // Pong Response
{ 0x39, PacketTypesIn.CraftRecipeResponse }, // Place Ghost Recipe
{ 0x3A, PacketTypesIn.PlayerAbilities }, // Player Abilities
{ 0x3B, PacketTypesIn.ChatMessage }, // Player Chat
{ 0x3C, PacketTypesIn.EndCombatEvent }, // Player Combat End
{ 0x3D, PacketTypesIn.EnterCombatEvent }, // Player Combat Enter
{ 0x3E, PacketTypesIn.DeathCombatEvent }, // Player Combat Kill
{ 0x3F, PacketTypesIn.PlayerRemove }, // Player Info Remove
{ 0x40, PacketTypesIn.PlayerInfo }, // Player Info Update
{ 0x41, PacketTypesIn.FacePlayer }, // Player Look At
{ 0x42, PacketTypesIn.PlayerPositionAndLook }, // Player Position
{ 0x43, PacketTypesIn.PlayerRotation }, // Player Rotation (new in 1.21.2)
{ 0x44, PacketTypesIn.RecipeBookAdd }, // Recipe Book Add (new in 1.21.2, replaces UnlockRecipes)
{ 0x45, PacketTypesIn.RecipeBookRemove }, // Recipe Book Remove (new in 1.21.2)
{ 0x46, PacketTypesIn.RecipeBookSettings }, // Recipe Book Settings (new in 1.21.2)
{ 0x47, PacketTypesIn.DestroyEntities }, // Remove Entities
{ 0x48, PacketTypesIn.RemoveEntityEffect }, // Remove Mob Effect
{ 0x49, PacketTypesIn.ResetScore }, // Reset Score
{ 0x4A, PacketTypesIn.RemoveResourcePack }, // Resource Pack Pop
{ 0x4B, PacketTypesIn.ResourcePackSend }, // Resource Pack Push
{ 0x4C, PacketTypesIn.Respawn }, // Respawn
{ 0x4D, PacketTypesIn.EntityHeadLook }, // Rotate Head
{ 0x4E, PacketTypesIn.MultiBlockChange }, // Section Blocks Update
{ 0x4F, PacketTypesIn.SelectAdvancementTab }, // Select Advancements Tab
{ 0x50, PacketTypesIn.ServerData }, // Server Data
{ 0x51, PacketTypesIn.ActionBar }, // Set Action Bar Text
{ 0x52, PacketTypesIn.WorldBorderCenter }, // Set Border Center
{ 0x53, PacketTypesIn.WorldBorderLerpSize }, // Set Border Lerp Size
{ 0x54, PacketTypesIn.WorldBorderSize }, // Set Border Size
{ 0x55, PacketTypesIn.WorldBorderWarningDelay }, // Set Border Warning Delay
{ 0x56, PacketTypesIn.WorldBorderWarningReach }, // Set Border Warning Distance
{ 0x57, PacketTypesIn.Camera }, // Set Camera
{ 0x58, PacketTypesIn.UpdateViewPosition }, // Set Chunk Cache Center
{ 0x59, PacketTypesIn.UpdateViewDistance }, // Set Chunk Cache Radius
{ 0x5A, PacketTypesIn.SetCursorItem }, // Set Cursor Item (new in 1.21.2)
{ 0x5B, PacketTypesIn.SpawnPosition }, // Set Default Spawn Position
{ 0x5C, PacketTypesIn.DisplayScoreboard }, // Set Display Objective
{ 0x5D, PacketTypesIn.EntityMetadata }, // Set Entity Data
{ 0x5E, PacketTypesIn.AttachEntity }, // Set Entity Link
{ 0x5F, PacketTypesIn.EntityVelocity }, // Set Entity Motion
{ 0x60, PacketTypesIn.EntityEquipment }, // Set Equipment
{ 0x61, PacketTypesIn.SetExperience }, // Set Experience
{ 0x62, PacketTypesIn.UpdateHealth }, // Set Health
{ 0x63, PacketTypesIn.SetHeldSlot }, // Set Held Slot (new in 1.21.2, replaces HeldItemChange)
{ 0x64, PacketTypesIn.ScoreboardObjective }, // Set Objective
{ 0x65, PacketTypesIn.SetPassengers }, // Set Passengers
{ 0x66, PacketTypesIn.SetPlayerInventory }, // Set Player Inventory (new in 1.21.2)
{ 0x67, PacketTypesIn.Teams }, // Set Player Team
{ 0x68, PacketTypesIn.UpdateScore }, // Set Score
{ 0x69, PacketTypesIn.UpdateSimulationDistance }, // Set Simulation Distance
{ 0x6A, PacketTypesIn.SetTitleSubTitle }, // Set Subtitle Text
{ 0x6B, PacketTypesIn.TimeUpdate }, // Set Time
{ 0x6C, PacketTypesIn.SetTitleText }, // Set Title Text
{ 0x6D, PacketTypesIn.SetTitleTime }, // Set Titles Animation
{ 0x6E, PacketTypesIn.EntitySoundEffect }, // Sound Entity
{ 0x6F, PacketTypesIn.SoundEffect }, // Sound
{ 0x70, PacketTypesIn.StartConfiguration }, // Start Configuration
{ 0x71, PacketTypesIn.StopSound }, // Stop Sound
{ 0x72, PacketTypesIn.StoreCookie }, // Store Cookie
{ 0x73, PacketTypesIn.SystemChat }, // System Chat
{ 0x74, PacketTypesIn.PlayerListHeaderAndFooter }, // Tab List
{ 0x75, PacketTypesIn.NBTQueryResponse }, // Tag Query
{ 0x76, PacketTypesIn.CollectItem }, // Take Item Entity
{ 0x77, PacketTypesIn.EntityTeleport }, // Teleport Entity
{ 0x78, PacketTypesIn.SetTickingState }, // Ticking State
{ 0x79, PacketTypesIn.StepTick }, // Ticking Step
{ 0x7A, PacketTypesIn.Transfer }, // Transfer
{ 0x7B, PacketTypesIn.Advancements }, // Update Advancements
{ 0x7C, PacketTypesIn.EntityProperties }, // Update Attributes
{ 0x7D, PacketTypesIn.EntityEffect }, // Update Mob Effect
{ 0x7E, PacketTypesIn.DeclareRecipes }, // Update Recipes
{ 0x7F, PacketTypesIn.Tags }, // Update Tags
{ 0x80, PacketTypesIn.ProjectilePower }, // Projectile Power
{ 0x81, PacketTypesIn.CustomReportDetails }, // Custom Report Details
{ 0x82, PacketTypesIn.ServerLinks } // Server Links
};
private readonly Dictionary<int, PacketTypesOut> typeOut = new()
{
{ 0x00, PacketTypesOut.TeleportConfirm }, // Accept Teleportation
{ 0x01, PacketTypesOut.QueryBlockNBT }, // Block Entity Tag Query
{ 0x02, PacketTypesOut.BundleItemSelected }, // Bundle Item Selected (new in 1.21.2)
{ 0x03, PacketTypesOut.SetDifficulty }, // Change Difficulty
{ 0x04, PacketTypesOut.MessageAcknowledgment }, // Chat Ack
{ 0x05, PacketTypesOut.ChatCommand }, // Chat Command
{ 0x06, PacketTypesOut.SignedChatCommand }, // Chat Command Signed
{ 0x07, PacketTypesOut.ChatMessage }, // Chat
{ 0x08, PacketTypesOut.PlayerSession }, // Chat Session Update
{ 0x09, PacketTypesOut.ChunkBatchReceived }, // Chunk Batch Received
{ 0x0A, PacketTypesOut.ClientStatus }, // Client Command
{ 0x0B, PacketTypesOut.ClientTickEnd }, // Client Tick End (new in 1.21.2)
{ 0x0C, PacketTypesOut.ClientSettings }, // Client Information
{ 0x0D, PacketTypesOut.TabComplete }, // Command Suggestion
{ 0x0E, PacketTypesOut.AcknowledgeConfiguration }, // Configuration Acknowledged
{ 0x0F, PacketTypesOut.ClickWindowButton }, // Container Button Click
{ 0x10, PacketTypesOut.ClickWindow }, // Container Click
{ 0x11, PacketTypesOut.CloseWindow }, // Container Close
{ 0x12, PacketTypesOut.ChangeContainerSlotState }, // Container Slot State Changed
{ 0x13, PacketTypesOut.CookieResponse }, // Cookie Response
{ 0x14, PacketTypesOut.PluginMessage }, // Custom Payload
{ 0x15, PacketTypesOut.DebugSampleSubscription }, // Debug Sample Subscription
{ 0x16, PacketTypesOut.EditBook }, // Edit Book
{ 0x17, PacketTypesOut.EntityNBTRequest }, // Entity Tag Query
{ 0x18, PacketTypesOut.InteractEntity }, // Interact
{ 0x19, PacketTypesOut.GenerateStructure }, // Jigsaw Generate
{ 0x1A, PacketTypesOut.KeepAlive }, // Keep Alive
{ 0x1B, PacketTypesOut.LockDifficulty }, // Lock Difficulty
{ 0x1C, PacketTypesOut.PlayerPosition }, // Move Player Pos
{ 0x1D, PacketTypesOut.PlayerPositionAndRotation }, // Move Player Pos Rot
{ 0x1E, PacketTypesOut.PlayerRotation }, // Move Player Rot
{ 0x1F, PacketTypesOut.PlayerMovement }, // Move Player Status Only
{ 0x20, PacketTypesOut.VehicleMove }, // Move Vehicle
{ 0x21, PacketTypesOut.SteerBoat }, // Paddle Boat
{ 0x22, PacketTypesOut.PickItem }, // Pick Item
{ 0x23, PacketTypesOut.PingRequest }, // Ping Request
{ 0x24, PacketTypesOut.CraftRecipeRequest }, // Place Recipe
{ 0x25, PacketTypesOut.PlayerAbilities }, // Player Abilities
{ 0x26, PacketTypesOut.PlayerDigging }, // Player Action
{ 0x27, PacketTypesOut.EntityAction }, // Player Command
{ 0x28, PacketTypesOut.SteerVehicle }, // Player Input
{ 0x29, PacketTypesOut.Pong }, // Pong
{ 0x2A, PacketTypesOut.SetDisplayedRecipe }, // Recipe Book Change Settings
{ 0x2B, PacketTypesOut.SetRecipeBookState }, // Recipe Book Seen Recipe
{ 0x2C, PacketTypesOut.NameItem }, // Rename Item
{ 0x2D, PacketTypesOut.ResourcePackStatus }, // Resource Pack
{ 0x2E, PacketTypesOut.AdvancementTab }, // Seen Advancements
{ 0x2F, PacketTypesOut.SelectTrade }, // Select Trade
{ 0x30, PacketTypesOut.SetBeaconEffect }, // Set Beacon
{ 0x31, PacketTypesOut.HeldItemChange }, // Set Carried Item
{ 0x32, PacketTypesOut.UpdateCommandBlock }, // Set Command Block
{ 0x33, PacketTypesOut.UpdateCommandBlockMinecart }, // Set Command Minecart
{ 0x34, PacketTypesOut.CreativeInventoryAction }, // Set Creative Mode Slot
{ 0x35, PacketTypesOut.UpdateJigsawBlock }, // Set Jigsaw Block
{ 0x36, PacketTypesOut.UpdateStructureBlock }, // Set Structure Block
{ 0x37, PacketTypesOut.UpdateSign }, // Sign Update
{ 0x38, PacketTypesOut.Animation }, // Swing
{ 0x39, PacketTypesOut.Spectate }, // Teleport To Entity
{ 0x3A, PacketTypesOut.PlayerBlockPlacement }, // Use Item On
{ 0x3B, PacketTypesOut.UseItem }, // Use Item
};
private readonly Dictionary<int, ConfigurationPacketTypesIn> configurationTypesIn = new()
{
{ 0x00, ConfigurationPacketTypesIn.CookieRequest },
{ 0x01, ConfigurationPacketTypesIn.PluginMessage },
{ 0x02, ConfigurationPacketTypesIn.Disconnect },
{ 0x03, ConfigurationPacketTypesIn.FinishConfiguration },
{ 0x04, ConfigurationPacketTypesIn.KeepAlive },
{ 0x05, ConfigurationPacketTypesIn.Ping },
{ 0x06, ConfigurationPacketTypesIn.ResetChat },
{ 0x07, ConfigurationPacketTypesIn.RegistryData },
{ 0x08, ConfigurationPacketTypesIn.RemoveResourcePack },
{ 0x09, ConfigurationPacketTypesIn.ResourcePack },
{ 0x0A, ConfigurationPacketTypesIn.StoreCookie },
{ 0x0B, ConfigurationPacketTypesIn.Transfer },
{ 0x0C, ConfigurationPacketTypesIn.FeatureFlags },
{ 0x0D, ConfigurationPacketTypesIn.UpdateTags },
{ 0x0E, ConfigurationPacketTypesIn.KnownDataPacks },
{ 0x0F, ConfigurationPacketTypesIn.CustomReportDetails },
{ 0x10, ConfigurationPacketTypesIn.ServerLinks }
};
private readonly Dictionary<int, ConfigurationPacketTypesOut> configurationTypesOut = new()
{
{ 0x00, ConfigurationPacketTypesOut.ClientInformation },
{ 0x01, ConfigurationPacketTypesOut.CookieResponse },
{ 0x02, ConfigurationPacketTypesOut.PluginMessage },
{ 0x03, ConfigurationPacketTypesOut.FinishConfiguration },
{ 0x04, ConfigurationPacketTypesOut.KeepAlive },
{ 0x05, ConfigurationPacketTypesOut.Pong },
{ 0x06, ConfigurationPacketTypesOut.ResourcePackResponse },
{ 0x07, ConfigurationPacketTypesOut.KnownDataPacks }
};
protected override Dictionary<int, PacketTypesIn> GetListIn() => typeIn;
protected override Dictionary<int, PacketTypesOut> GetListOut() => typeOut;
protected override Dictionary<int, ConfigurationPacketTypesIn> GetConfigurationListIn() => configurationTypesIn!;
protected override Dictionary<int, ConfigurationPacketTypesOut> GetConfigurationListOut() => configurationTypesOut!;
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using MinecraftClient.Protocol.Handlers.PacketPalettes;
namespace MinecraftClient.Protocol.Handlers
@ -48,7 +48,7 @@ namespace MinecraftClient.Protocol.Handlers
{
PacketTypePalette p = protocol switch
{
> Protocol18Handler.MC_1_20_4_Version => throw new NotImplementedException(Translations
> Protocol18Handler.MC_1_21_2_Version => throw new NotImplementedException(Translations
.exception_palette_packet),
<= Protocol18Handler.MC_1_8_Version => new PacketPalette17(),
<= Protocol18Handler.MC_1_11_2_Version => new PacketPalette110(),
@ -67,7 +67,10 @@ namespace MinecraftClient.Protocol.Handlers
<= Protocol18Handler.MC_1_19_4_Version => new PacketPalette1194(),
<= Protocol18Handler.MC_1_20_Version => new PacketPalette1194(),
<= Protocol18Handler.MC_1_20_2_Version => new PacketPalette1202(),
_ => new PacketPalette1204()
<= Protocol18Handler.MC_1_20_4_Version => new PacketPalette1204(),
<= Protocol18Handler.MC_1_20_6_Version => new PacketPalette1206(),
<= Protocol18Handler.MC_1_21_Version => new PacketPalette121(),
_ => new PacketPalette1212()
};
p.SetForgeEnabled(forgeEnabled);

View file

@ -1,4 +1,4 @@
namespace MinecraftClient.Protocol.Handlers
namespace MinecraftClient.Protocol.Handlers
{
/// <summary>
/// Incoming packet types
@ -29,9 +29,12 @@
CloseWindow, //
CollectItem, //
CombatEvent, //
CookieRequest, // Added in 1.20.6
CraftRecipeResponse, //
CustomReportDetails, // Added in 1.21 (Not used)
DamageEvent, // Added in 1.19.4
DeathCombatEvent, //
DebugSample, // Added in 1.20.6
DeclareCommands, //
DeclareRecipes, //
DestroyEntities, //
@ -48,6 +51,7 @@
EntityMovement, //
EntityPosition, //
EntityPositionAndRotation, //
EntityPositionSync, // Added in 1.21.2
EntityProperties, //
EntityRotation, //
EntitySoundEffect, //
@ -55,6 +59,7 @@
EntityTeleport, //
EntityVelocity, //
Explosion, //
MoveMinecartAlongTrack, // Added in 1.21.2
FacePlayer, //
FeatureFlags, // Added in 1.19.3
HeldItemChange, //
@ -81,22 +86,31 @@
PlayerListHeaderAndFooter, //
PlayerRemove, // Added in 1.19.3 (Not used)
PlayerPositionAndLook, //
PlayerRotation, // Added in 1.21.2
PluginMessage, //
ProfilelessChatMessage, // Added in 1.19.3
ProjectilePower, // Added in 1.20.6
RemoveEntityEffect, //
RemoveResourcePack, // Added in 1.20.3
ResetScore, // Added in 1.20.3
ResourcePackSend, //
Respawn, //
RecipeBookAdd, // Added in 1.21.2 (replaces UnlockRecipes)
RecipeBookRemove, // Added in 1.21.2
RecipeBookSettings, // Added in 1.21.2
ScoreboardObjective, //
SelectAdvancementTab, //
ServerData, // Added in 1.19
ServerDifficulty, //
ServerLinks, // Added in 1.21 (Not used)
SetCompression, // For 1.8 or below
SetCooldown, //
SetCursorItem, // Added in 1.21.2
SetDisplayChatPreview, // Added in 1.19
SetExperience, //
SetHeldSlot, // Added in 1.21.2 (replaces HeldItemChange clientbound)
SetPassengers, //
SetPlayerInventory, // Added in 1.21.2
SetSlot, //
SetTickingState, // Added in 1.20.3
StepTick, // Added in 1.20.3
@ -115,6 +129,7 @@
StartConfiguration, // Added in 1.20.2
Statistics, //
StopSound, //
StoreCookie, // Added in 1.20.6
SystemChat, // Added in 1.19
TabComplete, //
Tags, //
@ -122,6 +137,7 @@
TimeUpdate, //
Title, //
TradeList, //
Transfer, // Added in 1.20.6
Unknown, // For old version packet that have been removed and not used by mcc
UnloadChunk, //
UnlockRecipes, //

View file

@ -1,4 +1,4 @@
namespace MinecraftClient.Protocol.Handlers
namespace MinecraftClient.Protocol.Handlers
{
/// <summary>
/// Outgoing packet types
@ -8,6 +8,7 @@
AcknowledgeConfiguration, // Added in 1.20.2
AdvancementTab, //
Animation, //
BundleItemSelected, // Added in 1.21.2
ChangeContainerSlotState, // Added in 1.20.3
ChatCommand, // Added in 1.19
ChatMessage, //
@ -17,9 +18,12 @@
ClickWindowButton, //
ClientSettings, //
ClientStatus, //
ClientTickEnd, // Added in 1.21.2
CloseWindow, //
CraftRecipeRequest, //
CreativeInventoryAction, //
CookieResponse, // Added in 1.20.6
DebugSampleSubscription, // Added in 1.20.6
EditBook, //
EnchantItem, // For 1.13.2 or below
EntityAction, //
@ -28,6 +32,7 @@
HeldItemChange, //
InteractEntity, //
KeepAlive, //
KnownDataPacks, // Added in 1.20.6
LockDifficulty, //
MessageAcknowledgment, // Added in 1.19.1 (1.19.2)
NameItem, //
@ -52,6 +57,7 @@
SetDifficulty, //
SetDisplayedRecipe, // Added in 1.16.2
SetRecipeBookState, // Added in 1.16.2
SignedChatCommand, // Added in 1.20.6
Spectate, //
SteerBoat, //
SteerVehicle, //

View file

@ -236,6 +236,16 @@ namespace MinecraftClient.Protocol.Handlers
return netRead != null ? netRead.Item1.ManagedThreadId : -1;
}
public bool SendCookieResponse(string name, byte[]? data)
{
throw new NotImplementedException();
}
public bool SendKnownDataPacks(List<(string, string, string)> knownDataPacks)
{
throw new NotImplementedException();
}
public void Dispose()
{
try

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary>
/// Wrapper for handling unencrypted & encrypted socket
/// </summary>
class SocketWrapper
public class SocketWrapper
{
readonly TcpClient c;
AesCfb8Stream? s;

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class AttributeModifiersComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfAttributes { get; set; }
public List<SubComponent> Attributes { get; set; } = new();
public bool ShowInTooltip { get; set; }
public override void Parse(Queue<byte> data)
{
NumberOfAttributes = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < NumberOfAttributes; i++)
Attributes.Add(subComponentRegistry.ParseSubComponent(SubComponents.Attribute, data));
ShowInTooltip = dataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(NumberOfAttributes));
if(Attributes.Count != NumberOfAttributes)
throw new ArgumentNullException($"Can not serialize a AttributeModifiersComponent when the Attributes count != NumberOfAttributes!");
foreach (var attribute in Attributes)
data.AddRange(attribute.Serialize());
data.AddRange(DataTypes.GetBool(ShowInTooltip));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class BannerPatternsComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfLayers { get; set; }
public List<BannerLayer> Layers { get; set; } = [];
public override void Parse(Queue<byte> data)
{
NumberOfLayers = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < NumberOfLayers; i++)
{
var patternType = dataTypes.ReadNextVarInt(data);
Layers.Add(new BannerLayer
{
PatternType = patternType,
AssetId = patternType == 0 ? dataTypes.ReadNextString(data) : null,
TranslationKey = patternType == 0 ? dataTypes.ReadNextString(data) : null,
DyeColor = dataTypes.ReadNextVarInt(data)
});
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(NumberOfLayers));
if (NumberOfLayers > 0)
{
if (NumberOfLayers != Layers.Count)
throw new Exception("Can't serialize BannerPatternsComponent because NumberOfLayers and Layers.Count differ!");
foreach (var bannerLayer in Layers)
{
data.AddRange(DataTypes.GetVarInt(bannerLayer.PatternType));
if (bannerLayer.PatternType == 0)
{
if(string.IsNullOrEmpty(bannerLayer.AssetId) || string.IsNullOrEmpty(bannerLayer.TranslationKey))
throw new Exception("Can't serialize BannerPatternsComponent because AssetId or TranslationKey is null/empty!");
data.AddRange(DataTypes.GetString(bannerLayer.AssetId));
data.AddRange(DataTypes.GetString(bannerLayer.TranslationKey));
}
data.AddRange(DataTypes.GetVarInt(bannerLayer.DyeColor));
}
}
return new Queue<byte>(data);
}
}
public class BannerLayer
{
public int PatternType { get; set; }
public string? AssetId { get; set; } = null!;
public string? TranslationKey { get; set; } = null!;
public int DyeColor { get; set; }
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class BaseColorComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int DyeColor { get; set; }
public override void Parse(Queue<byte> data)
{
DyeColor = dataTypes.ReadNextVarInt(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(DyeColor));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class BeesComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfBees { get; set; }
public List<Bee> Bees { get; set; } = [];
public override void Parse(Queue<byte> data)
{
NumberOfBees = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < NumberOfBees; i++)
{
Bees.Add(new Bee(dataTypes.ReadNextNbt(data), dataTypes.ReadNextVarInt(data), dataTypes.ReadNextVarInt(data)));
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(NumberOfBees));
if (NumberOfBees > 0)
{
if (NumberOfBees != Bees.Count)
throw new Exception("Can't serialize the BeeComponent because NumberOfBees and Bees.Count differ!");
foreach (var bee in Bees)
{
data.AddRange(DataTypes.GetNbt(bee.EntityDataNbt));
data.AddRange(DataTypes.GetVarInt(bee.TicksInHive));
data.AddRange(DataTypes.GetVarInt(bee.MinTicksInHive));
}
}
return new Queue<byte>(data);
}
}
public record Bee(Dictionary<string, object>? EntityDataNbt, int TicksInHive, int MinTicksInHive);

View file

@ -0,0 +1,31 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class BlockStateComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public List<(string, string)> Properties { get; set; } = [];
public override void Parse(Queue<byte> data)
{
var count = dataTypes.ReadNextVarInt(data);
for(var i = 0; i < count; i++)
Properties.Add((dataTypes.ReadNextString(data), dataTypes.ReadNextString(data)));
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Properties.Count));
foreach (var (key, value) in Properties)
{
data.AddRange(DataTypes.GetString(key));
data.AddRange(DataTypes.GetString(value));
}
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,35 @@
using System.Collections.Generic;
using MinecraftClient.Inventory;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class BundleContentsComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public List<Item> Items { get; set; } = [];
public override void Parse(Queue<byte> data)
{
var count = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < count; i++)
{
var item = dataTypes.ReadNextItemSlot(data, itemPalette);
if (item != null)
Items.Add(item);
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Items.Count));
foreach (var item in Items)
data.AddRange(DataTypes.GetItemSlot(item, itemPalette));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class CanBreakComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfPredicates { get; set; }
public List<BlockPredicateSubcomponent> BlockPredicates { get; set; } = new();
public bool ShowInTooltip { get; set; }
public override void Parse(Queue<byte> data)
{
NumberOfPredicates = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < NumberOfPredicates; i++)
BlockPredicates.Add((BlockPredicateSubcomponent)subComponentRegistry.ParseSubComponent(SubComponents.BlockPredicate, data));
ShowInTooltip = dataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(NumberOfPredicates));
if(NumberOfPredicates > 0 && BlockPredicates.Count == 0)
throw new ArgumentNullException($"Can not serialize a CanBreakComponent when the BlockPredicates is empty but NumberOfPredicates is > 0!");
foreach (var blockPredicate in BlockPredicates)
data.AddRange(blockPredicate.Serialize());
data.AddRange(DataTypes.GetBool(ShowInTooltip));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class CanPlaceOnComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfPredicates { get; set; }
public List<BlockPredicateSubcomponent> BlockPredicates { get; set; } = new();
public bool ShowInTooltip { get; set; }
public override void Parse(Queue<byte> data)
{
NumberOfPredicates = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < NumberOfPredicates; i++)
BlockPredicates.Add((BlockPredicateSubcomponent)subComponentRegistry.ParseSubComponent(SubComponents.BlockPredicate, data));
ShowInTooltip = dataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(NumberOfPredicates));
if(NumberOfPredicates > 0 && BlockPredicates.Count == 0)
throw new ArgumentNullException($"Can not serialize a CanPlaceOnComponent when the BlockPredicates is empty but NumberOfPredicates is > 0!");
foreach (var blockPredicate in BlockPredicates)
data.AddRange(blockPredicate.Serialize());
data.AddRange(DataTypes.GetBool(ShowInTooltip));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,35 @@
using System.Collections.Generic;
using MinecraftClient.Inventory;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class ChargedProjectilesComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public List<Item> Items { get; set; } = [];
public override void Parse(Queue<byte> data)
{
var count = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < count; i++)
{
var item = dataTypes.ReadNextItemSlot(data, itemPalette);
if (item != null)
Items.Add(item);
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Items.Count));
foreach (var item in Items)
data.AddRange(DataTypes.GetItemSlot(item, itemPalette));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,29 @@
using System.Collections.Generic;
using MinecraftClient.Inventory;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class ContainerComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public List<Item?> Items { get; set; } = [];
public override void Parse(Queue<byte> data)
{
var count = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < count; i++)
Items.Add(dataTypes.ReadNextItemSlot(data, ItemPalette));
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Items.Count));
foreach (var item in Items)
data.AddRange(DataTypes.GetItemSlot(item, itemPalette));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class ContainerLootComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public Dictionary<string, object>? Nbt { get; set; }
public override void Parse(Queue<byte> data)
{
Nbt = dataTypes.ReadNextNbt(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetNbt(Nbt));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,8 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class CreativeSlotLockComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: EmptyComponent(dataTypes, itemPalette, subComponentRegistry);

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class CustomDataComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public Dictionary<string, object>? Nbt { get; set; } = new();
public override void Parse(Queue<byte> data)
{
Nbt = dataTypes.ReadNextNbt(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetNbt(Nbt));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,22 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class CustomModelDataComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Value { get; set; }
public override void Parse(Queue<byte> data)
{
Value = dataTypes.ReadNextVarInt(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Value));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,26 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
using MinecraftClient.Protocol.Message;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class CustomNameComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public string CustomName { get; set; } = string.Empty;
public Dictionary<string, object>? CustomNameNbt { get; set; }
public override void Parse(Queue<byte> data)
{
CustomNameNbt = dataTypes.ReadNextNbt(data);
CustomName = ChatParser.ParseText(CustomNameNbt);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetNbt(CustomNameNbt));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class DamageComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Damage { get; set; }
public override void Parse(Queue<byte> data)
{
Damage = dataTypes.ReadNextVarInt(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Damage));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class DebugStickStateComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public Dictionary<string, object>? Nbt { get; set; }
public override void Parse(Queue<byte> data)
{
Nbt = dataTypes.ReadNextNbt(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetNbt(Nbt));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,26 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class DyeColorComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Color { get; set; }
public bool ShowInTooltip { get; set; }
public override void Parse(Queue<byte> data)
{
Color = dataTypes.ReadNextInt(data);
ShowInTooltip = dataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetInt(Color));
data.AddRange(DataTypes.GetBool(ShowInTooltip));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class EnchantmentGlintOverrideComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public bool HasGlint { get; set; }
public override void Parse(Queue<byte> data)
{
HasGlint = dataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetBool(HasGlint));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,41 @@
using System.Collections.Generic;
using MinecraftClient.Inventory;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class EnchantmentsComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfEnchantments { get; set; }
public List<Enchantment> Enchantments { get; set; } = new();
public bool ShowTooltip { get; set; }
public override void Parse(Queue<byte> data)
{
NumberOfEnchantments = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < NumberOfEnchantments; i++)
{
var registryId = dataTypes.ReadNextVarInt(data);
var level = dataTypes.ReadNextVarInt(data);
Enchantments.Add(new Enchantment(EnchantmentMapping.GetEnchantmentByRegistryId1206(registryId), level));
}
ShowTooltip = dataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Enchantments.Count));
foreach (var enchantment in Enchantments)
{
data.AddRange(DataTypes.GetVarInt(EnchantmentMapping.GetRegistryId1206ByEnchantment(enchantment.Type)));
data.AddRange(DataTypes.GetVarInt(enchantment.Level));
}
data.AddRange(DataTypes.GetBool(ShowTooltip));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,29 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class EntityDataComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public Dictionary<string, object>? Nbt { get; set; }
public override void Parse(Queue<byte> data)
{
Nbt = dataTypes.ReadNextNbt(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetNbt(Nbt));
return new Queue<byte>(data);
}
}
public class BucketEntityDataComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: EntityDataComponent(dataTypes, itemPalette, subComponentRegistry) {}
public class BlockEntityDataComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: EntityDataComponent(dataTypes, itemPalette, subComponentRegistry) {}

View file

@ -0,0 +1,7 @@
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class FireResistantComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: EmptyComponent(dataTypes, itemPalette, subComponentRegistry);

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Mapping;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class FireworkExplosionComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public FireworkExplosionSubComponent? FireworkExplosionSubComponent { get; set; }
public override void Parse(Queue<byte> data)
{
FireworkExplosionSubComponent = (FireworkExplosionSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.FireworkExplosion, data);
}
public override Queue<byte> Serialize()
{
return FireworkExplosionSubComponent!.Serialize();
}
}

View file

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Mapping;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class FireworksComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int FlightDuration { get; set; }
public int NumberOfExplosions { get; set; }
public List<FireworkExplosionSubComponent> Explosions { get; set; } = [];
public override void Parse(Queue<byte> data)
{
FlightDuration = dataTypes.ReadNextVarInt(data);
NumberOfExplosions = dataTypes.ReadNextVarInt(data);
if (NumberOfExplosions > 0)
{
for(var i = 0; i < NumberOfExplosions; i++)
Explosions.Add(
(FireworkExplosionSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.FireworkExplosion,
data));
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(FlightDuration));
data.AddRange(DataTypes.GetVarInt(NumberOfExplosions));
if (NumberOfExplosions > 0)
{
if (NumberOfExplosions != Explosions.Count)
throw new Exception("Can't serialize FireworksComponent because NumberOfExplosions and the lenght of Explosions differ!");
foreach(var explosion in Explosions)
data.AddRange(explosion.Serialize().ToList());
}
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class FoodComponentComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Nutrition { get; set; }
public float Saturation { get; set; }
public bool CanAlwaysEat { get; set; }
public float SecondsToEat { get; set; }
public List<EffectSubComponent> Effects { get; set; } = new();
public override void Parse(Queue<byte> data)
{
Nutrition = dataTypes.ReadNextVarInt(data);
Saturation = dataTypes.ReadNextFloat(data);
CanAlwaysEat = dataTypes.ReadNextBool(data);
SecondsToEat = dataTypes.ReadNextFloat(data);
var numberOfEffects = dataTypes.ReadNextVarInt(data);
for(var i = 0; i < numberOfEffects; i++)
Effects.Add((EffectSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.Effect, data));
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Nutrition));
data.AddRange(DataTypes.GetFloat(Saturation));
data.AddRange(DataTypes.GetBool(CanAlwaysEat));
data.AddRange(DataTypes.GetFloat(SecondsToEat));
data.AddRange(DataTypes.GetVarInt(Effects.Count));
foreach(var effect in Effects)
data.AddRange(effect.Serialize());
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,7 @@
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class HideAdditionalTooltipComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: EmptyComponent(dataTypes, itemPalette, subComponentRegistry);

View file

@ -0,0 +1,7 @@
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class HideTooltipComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: EmptyComponent(dataTypes, itemPalette, subComponentRegistry);

View file

@ -0,0 +1,68 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class InstrumentComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
// holder ID: 0 = inline instrument data, N>0 = registry reference (id = N-1)
public int InstrumentHolderId { get; set; }
// Inline instrument fields (only when InstrumentHolderId == 0):
// holder ID for SoundEvent: 0 = inline sound, N>0 = registry reference (id = N-1)
public int SoundEventHolderId { get; set; }
// Inline SoundEvent fields (only when SoundEventHolderId == 0):
public string? SoundLocation { get; set; }
public bool HasFixedRange { get; set; }
public float FixedRange { get; set; }
public int UseDuration { get; set; }
public float Range { get; set; }
public override void Parse(Queue<byte> data)
{
InstrumentHolderId = dataTypes.ReadNextVarInt(data);
if (InstrumentHolderId == 0)
{
SoundEventHolderId = dataTypes.ReadNextVarInt(data);
if (SoundEventHolderId == 0)
{
SoundLocation = dataTypes.ReadNextString(data);
HasFixedRange = dataTypes.ReadNextBool(data);
if (HasFixedRange)
FixedRange = dataTypes.ReadNextFloat(data);
}
UseDuration = dataTypes.ReadNextVarInt(data);
Range = dataTypes.ReadNextFloat(data);
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(InstrumentHolderId));
if (InstrumentHolderId == 0)
{
data.AddRange(DataTypes.GetVarInt(SoundEventHolderId));
if (SoundEventHolderId == 0)
{
data.AddRange(DataTypes.GetString(SoundLocation ?? ""));
data.AddRange(DataTypes.GetBool(HasFixedRange));
if (HasFixedRange)
data.AddRange(DataTypes.GetFloat(FixedRange));
}
data.AddRange(DataTypes.GetVarInt(UseDuration));
data.AddRange(DataTypes.GetFloat(Range));
}
return new Queue<byte>(data);
}
}

Some files were not shown because too many files have changed in this diff Show more