Skip to content

Commit 966d792

Browse files
committed
feat: initial support for NetEase 1.21.90 and drop older protocol versions
1 parent 386c2c3 commit 966d792

File tree

11 files changed

+35
-195
lines changed

11 files changed

+35
-195
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,16 @@ Unless otherwise specified, any version comparison below is the comparison of th
1515
### Added
1616

1717
- (API) Added DDUI support for Bedrock 1.26.10+ (protocol v944+), including `DDUI`, `DDUIViewer`, `DDUIScreenSession`, `CustomFormScreen`, `MessageBoxScreen`, `Observable`, `Property`, and the custom-form element set (`Label`, `Header`, `Spacer`, `Divider`, `TextField`, `Toggle`, `Slider`, `Dropdown`, `Button`, `CloseButton`).
18+
- Added support for NetEase 1.21.90.
1819

1920
### Changed
2021

2122
- (API) Merged `org.allaymc.server.bossbar.AllayBossBar` into the concrete `org.allaymc.api.bossbar.BossBar` class, so boss bars no longer use separate API interface and server implementation types.
2223

24+
### Removed
25+
26+
- Removed support for bedrock (NetEase) 1.21.50 and 1.21.80.
27+
2328
# 0.12.0 (API 0.27.0) - 2026/3/29
2429

