Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions Data Asset Sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The Java data generator and its setup steps are in [generator/README.md](generat

### data/bedrock/block_palette.nbt

[GeyserMC/Geyser](https://github.com/GeyserMC/Geyser/blob/50115039af4cd92e50545075d3a13eea6880cf88/core/src/main/resources/bedrock/block_palette.26_50.nbt)
[GeyserMC/Geyser](https://github.com/GeyserMC/Geyser/blob/a24ba9c8f07b38be6455e5e86d187a2ef2ffa6a8/core/src/main/resources/bedrock/block_palette.26_60.nbt)

### data/bedrock/block_sounds.json

Expand Down Expand Up @@ -61,7 +61,7 @@ This file has been generated using `./gradlew generateBedrockParticleList` from

### data/bedrock/runtime_item_states.json

[CloudburstMC/Data](https://github.com/CloudburstMC/Data/blob/a8a4341d7763d6eb8547cff3ca46b4153d60163d/runtime_item_states.json)
[CloudburstMC/Data](https://github.com/GeyserMC/Geyser/blob/a24ba9c8f07b38be6455e5e86d187a2ef2ffa6a8/core/src/main/resources/bedrock/runtime_item_states.26_60.json)

### data/bedrock/sounds.json

Expand Down Expand Up @@ -110,3 +110,22 @@ These files have been generated using `./gradlew generateBedrockPacks` from the
### skin_packs/*

These files have been generated using `./gradlew generateBedrockPacks` from the official bedrock client's assets folder.

### Bedrock 1.26.60 source snapshot

The protocol update uses [Mojang protocol 2225 metadata](https://github.com/Mojang/bedrock-protocol-docs/releases/tag/v1.26.60).
Client resources come from the [1.26.60.5 GDK archive](https://github.com/bubbles-wow/mcbe-gdk-unpack-archive/releases/tag/1.26.60.5).
The archive SHA-256 is `a36945ad3b28d762d31d4533168a102294b55e8f88fe2c570485493fb3d15f08`.
The resource generators use its non-empty original files and unpacked archives.
Particle identifiers include compiled definitions with formats 1.26.10, 1.26.30, and 1.26.50.

The palette keeps state version 1.21.60.33 while adding connection properties to redstone, fire, and chorus plants.
The connection upgrade adds missing properties and preserves explicit values at that unchanged version.
New experimental blocks, entities, particles, and sounds use Java shape or type fallbacks where direct equivalents are absent.
These fallbacks do not establish complete behavior or visual parity for the experimental features.

The entity registry retains the stable 26.60.6 BDS table captured through an offline NetherNet bootstrap.
It adds `minecraft:ice_ball` with numeric ID 156 to the previous stable table.
The generated experimental sound table also requires `minecraft:frostbite`.
Its identifier, spawn egg, and numeric ID 155 come from the matching client definition and `ActorType` metadata.
The Frostbite entry is a curated experimental addition, not part of the default server registry capture.
11 changes: 11 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ dependencies {
toolImplementation "org.jsoup:jsoup:1.23.2"
toolImplementation "org.ow2.asm:asm-tree:9.11.1"
toolImplementation "net.lenni0451.commons:asm:1.9.2"

testImplementation "com.viaversion:viaversion-common:5.12.0"
testImplementation "com.google.guava:guava:33.7.1-jre"
testImplementation "io.netty:netty-handler:4.2.18.Final"
testImplementation "org.junit.jupiter:junit-jupiter:6.1.3"
testImplementation sourceSets.tool.output
testRuntimeOnly "org.junit.platform:junit-platform-launcher:6.1.3"
}

test {
useJUnitPlatform()
}

def registerToolTask(String name, String toolMainClass, String toolDescription) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public BlockStateUpgrader() {
final JsonObject json = GsonUtil.getGson().fromJson(new String(data, StandardCharsets.UTF_8), JsonObject.class);
this.schemas.add(new JsonBlockStateUpgradeSchema(json));
}
this.schemas.add(new ConnectionBlockStateUpgradeSchema());
} catch (final Throwable e) {
ViaBedrock.getPlatform().getLogger().log(Level.SEVERE, "Failed to load block state upgrade schema", e);
this.schemas.clear();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock
* Copyright (C) 2023-2026 RK_01/RaphiMC and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.raphimc.viabedrock.api.chunk.blockstate;

import com.viaversion.nbt.tag.CompoundTag;

/** Normalizes legacy connected blocks whose state version did not change in 26.60. */
public final class ConnectionBlockStateUpgradeSchema extends BlockStateUpgradeSchema {

public ConnectionBlockStateUpgradeSchema() {
super(1, 21, 60, 33);
this.actions.add(tag -> {
if (!(tag.get("states") instanceof CompoundTag states)) {
return;
}
final String name = tag.getStringTag("name").getValue();
if (name.equals("minecraft:redstone_wire")) {
for (String side : new String[]{"north", "east", "south", "west"}) {
if (!states.contains("redstone_" + side)) {
states.putString("redstone_" + side, "none");
}
}
} else if (name.equals("minecraft:chorus_plant") || name.equals("minecraft:fire")) {
for (String side : new String[]{"north", "east", "south", "west", "up", "down"}) {
if (side.equals("down") && name.equals("minecraft:fire")) {
continue;
}
if (!states.contains("minecraft:connection_" + side)) {
states.putByte("minecraft:connection_" + side, (byte) 0);
}
}
}
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ protected void decode(final ChannelHandlerContext ctx, final ByteBuf in, final L
}

final int rawAlgorithm = in.readUnsignedByte();
final PacketCompressionAlgorithm algorithm = PacketCompressionAlgorithm.getByValue(rawAlgorithm);
// NetworkSettings uses a uint16 sentinel; a compressed frame has only a uint8 header.
final PacketCompressionAlgorithm algorithm = rawAlgorithm == 0xFF ? PacketCompressionAlgorithm.None : PacketCompressionAlgorithm.getByValue(rawAlgorithm);
if (algorithm == null) { // Bedrock client drops the packet if the algorithm is unknown
ViaBedrock.getPlatform().getLogger().log(Level.WARNING, "Dropping packet with unknown PacketCompressionAlgorithm: " + rawAlgorithm);
in.skipBytes(in.readableBytes());
Expand All @@ -95,7 +96,7 @@ protected void decode(final ChannelHandlerContext ctx, final ByteBuf in, final L

final CompressionAlgorithm compressionAlgorithm = this.getCompressionAlgorithm(algorithm);
if (compressionAlgorithm instanceof NoopCompression) {
out.add(in.retain());
out.add(in.readRetainedSlice(in.readableBytes()));
} else {
final ByteBuf uncompressedData = ctx.alloc().buffer();
compressionAlgorithm.decompress(in, uncompressedData); // Bedrock client would drop packets with invalid data, but this would be too insane to do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@ public enum ClientboundBedrockPackets implements ClientboundPacketType {
VOXEL_SHAPES(MinecraftPacketIds.VoxelShapesPacket.getValue()),
SET_PLAYER_FURNACE_OPTIONS(MinecraftPacketIds.SetPlayerFurnaceOptions.getValue()),
RECORD_STARTED(MinecraftPacketIds.RecordStarted.getValue()),
STONECUTTER_SET_RECIPE(MinecraftPacketIds.ClientboundStonecutterSetRecipePacket.getValue());
STONECUTTER_SET_RECIPE(MinecraftPacketIds.ClientboundStonecutterSetRecipePacket.getValue()),
SET_PASSENGER_OF_BLOCK(MinecraftPacketIds.SetPassengerOfBlockPacket.getValue()),
PLAY_AUDIO_CONTENT(MinecraftPacketIds.ClientboundPlayAudioContent.getValue());
// UPDATE_SOUND_DATA(MinecraftPacketIds.ClientboundUpdateSoundDataPacket.getValue());
// CONTROL_SCHEME_SET(MinecraftPacketIds.ClientboundControlSchemeSetPacket.getValue()),
// PRIMITIVE_SHAPES(MinecraftPacketIds.PrimitiveShapesPacket.getValue()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.libs.fastutil.ints.IntIntPair;
import com.viaversion.viaversion.util.Key;
import net.raphimc.viabedrock.ViaBedrock;
import net.raphimc.viabedrock.api.resourcepack.definition.BiomeDefinitions;
Expand All @@ -29,6 +28,7 @@
import net.raphimc.viabedrock.protocol.BedrockProtocol;
import net.raphimc.viabedrock.protocol.data.enums.Dimension;
import net.raphimc.viabedrock.protocol.data.generated.java.RegistryKeys;
import net.raphimc.viabedrock.protocol.model.DimensionDefinition;
import net.raphimc.viabedrock.protocol.storage.GameSessionStorage;
import net.raphimc.viabedrock.protocol.storage.ResourcePackStorage;

Expand Down Expand Up @@ -62,13 +62,24 @@ private static void modifyDimensionRegistry(final GameSessionStorage gameSession
dimensionRegistry.getCompoundTag(Dimension.OVERWORLD.getKey()).putInt("height", 256);
dimensionRegistry.getCompoundTag(Dimension.OVERWORLD.getKey()).putInt("logical_height", 256);
}
for (Map.Entry<String, IntIntPair> entry : gameSession.getBedrockDimensionDefinitions().entrySet()) {
final CompoundTag dimensionTag = new CompoundTag();
final int height = entry.getValue().rightInt() - entry.getValue().leftInt();
dimensionTag.putInt("min_y", entry.getValue().leftInt());
dimensionTag.putInt("height", height);
dimensionTag.putInt("logical_height", height);
dimensionRegistry.getCompoundTag(entry.getKey()).putAll(dimensionTag);
for (Map.Entry<String, DimensionDefinition> entry : gameSession.getBedrockDimensionDefinitions().entrySet()) {
applyDimensionDefinition(dimensionRegistry.getCompoundTag(entry.getKey()), entry.getValue());
}
}

static void applyDimensionDefinition(final CompoundTag dimensionTag, final DimensionDefinition definition) {
dimensionTag.putInt("min_y", definition.minimumY());
dimensionTag.putInt("height", definition.height());
dimensionTag.putInt("logical_height", definition.height());
CompoundTag attributes = dimensionTag.getCompoundTag("attributes");
if (attributes == null) {
attributes = new CompoundTag();
dimensionTag.put("attributes", attributes);
}
attributes.putFloat("minecraft:visual/cloud_height", definition.cloudHeight());
if (!definition.renderClouds()) {
// Java's day timeline multiplies cloud color, preserving zero alpha.
attributes.putString("minecraft:visual/cloud_color", "#00ffffff");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public final class ProtocolConstants {
public static final TextComponentCodec JAVA_TEXT_COMPONENT_SERIALIZER = TextComponentCodec.V26_1;
public static final int JAVA_AIR_ID = 0;

public static final String BEDROCK_VERSION_NAME = "1.26.51";
public static final int BEDROCK_PROTOCOL_VERSION = 2193;
public static final String BEDROCK_VERSION_NAME = "1.26.60";
public static final int BEDROCK_PROTOCOL_VERSION = 2225;
public static final int BEDROCK_RAKNET_PROTOCOL_VERSION = 11;
public static final int BEDROCK_DEFAULT_PORT = 19132;
public static final int BEDROCK_NETHERNET_LAN_DEFAULT_PORT = 7551;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ public enum ActorType {
CamelHusk(70552),
SulfurCube(921),
Cushion(154),
Frostbite(199579),
IceBall(4194460),
;

private static final Int2ObjectMap<ActorType> BY_VALUE = new Int2ObjectOpenHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// THIS FILE IS AUTO-GENERATED. DO NOT EDIT!
package net.raphimc.viabedrock.protocol.data.enums.bedrock.generated;

import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;

public enum AudioContentPlaybackType {

Music(0),
Sound(1),
;

private static final Int2ObjectMap<AudioContentPlaybackType> BY_VALUE = new Int2ObjectOpenHashMap<>();

static {
for (AudioContentPlaybackType value : values()) {
if (!BY_VALUE.containsKey(value.value)) {
BY_VALUE.put(value.value, value);
}
}
}

public static AudioContentPlaybackType getByValue(final int value) {
return BY_VALUE.get(value);
}

public static AudioContentPlaybackType getByValue(final int value, final AudioContentPlaybackType fallback) {
return BY_VALUE.getOrDefault(value, fallback);
}

public static AudioContentPlaybackType getByName(final String name) {
for (AudioContentPlaybackType value : values()) {
if (value.name().equalsIgnoreCase(name)) {
return value;
}
}
return null;
}

public static AudioContentPlaybackType getByName(final String name, final AudioContentPlaybackType fallback) {
for (AudioContentPlaybackType value : values()) {
if (value.name().equalsIgnoreCase(name)) {
return value;
}
}
return fallback;
}

private final int value;

AudioContentPlaybackType(final AudioContentPlaybackType value) {
this(value.value);
}

AudioContentPlaybackType(final int value) {
this.value = value;
}

public int getValue() {
return this.value;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public enum ContainerEnumName {
SmithingTableTemplateContainer(61),
CrafterLevelEntityContainer(62),
DynamicContainer(63),
ReservedContainerA(67),
ReservedContainerB(68),
ReservedContainerC(69),
ReservedContainerD(70),
;

private static final Int2ObjectMap<ContainerEnumName> BY_VALUE = new Int2ObjectOpenHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public enum ContainerType {
CHEST_BOAT(34),
DECORATED_POT(35),
CRAFTER(36),
RESERVED_CONTAINER_TYPE(38),
;

private static final Int2ObjectMap<ContainerType> BY_VALUE = new Int2ObjectOpenHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ public enum CurrentCmdVersion {
LocateStructureOutput(42),
PostBlockFlattening(43),
TestForBlockCommandDoesNotIgnoreBlockState(44),
Count(55),
Latest(54),
Count(56),
Latest(55),
;

private static final Int2ObjectMap<CurrentCmdVersion> BY_VALUE = new Int2ObjectOpenHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// THIS FILE IS AUTO-GENERATED. DO NOT EDIT!
package net.raphimc.viabedrock.protocol.data.enums.bedrock.generated;

import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;

public enum CursorItemDragState {

Start(0),
Stop(1),
;

private static final Int2ObjectMap<CursorItemDragState> BY_VALUE = new Int2ObjectOpenHashMap<>();

static {
for (CursorItemDragState value : values()) {
if (!BY_VALUE.containsKey(value.value)) {
BY_VALUE.put(value.value, value);
}
}
}

public static CursorItemDragState getByValue(final int value) {
return BY_VALUE.get(value);
}

public static CursorItemDragState getByValue(final int value, final CursorItemDragState fallback) {
return BY_VALUE.getOrDefault(value, fallback);
}

public static CursorItemDragState getByName(final String name) {
for (CursorItemDragState value : values()) {
if (value.name().equalsIgnoreCase(name)) {
return value;
}
}
return null;
}

public static CursorItemDragState getByName(final String name, final CursorItemDragState fallback) {
for (CursorItemDragState value : values()) {
if (value.name().equalsIgnoreCase(name)) {
return value;
}
}
return fallback;
}

private final int value;

CursorItemDragState(final CursorItemDragState value) {
this(value.value);
}

CursorItemDragState(final int value) {
this.value = value;
}

public int getValue() {
return this.value;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

public enum DataItemType {

Unknown(-1),
Byte(0),
Short(1),
Int(2),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public enum DisconnectFailReason {
EditorNotAllowed(147),
MissingStructureData(148),
UnsupportedTransport(149),
SubClientLoginNotBound(150),
;

private static final Int2ObjectMap<DisconnectFailReason> BY_VALUE = new Int2ObjectOpenHashMap<>();
Expand Down
Loading