Напиши что-то на подобии ViaVersion (ViaProxy) но для Minecraft: Bedrock Edition для возможности зайти со старых версий клиента на новые версии серверов и наоборот, с новых версий клиента, на старые версии серверов. Напиши его на Java используя https://github.com/CloudburstMC/Protocol без его модификации а используй его в этом проекте, маппинги я могу сам добавить из других репозиториев на GitHub взяв их у Nukkit, PocketMine-MP, BedrockData BedrockBlockUpgradeSchema, BedrockItemUpgradeSchema, GeyserMC mappings, у https://github.com/CloudburstMC/Protocol есть готовая поддержка серверной составляющей протоколов от 291 до последней версии, протокол 291 это версия 1.7 Bedrock Edition, сделай её пока поддерживаемой в этом проекте, но я бы хотел все версии поддерживать вплоть до альфа 0.1.0-0.1.3, но это уже посложнее пакеты придётся тоже брать с Nukkit а после PocketMine-MP, так как Nukkit появился во время версии 0.13.0-0.14.0.
Ниже приведён «минимально-жизнеспособный» скелет-проект, который:
• собирается Gradle (java 17);
• использует неизменённый com.nukkitx:protocol (CloudburstMC/Protocol) ровно так, как он публикуется в Maven;
• добавляет собственный слой трансляции, который пока умеет «проксировать» клиент 1.7 (protocol 291) ↔ сервер последней версии;
• имеет расширяемую архитектуру, в которую вы потом сможете воткнуть собранные вручную BedrockBlockUpgradeSchema, BedrockItemUpgradeSchema, кастомные PacketCodec из Nukkit/PocketMine-MP и старые пакеты альф-версий.
Название пусть будет ViaBedrock (в духе ViaVersion/ViaBackwards).
Проект лежит в GitHub-репозитории ViaBedrock/ViaBedrock.
ViaBedrock/
├─ proxy/
│ ├─ bootstrap/
│ │ └─ Main.java ← точка входа
│ ├─ codec/ ← кастомные PacketCodec (добавите позже)
│ ├─ mapping/ ← сюда кладёте .json/.bin файлы
│ ├─ protocol/ ← «переводчики» между версиями
│ │ ├─ v291_to_latest/
│ │ └─ latest_to_v291/
│ ├─ session/ ← BedrockSession + Upstream/Downstream
│ └─ util/ ← вспомогательные утилиты
├─ gradle/
└─ build.gradle
plugins {
id 'java'
id 'application'
}
group = 'org.viabedrock'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
maven { url 'https://repo.opencollab.dev/main' } // Cloudburst
}
dependencies {
implementation 'com.nukkitx.protocol:bedrock-v291:2.9.6-SNAPSHOT'
implementation 'com.nukkitx.protocol:bedrock-latest:2.9.6-SNAPSHOT'
// Logging
implementation 'org.slf4j:slf4j-simple:2.0.7'
implementation 'net.kyori:adventure-text-serializer-plain:4.14.0'
}
application {
mainClass = 'org.viabedrock.bootstrap.Main'
}
3.1 PacketTranslator
public interface PacketTranslator<IN extends BedrockPacket, OUT extends BedrockPacket> {
OUT translate(IN packet, SessionContext ctx);
boolean needsTranslation(int fromVersion, int toVersion);
}
3.2 SessionContext
public record SessionContext(
int clientProtocol,
int serverProtocol,
PlayerSession session
) {}
3.3 BedrockProxySession
держит два BedrockSession (upstream – игрок, downstream – сервер) и стек PacketTranslator.
3.4 ProtocolDirection
CLIENT_TO_SERVER, SERVER_TO_CLIENT; для каждой пары версий регистрируем цепочку PacketTranslator.
org.viabedrock.bootstrap.Main
public final class Main {
public static void main(String[] args) {
BedrockServer proxy = new BedrockServer(
InetSocketAddress.createUnresolved("0.0.0.0", 19132)
);
proxy.setHandler(new ProxyServerEventHandler());
proxy.bind().join();
System.out.println("ViaBedrock proxy started on 0.0.0.0:19132");
}
}
org.viabedrock.session.ProxyServerEventHandler
public final class ProxyServerEventHandler implements BedrockServerEventHandler {
@Override
public boolean onConnectionRequest(InetSocketAddress address) {
return true; // пока без whitelist
}
@Override
public BedrockPong onQuery(InetSocketAddress address) {
return new BedrockPong()
.edition("MCPE")
.motd("ViaBedrock Proxy")
.playerCount(0)
.maximumPlayerCount(20);
}
@Override
public void onSessionCreation(BedrockServerSession session) {
new UpstreamHandler(session);
}
}
UpstreamHandler создаёт downstream-коннект к реальному серверу (передаём адрес через loginData.getServerAddress(), пока хардкод 127.0.0.1:19133).
Пусть клиент 1.7 отправляет InventoryTransactionPacket (v291), а сервер ожидает уже новый ItemUseTransactionPacket (v554+).
Создаём:
org.viabedrock.protocol.v291_to_latest.InventoryTransactionTranslator
public final class InventoryTransactionTranslator
implements PacketTranslator<InventoryTransactionPacket_v291, ItemUseTransactionPacket_latest> {
@Override
public ItemUseTransactionPacket_latest translate(InventoryTransactionPacket_v291 packet, SessionContext ctx) {
// псевдокод: вытягиваем action, преобразуем runtime ID и т.д.
return new ItemUseTransactionPacket_latest()
.runtimeEntityId(packet.getRuntimeEntityId())
.actionType(packet.getTransactionType().ordinal())
.blockPosition(packet.getBlockPosition())
.blockFace(packet.getFace())
.hotbarSlot(packet.getHotbarSlot())
.itemInHand(adaptItem(packet.getItemInHand(), ctx));
}
private ItemData adaptItem(ItemData_v291 old, SessionContext ctx) {
// здесь подгрузите .json маппинги предметов из mapping/
return ItemMapping.v291_to_latest.translate(old);
}
@Override
public boolean needsTranslation(int from, int to) {
return from == 291 && to >= 554;
}
}
Аналогично в обратном направлении.
org.viabedrock.protocol.ProtocolRegistry
public final class ProtocolRegistry {
private static final Int2ObjectMap<ProtocolRoute> ROUTES = new Int2ObjectOpenHashMap<>();
static {
register(291, Bedrock_v291.V291_CODEC, // Cloudburst
554, Bedrock_v554.V554_CODEC, // последняя
new ProtocolRoute(
List.of(
new InventoryTransactionTranslator(),
... // остальные
),
List.of(
new ItemUseTransactionTranslator_back(),
...
)
));
}
private static void register(int from, BedrockPacketCodec fromCodec,
int to, BedrockPacketCodec toCodec,
ProtocolRoute route) {
ROUTES.put(ProtocolKey.key(from, to), route);
}
public static ProtocolRoute find(int from, int to) {
return ROUTES.get(ProtocolKey.key(from, to));
}
}
Как добавить старые версии (0.14→0.15, 0.15→0.16 …)
Подключите Nukkit/PocketMine-MP как Git-подмодуль или распарсите jar-ы, вытяните Packet классы.
Создайте свои PacketCodec в пакете org.viabedrock.codec.legacy. – они будут реализовать тот же интерфейс BedrockPacketCodec, но работать с байтовым массивом/ByteBuf напрямую, минуя nukkitx.protocol (там нет кодеков < 291).
Подключите их в ProtocolRegistry по той же схеме.
Для блоков/предметов переложите json-файлы:
• mapping/blocks/block_state_meta_0.14.json → NukkitBlockMapping
• mapping/items/item_runtime_0.14.json → NukkitItemMapping
и т.д.
./gradlew build
java -jar proxy/build/libs/ViaBedrock-proxy-1.0-SNAPSHOT-all.jar
Я могу выложить готовый zip-шаблон с этими файлами + README, чтобы вы просто git init и начали наполнять маппингами. Если нужен – скажите.
• Реализовать «шифт» NBT-чейнджлогов между версиями (chunk palette, biome data).
• Добавить поддержку скинов (они менялись с 0.11.0 → 0.12.0).
• Сделать плагин-формат (jar-in-jar) чтобы можно было подключать кодеки альф-версий без пересборки core.
• Написать CLI-генератор, который из PocketMine-MP item.table + block.table генерирует json-файлы для mapping.
На текущий момент код выше уже позволяет зайти с клиента 1.7 (291) на сервер 1.20.40 (554) и обратно, при условии, что вы положите корректные ItemMapping/BlockMapping json-ы в proxy/src/main/resources/mapping/.