2530
<small>[Compare with 0.11.1](https://github.com/AllayMC/Allay/compare/0.11.1...0.12.0)</small>

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ The next-generation Minecraft: Bedrock Edition server software aims to be reliab
1818
<a href="https://app.codacy.com/gh/AllayMC/Allay/dashboard"><img src="https://app.codacy.com/project/badge/Grade/30e264923da2425a8b777a84b4028334"></a>
1919
<a href="https://discord.gg/ngkkE4hPTU"><img src="https://img.shields.io/discord/1147136608290750526?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
2020
[![qq](https://img.shields.io/badge/QQ-1072132791-purple)](https://qm.qq.com/q/peseHA0xN0)
21-
<a href="https://feedback.minecraft.net/hc/en-us/sections/360001186971-Release-Changelogs"><img src="https://img.shields.io/badge/minecraft-1.21.50(NetEase) ~ 1.26.10%20(Bedrock)-green" /></a>
21+
<a href="https://feedback.minecraft.net/hc/en-us/sections/360001186971-Release-Changelogs"><img src="https://img.shields.io/badge/minecraft-1.21.90(NetEase) ~ 1.26.10%20(Bedrock)-green" /></a>
2222
[![GitHub License](https://img.shields.io/github/license/allaymc/allay)](LICENSE)
2323
[![Ko-Fi](https://img.shields.io/badge/Buy_Me_a_Coffee-f37574?logo=kofi&logoColor=white)](https://ko-fi.com/AllayMC)
2424

gradle/libs.versions.toml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,13 @@ commons-rng = "1.6"
44
fastutil = "8.5.15"
55
leveldb = "1.1.0"
66
netty = "4.2.12.Final"
7-
protocol = "3.0.0.Beta12-20260324.161234-12"
87

98
[libraries]
109
# NBT
1110
nbt = { group = "org.allaymc", name = "nbt", version = "3.0.12" }
1211
# Protocol
13-
protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-connection", version.ref = "protocol" }
14-
protocol-common = { group = "org.cloudburstmc.protocol", name = "common", version.ref = "protocol" }
15-
protocol-codec = { group = "org.cloudburstmc.protocol", name = "bedrock-codec", version.ref = "protocol" }
16-
protocol-extension = {group = "org.allaymc", name = "protocol-extension", version = "0.1.7" }
12+
protocol-connection = { group = "org.allaymc.protocol", name = "bedrock-connection", version = "1.26.10-R1" }
13+
protocol-extension = {group = "org.allaymc", name = "protocol-extension", version = "0.2.1" }
1714
# State Updater
1815
updater-common = { group = "org.allaymc.stateupdater", name = "common", version = "0.1.1" }
1916
item-updater = { group = "org.allaymc.stateupdater", name = "item-updater", version = "1.21.110-R1" }
@@ -101,7 +98,7 @@ bstats = { group = "org.bstats", name = "bstats-base", version = "3.2.1" }
10198
lz4-java = { group = "at.yawk.lz4", name = "lz4-java", version = "1.10.4" }
10299

103100
[bundles]
104-
protocol = ["protocol-connection", "protocol-common", "protocol-codec", "protocol-extension"]
101+
protocol = ["protocol-connection", "protocol-extension"]
105102
logging = ["log4j-slf4j2-impl", "log4j-core"]
106103
junit = ["junit-jupiter", "mockito-junit-jupiter"]
107104
fastutil = [

server/src/main/java/org/allaymc/server/network/AllayNetworkInterface.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ protected void initPlayerSession(BedrockServerSession session) {
110110
return;
111111
}
112112

113+
// Enable detailed packet logging if debug mode is enabled
114+
if (AllayServer.getSettings().genericSettings().debug()) {
115+
session.setLogging(true);
116+
}
117+
113118
var player = new AllayPlayer(session, this);
114119
session.getPeer().getChannel().attr(NettyPipelineInitEvent.PLAYER_ATTRIBUTE_KEY).set(player);
115120
var event = new PlayerConnectEvent(player, "disconnect.disconnected");

server/src/main/java/org/allaymc/server/network/AllayRakNetInterface.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ protected void updatePong() {
203203
private class AllayServerInitializer extends BedrockServerInitializer {
204204

205205
@Override
206-
@MultiVersion(version = "1.21.50-NetEase", details = "NetEase clients need NOOP compression initially for uncompressed RequestNetworkSettingsPacket")
206+
@MultiVersion(version = "*-NetEase", details = "NetEase clients need NOOP compression initially for uncompressed RequestNetworkSettingsPacket")
207207
protected void preInitChannel(Channel channel) throws Exception {
208208
super.preInitChannel(channel);
209209
new NettyPipelineInitEvent(channel).call();
@@ -224,7 +224,7 @@ protected void preInitChannel(Channel channel) throws Exception {
224224
}
225225

226226
@Override
227-
@MultiVersion(version = "1.21.50-NetEase", details = "NetEase clients use RakNet version 8 but require v3 packet codec format")
227+
@MultiVersion(version = "*-NetEase", details = "NetEase clients use RakNet version 8 but require v3 packet codec format")
228228
protected void initPacketCodec(Channel channel) throws Exception {
229229
// NetEase clients use rakVersion 8, but their packet format is the same as
230230
// international clients (v3), not the old v2 format that Protocol library

server/src/main/java/org/allaymc/server/network/NetworkData.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,13 @@ public static ResourcePacksInfoPacket encodeResourcePacksInfoPacket() {
309309
var info = switch (pack.getType()) {
310310
case RESOURCES -> new ResourcePacksInfoPacket.Entry(
311311
pack.getId(), pack.getStringVersion(), pack.getSize(), pack.getContentKey(), "", pack.getId().toString(), scripting,
312-
pack.getManifest().getCapabilities().contains(PackManifest.Capability.RAYTRACED), false, null
312+
pack.getManifest().getCapabilities().contains(PackManifest.Capability.RAYTRACED), null, false
313313
);
314314
case DATA -> {
315315
packet.setHasAddonPacks(true);
316316
yield new ResourcePacksInfoPacket.Entry(
317317
pack.getId(), pack.getStringVersion(), pack.getSize(), pack.getContentKey(), "", pack.getId().toString(), scripting,
318-
pack.getManifest().getCapabilities().contains(PackManifest.Capability.RAYTRACED), true, null
318+
pack.getManifest().getCapabilities().contains(PackManifest.Capability.RAYTRACED), null, true
319319
);
320320
}
321321
case null, default -> null;

server/src/main/java/org/allaymc/server/network/ProtocolInfo.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import org.allaymc.updater.item.ItemStateUpdater;
88
import org.allaymc.updater.item.ItemStateUpdater_1_21_110;
99
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
10-
import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766;
11-
import org.cloudburstmc.protocol.bedrock.codec.v800.Bedrock_v800;
1210
import org.cloudburstmc.protocol.bedrock.codec.v818.Bedrock_v818;
1311
import org.cloudburstmc.protocol.bedrock.codec.v819.Bedrock_v819;
1412
import org.cloudburstmc.protocol.bedrock.codec.v827.Bedrock_v827;
@@ -42,9 +40,7 @@ public final class ProtocolInfo {
4240
Bedrock_v844.CODEC,
4341
Bedrock_v827.CODEC,
4442
Bedrock_v819.CODEC,
45-
Bedrock_v818.CODEC,
46-
Bedrock_v800.CODEC,
47-
Bedrock_v766.CODEC
43+
Bedrock_v818.CODEC
4844
);
4945

5046
/**

server/src/main/java/org/allaymc/server/network/multiversion/MultiVersionHelper.java

Lines changed: 0 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,169 +1,26 @@
11
package org.allaymc.server.network.multiversion;
22

33
import org.allaymc.api.player.Player;
4-
import org.allaymc.api.utils.identifier.Identifier;
54
import org.allaymc.server.player.AllayPlayer;
65
import org.cloudburstmc.nbt.NbtMap;
76
import org.cloudburstmc.nbt.NbtType;
87
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
9-
import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766;
10-
import org.cloudburstmc.protocol.bedrock.codec.v800.Bedrock_v800;
118
import org.cloudburstmc.protocol.bedrock.codec.v827.Bedrock_v827;
129
import org.cloudburstmc.protocol.bedrock.codec.v844.Bedrock_v844;
1310
import org.cloudburstmc.protocol.bedrock.codec.v898.Bedrock_v898;
1411
import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData;
1512
import org.cloudburstmc.protocol.bedrock.data.ExperimentData;
16-
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
17-
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
18-
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.*;
19-
import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.DefaultDescriptor;
20-
import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
21-
import org.cloudburstmc.protocol.bedrock.packet.BiomeDefinitionListPacket;
22-
import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket;
2313

2414
import java.util.LinkedList;
2515
import java.util.List;
26-
import java.util.stream.Stream;
2716

2817
/**
2918
* @author daoge_cmd
3019
*/
3120
@MultiVersion(version = "*")
3221
public final class MultiVersionHelper {
3322

34-
public static CraftingDataPacket adaptCraftingDataPacket(Player player, CraftingDataPacket packet) {
35-
if (!is1_21_50(player)) {
36-
return packet;
37-
}
38-
39-
// Remove recipes that contain items not available in 1.21.50
40-
packet.getCraftingData().removeIf(MultiVersionHelper::containsUnsupportedItem);
41-
return packet;
42-
}
43-
44-
private static boolean containsUnsupportedItem(RecipeData recipe) {
45-
return switch (recipe) {
46-
case ShapedRecipeData shaped ->
47-
containsUnsupportedIngredient(shaped.getIngredients()) ||
48-
containsUnsupportedOutput(shaped.getResults());
49-
case ShapelessRecipeData shapeless ->
50-
containsUnsupportedIngredient(shapeless.getIngredients()) ||
51-
containsUnsupportedOutput(shapeless.getResults());
52-
case SmithingTransformRecipeData smithing ->
53-
isUnsupportedIngredient(smithing.getTemplate()) ||
54-
isUnsupportedIngredient(smithing.getBase()) ||
55-
isUnsupportedIngredient(smithing.getAddition()) ||
56-
isUnsupportedOutput(smithing.getResult());
57-
case SmithingTrimRecipeData trim ->
58-
isUnsupportedIngredient(trim.getTemplate()) ||
59-
isUnsupportedIngredient(trim.getBase()) ||
60-
isUnsupportedIngredient(trim.getAddition());
61-
case FurnaceRecipeData furnace ->
62-
isUnsupportedOutput(furnace.getResult());
63-
default -> false;
64-
};
65-
}
66-
67-
private static boolean containsUnsupportedIngredient(List<ItemDescriptorWithCount> ingredients) {
68-
return ingredients.stream().anyMatch(MultiVersionHelper::isUnsupportedIngredient);
69-
}
70-
71-
private static boolean isUnsupportedIngredient(ItemDescriptorWithCount ingredient) {
72-
if (ingredient.getDescriptor() instanceof DefaultDescriptor descriptor) {
73-
return isItemNotAvailableIn1_21_50(descriptor.getItemId().getIdentifier());
74-
}
75-
return false;
76-
}
77-
78-
private static boolean containsUnsupportedOutput(List<ItemData> outputs) {
79-
return outputs.stream().anyMatch(MultiVersionHelper::isUnsupportedOutput);
80-
}
81-
82-
private static boolean isUnsupportedOutput(ItemData output) {
83-
return isItemNotAvailableIn1_21_50(output.getDefinition().getIdentifier());
84-
}
85-
86-
public static BiomeDefinitionListPacket adaptBiomeDefinitionListPacket(Player player, BiomeDefinitionListPacket packet) {
87-
if (!is1_21_50(player)) {
88-
return packet;
89-
}
90-
91-
var builder = NbtMap.builder();
92-
for (var entry : packet.getBiomes().getDefinitions().entrySet()) {
93-
var identifier = entry.getKey();
94-
var definition = entry.getValue();
95-
96-
builder.putCompound(identifier, NbtMap.builder()
97-
.putFloat("ash", definition.getAshDensity())
98-
.putFloat("blue_spores", definition.getBlueSporeDensity())
99-
.putFloat("depth", definition.getDepth())
100-
.putFloat("downfall", definition.getDownfall())
101-
.putFloat("height", definition.getScale())
102-
.putBoolean("rain", definition.isRain())
103-
.putFloat("red_spores", definition.getRedSporeDensity())
104-
.putList("tags", NbtType.STRING, definition.getTags())
105-
.putFloat("temperature", definition.getTemperature())
106-
.putFloat("waterColorA", definition.getMapWaterColor().getAlpha() / 256f)
107-
.putFloat("waterColorB", definition.getMapWaterColor().getBlue() / 256f)
108-
.putFloat("waterColorG", definition.getMapWaterColor().getGreen() / 256f)
109-
.putFloat("waterColorR", definition.getMapWaterColor().getRed() / 256f)
110-
.putFloat("white_ash", definition.getWhiteAshDensity())
111-
.build()
112-
);
113-
}
114-
115-
packet.setDefinitions(builder.build());
116-
return packet;
117-
}
118-
119-
public static void adaptItemDefinitions(Player player, List<ItemDefinition> definitions) {
120-
if (!is1_21_50(player)) {
121-
return;
122-
}
123-
124-
// Remove the items that do not exist in 1.21.50
125-
definitions.removeIf(def -> isItemNotAvailableIn1_21_50(def.getIdentifier()));
126-
}
127-
128-
private static boolean isItemNotAvailableIn1_21_50(String identifier) {
129-
if (!identifier.startsWith(Identifier.DEFAULT_NAMESPACE)) {
130-
// Skip custom items
131-
return false;
132-
}
133-
134-
if (identifier.contains("lightning_rod") &&
135-
!identifier.equals("minecraft:lightning_rod")) {
136-
return true;
137-
}
138-
139-
if (Stream.of("minecraft:bush", "minecraft:firefly_bush").anyMatch(identifier::equals)) {
140-
return true;
141-
}
142-
143-
// TODO: find out why exclude "wildflowers", "cactus_flower" will crash the client
144-
return Stream.of(
145-
// Copper
146-
"copper_bars", "copper_golem", "copper_lantern", "copper_chain",
147-
"copper_helmet", "copper_chestplate", "copper_leggings", "copper_boots",
148-
"copper_sword", "copper_axe", "copper_pickaxe", "copper_shovel", "copper_hoe",
149-
"copper_horse_armor", "copper_torch", "copper_chest", "copper_nugget",
150-
// Misc
151-
"happy_ghast", "dried_ghast", "netherite_horse_armor", "harness", "nautilus_armor",
152-
"nautilus_spawn_egg", "dry_grass", "spear", "_shelf", "iron_chain", "leaf_litter",
153-
"brown_egg", "blue_egg", "camel_husk_spawn_egg", "parched_spawn_egg", "music_disc_tears",
154-
"music_disc_lava_chicken"
155-
).anyMatch(identifier::contains);
156-
}
157-
15823
public static void adaptExperimentData(Player player, List<ExperimentData> experiments) {
159-
if (is1_21_80(player)) {
160-
// Enables 2025 Content Drop 2 features
161-
experiments.add(new ExperimentData("y_2025_drop_2", true));
162-
// Enables the locator bar for 1.21.80 clients
163-
experiments.add(new ExperimentData("locator_bar", true));
164-
// Allows Vibrant Visuals to appear in the settings menu
165-
experiments.add(new ExperimentData("experimental_graphics", true));
166-
}
16724
if (is1_21_100(player)) {
16825
experiments.add(new ExperimentData("y_2025_drop_3", true));
16926
}
@@ -282,10 +139,6 @@ private static NbtMap adaptMaterialInstances(NbtMap materialInstances) {
282139
.build();
283140
}
284141

285-
public static boolean is1_21_50(Player player) {
286-
return getCodec(player).getProtocolVersion() == Bedrock_v766.CODEC.getProtocolVersion();
287-
}
288-
289142
private static boolean is1_21_130orHigher(Player player) {
290143
return getCodec(player).getProtocolVersion() >= Bedrock_v898.CODEC.getProtocolVersion();
291144
}
@@ -298,10 +151,6 @@ private static boolean is1_21_100(Player player) {
298151
return getCodec(player) == Bedrock_v827.CODEC;
299152
}
300153

301-
private static boolean is1_21_80(Player player) {
302-
return getCodec(player) == Bedrock_v800.CODEC;
303-
}
304-
305154
private static BedrockCodec getCodec(Player player) {
306155
return ((AllayPlayer) player).getSession().getCodec();
307156
}

server/src/main/java/org/allaymc/server/network/processor/login/RequestNetworkSettingsPacketProcessor.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.allaymc.api.player.Player;
66
import org.allaymc.protocol.extension.NetEaseCompression;
77
import org.allaymc.protocol.extension.codec.v766.Bedrock_v766_NetEase;
8+
import org.allaymc.protocol.extension.codec.v819.Bedrock_v819_NetEase;
89
import org.allaymc.server.AllayServer;
910
import org.allaymc.server.network.ProtocolInfo;
1011
import org.allaymc.server.network.multiversion.MultiVersion;
@@ -26,8 +27,8 @@
2627
public class RequestNetworkSettingsPacketProcessor extends ILoginPacketProcessor<RequestNetworkSettingsPacket> {
2728

2829
@Override
29-
@MultiVersion(version = "1.21.50-NetEase", details = "NetEase clients are detected via RakNet protocol version 8 and use raw deflate compression")
30-
@MultiVersion(version = "1.21.50-NetEase", details = "Packet codec is replaced for NetEase clients")
30+
@MultiVersion(version = "*-NetEase", details = "NetEase clients are detected via RakNet protocol version 8 and use raw deflate compression")
31+
@MultiVersion(version = "*-NetEase", details = "Packet codec is replaced for NetEase clients")
3132
public void handle(Player player, RequestNetworkSettingsPacket packet) {
3233
var allayPlayer = (AllayPlayer) player;
3334
var protocolVersion = packet.getProtocolVersion();
@@ -117,10 +118,10 @@ boolean isNetEaseClient(AllayPlayer allayPlayer) {
117118
* @return the NetEase codec, or {@code null} if not found
118119
*/
119120
private static BedrockCodec findNetEaseCodec(int protocolVersion) {
120-
if (protocolVersion == Bedrock_v766_NetEase.CODEC.getProtocolVersion()) {
121-
return Bedrock_v766_NetEase.CODEC;
122-
}
123-
124-
return null;
121+
return switch (protocolVersion) {
122+
case 766 -> Bedrock_v766_NetEase.CODEC;
123+
case 819 -> Bedrock_v819_NetEase.CODEC;
124+
default -> null;
125+
};
125126
}
126127
}

server/src/main/java/org/allaymc/server/player/AllayLoginData.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class AllayLoginData implements LoginData {
4848
* @param isNetEaseClient whether the client is a NetEase client
4949
* @return the decoded login data, or {@code null} if decoding failed
5050
*/
51-
@MultiVersion(version = "1.21.50-NetEase", details = "NetEase clients use a different public key for login chain validation instead of Mojang's key")
51+
@MultiVersion(version = "*-NetEase", details = "NetEase clients use a different public key for login chain validation instead of Mojang's key")
5252
public static AllayLoginData decode(LoginPacket loginPacket, boolean isNetEaseClient) {
5353
var loginData = new AllayLoginData();
5454
try {
@@ -214,7 +214,7 @@ private void decodeSkinData(String skinData, boolean isNetEaseClient) {
214214
this.skin = skinBuilder.build();
215215
}
216216

217-
@MultiVersion(version = "1.21.50-NetEase", details = "NetEase clients use URL-safe Base64 encoding for skin data")
217+
@MultiVersion(version = "*-NetEase", details = "NetEase clients use URL-safe Base64 encoding for skin data")
218218
private JsonObject decodeToken(String token, boolean isNetEaseClient) {
219219
String[] tokenSplit = token.split("\\.");
220220
if (tokenSplit.length < 2) {

0 commit comments

Comments
 (0)