- ItemPalette1216: 1415 items (generated from decompiled Items.java)
- EntityPalette1216: 151 entities (HappyGhast at index 56, all after +1)
- Palette1216: block states (DriedGhast 32 states at 13826-13857, all after +32)
- PacketPalette1216: clientbound +3 (Waypoint, ClearDialog, ShowDialog),
serverbound +2 (ChangeGameMode at 0x04 shifting all after, CustomClickAction at end),
config clientbound +2 (ClearDialog, ShowDialog),
config serverbound +1 (CustomClickAction)
- Version routing in Protocol18.cs, PacketType18Handler.cs, EntityMetadataPalette.cs
updated to select 1216 palettes for protocol >= 771
- EntityMetadataPalette reuses 1215 (EntityDataSerializers unchanged)
Made-with: Cursor
Add complete protocol 769 support for Minecraft 1.21.4:
- Version constants: Add 769 to supported versions, MC_1_21_4_Version constant,
and version string mappings (including 1.21.3 -> 768 compatibility)
- Item palette: 10 new items (Resin series + Eyeblossom), generated ItemPalette1214
- Entity palette: Remove CreakingTransient (149 entities, down from 150)
- Block palette: 10 new blocks with correct blockstate ID ranges from server data
- Packet palette: Serverbound packet ID reshuffling - PickItem split into
PickItemFromBlock/PickItemFromEntity, new PlayerLoaded packet inserted after
PlayerInput, subsequent IDs shifted accordingly. Clientbound unchanged.
- PlayerLoaded: Send empty PlayerLoaded packet after JoinGame processing (>= 1.21.4)
- EntityMetadata/DataComponents: Reuse 1.20.6 palettes (unchanged registries)
- Update all version guard checks from MC_1_21_2 to MC_1_21_4
Made-with: Cursor
1.20.6 introduced three new EntityDataSerializer types compared to 1.20.4:
- PARTICLES (id 18) - list of particles, inserted after PARTICLE
- WOLF_VARIANT (id 23) - wolf variant holder, inserted after CAT_VARIANT
- ARMADILLO_STATE (id 28) - armadillo state, inserted after SNIFFER_STATE
These insertions shifted subsequent serializer IDs, causing the 1.19.4
palette (EntityMetadataPalette1194) to misidentify metadata types on
1.20.6+ servers. This could lead to incorrect byte consumption and
potential packet parse failures when entities with affected metadata
types (e.g. wolves, armadillos, area effect clouds with particles)
were present.
Changes:
- Add Particles, WolfVariant, ArmadilloState to EntityMetaDataType enum
- Create EntityMetadataPalette1206 with correct 31-entry ID mapping
- Route 1.20.6+ to the new palette in EntityMetadataPalette.GetPalette()
- Add read logic for the three new types in DataTypes.cs
Verified on 1.21.1 vanilla server: cat, wolf, frog, armadillo, painting
entities all spawn without metadata parse errors.
Made-with: Cursor
Fix the Explosion packet handler that was truncating reads at the
knockback fields, leaving BlockInteraction, particles, and SoundEvent
bytes unconsumed for 1.20.4+. The old commented-out code had three bugs:
conditional particle read (should always read both small and large),
reading SoundEvent as a plain string (it's a Holder<SoundEvent> encoded
as VarInt id + optional inline DIRECT_STREAM_CODEC), and an incorrect
fixedRange version gate. Verified against decompiled ClientboundExplodePacket
from both 1.20.6 and 1.21.1 — the wire format is identical across versions.
Update LoadDefaultAttributes() fallback to match the 1.21.1 registry
order (31 attributes), adding 9 new entries: burning_time,
explosion_knockback_resistance, mining_efficiency, movement_efficiency,
oxygen_bonus, sneaking_speed, submerged_mining_speed,
sweeping_damage_ratio, and water_movement_efficiency. This fallback is
only used when the server omits the attribute RegistryData packet.
Made-with: Cursor
After the previous commit (99ac3d0) moved attribute lookup from a hardcoded
dictionary to the dynamic RegistryData, MCC would crash immediately upon
joining a vanilla 1.20.6 server with:
System.ArgumentException: An item with the same key has already been added.
Key: unknown
Root cause: When KnownDataPacks negotiation tells the server that MCC already
has the "minecraft" data pack, the server skips sending RegistryData for
registries it considers "known" — including minecraft:attribute. This left
the dynamic attribute map empty, so every VarInt attribute ID resolved to
"unknown". The EntityProperties packet often contains multiple attributes
(e.g. armor, max_health, movement_speed), and `keys.Add("unknown", ...)` on
the second "unknown" attribute threw ArgumentException.
Two fixes applied:
1. World.GetAttributeNameById(): When the dynamic attribute map is empty
(server didn't send the registry), automatically load the vanilla 1.20.6
default attribute order (22 entries matching Attributes.java registration
order). This mirrors the pattern used for dimensions where defaults are
loaded when RegistryData is not sent. If a modded server sends a custom
attribute registry, the dynamic map takes precedence.
2. Protocol18.cs EntityProperties handler: Change `keys.Add(propertyKey,
propertyValue2)` to `keys[propertyKey] = propertyValue2` to tolerate
duplicate keys defensively, in case an unknown attribute ID still appears.
Tested: MCC now connects to a vanilla 1.20.6 offline-mode server, stays
online for 6+ minutes with no crashes or disconnections. Verified: chat
messages received, inventory listing (item names/counts correct), entity
detection, TPS query, and health query all work correctly.
Made-with: Cursor
In 1.20.6+, EntityProperties packets reference attributes by VarInt registry
IDs instead of string names. Previously, a hardcoded dictionary of 22 attribute
entries (matching the vanilla 1.20.6 registry) was used to map these IDs back
to names. This works for vanilla servers but would fail silently for modded
servers that add custom attributes — any unknown ID would be reported as
"unknown".
This commit replaces the hardcoded attribute dictionary with dynamic registry
parsing, following the same pattern already used for dimension_type and
chat_type registries:
- World.cs: Add static `attributeIdMap` field, `SetAttributeIdMap()` and
`GetAttributeNameById()` methods for storing/querying attribute names by
their VarInt registry IDs.
- Protocol18.cs (RegistryData handler): When the server sends a
`minecraft:attribute` registry during the Configuration phase, parse all
entries and store the ID→name mapping. The `minecraft:` prefix is stripped
from entry names to match the format used in EntityProperties packets
(e.g. "minecraft:generic.armor" → "generic.armor").
- Protocol18.cs (EntityProperties handler): Remove the hardcoded 22-entry
`attributeDictionary` and use `World.GetAttributeNameById()` instead.
Unknown IDs still fall back to "unknown" for safety.
Also closes issue #4 (Disconnect packet extra boolean) — verified that both
Play and Configuration phase Disconnect handlers already use `ReadNextChat()`
(NBT format since 1.20.4+), matching the 1.20.6 protocol spec. No code
changes needed; updated tracking document to mark as closed.
Made-with: Cursor
Two critical issues in the 1.20.6 configuration phase that could cause
connection instability and packet desync:
1. RegistryData: The handler used an early `break` when it encountered
a registryId other than "minecraft:dimension_type" or
"minecraft:chat_type". This skipped reading the remaining entries
for that registry, leaving unconsumed data in the packet buffer.
Subsequent packet reads would start at the wrong offset, causing
cascading parse failures and eventual disconnection.
Fix: Always read all entries (entryId + hasData + optional NBT)
for every registry, regardless of whether we process it. For
dimension_type entries, if the server sends inline NBT data (i.e.
non-vanilla dimensions from mods/datapacks), parse and store
the dimension directly via World.StoreOneDimension(). Only fall
back to hardcoded defaults when no dimension data was received.
2. KnownDataPacks: The client echoed back ALL packs the server
listed, including non-vanilla ones. This told the server "I have
these packs cached" when the client actually did not, so the
server would skip sending full registry data for those packs.
The result: incomplete registries for modded/datapack content.
Fix: Filter the response to only include packs with the
"minecraft" namespace. Non-vanilla packs are omitted, forcing
the server to send their full registry data inline.
Also adds supporting methods to World.cs:
- SetDimensionIdMap(): Store VarInt ID -> dimension name mapping
from RegistryData entries (needed by JoinGame/Respawn)
- GetDimensionNameById(): Look up dimension name by numeric ID
- HasAnyDimension(): Check if any dimensions were loaded from
server-provided data
Made-with: Cursor
Added Farm bot crops handling for 1.20/.1
Added utilities for Containers/Inventories
Added bot movement lock to prevent multiple bots that use movements from running at the same time.
General code improvements.