Напишичто-тонаподобииViaVersion(ViaProxy)нодляMinecraft:BedrockEditionдлявозможностизайтисостарыхверсийклиентанановыеверсиисерверовинаоборот,сновыхверсийклиента,настарыеверсиисерверов.НапишиегонаJavaиспользуяhttps://github.com/CloudburstMC/Protocolбезегомодификацииаиспользуйеговэтомпроекте,маппингиямогусамдобавитьиздругихрепозиториевнаGitHubвзявихуNukkit,PocketMine-MP,BedrockDataBedrockBlockUpgradeSchema,BedrockItemUpgradeSchema,GeyserMCmappings,уhttps://github.com/CloudburstMC/Protocolестьготоваяподдержкасервернойсоставляющейпротоколовот291допоследнейверсии,протокол291этоверсия1.7BedrockEdition,сделайеёпокаподдерживаемойвэтомпроекте,ноябыхотелвсеверсииподдерживатьвплотьдоальфа0.1.0-0.1.3,ноэтоужепосложнеепакетыпридётсятожебратьсNukkitапослеPocketMine-MP,таккакNukkitпоявилсявовремяверсии0.13.0-0.14.0.Хочуподдерживатьверсии1.211.201.191.181.171.161.141.131.121.111.101.91.81.71.61.51.41.21.11.00.160.150.140.130.120.110.100.90.80.70.60.50.40.30.20.1Уменяужеестьзарезервированнаяструктурапр
Отлично, ты делаешь аналог ViaProxy, но для Minecraft: Bedrock Edition, с фокусом на поддержку широкого диапазона версий клиентов и серверов, включая альфа-версии. Ты хочешь использовать CloudburstMC/Protocol как основу, но без модификации, и доставать маппинги из внешних репозиториев (Nukkit, PocketMine-MP, Geyser, BedrockData и т.п.).
Я помогу тебе с базовой структурой Java-проекта, который:
bedrock-via-proxy/
├── src/main/java/
│ └── com/yourname/bedrockviaproxy/
│ ├── proxy/
│ │ ├── BedrockViaProxy.java
│ │ ├── ProxySession.java
│ │ ├── VersionBridge.java
│ │ └── MappingsLoader.java
│ ├── codec/
│ │ ├── PacketCodec.java
│ │ └── PacketMapper.java
│ └── utils/
│ └── VersionUtil.java
├── mappings/
│ ├── blocks/
│ ├── items/
│ └── packets/
├── build.gradle
└── README.md
build.gradleplugins {
id 'java'
id 'application'
}
group = 'com.yourname'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.nukkitx.protocol:bedrock-v291:2.9.10-SNAPSHOT'
implementation 'com.nukkitx.protocol:bedrock-v422:3.0.0-SNAPSHOT'
implementation 'com.nukkitx.protocol:bedrock-v486:3.0.0-SNAPSHOT'
implementation 'com.nukkitx.protocol:bedrock-latest:3.0.0-SNAPSHOT'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
implementation 'org.slf4j:slf4j-simple:2.0.9'
}
application {
mainClass = 'com.yourname.bedrockviaproxy.proxy.BedrockViaProxy'
}
BedrockViaProxy.javapublic class BedrockViaProxy {
public static void main(String[] args) {
int proxyPort = 19132;
String targetServer = "127.0.0.1";
int targetPort = 19133;
ProxySession session = new ProxySession(proxyPort, targetServer, targetPort);
session.start();
}
}
ProxySession.javapublic class ProxySession {
private final BedrockServer server;
private final String targetServer;
private final int targetPort;
public ProxySession(int port, String targetServer, int targetPort) {
this.server = new BedrockServer(new InetSocketAddress("0.0.0.0", port));
this.targetServer = targetServer;
this.targetPort = targetPort;
}
public void start() {
server.setHandler(new BedrockServerEventHandler() {
@Override
public boolean onConnectionRequest(InetSocketAddress address) {
return true;
}
@Override
public BedrockPong onQuery(InetSocketAddress address) {
return new BedrockPong()
.edition("MCPE")
.motd("BedrockViaProxy")
.playerCount(0)
.maximumPlayerCount(20)
.gameType("Survival")
.protocolVersion(291); // fallback
}
@Override
public void onSessionCreation(BedrockServerSession session) {
session.setPacketHandler(new ProxyPacketHandler(session, targetServer, targetPort));
}
});
server.bind().join();
}
}
ProxyPacketHandler.javapublic class ProxyPacketHandler implements BedrockPacketHandler {
private final BedrockServerSession clientSession;
private final String targetServer;
private final int targetPort;
private BedrockClient client;
private BedrockClientSession serverSession;
public ProxyPacketHandler(BedrockServerSession clientSession, String targetServer, int targetPort) {
this.clientSession = clientSession;
this.targetServer = targetServer;
this.targetPort = targetPort;
connectToServer();
}
private void connectToServer() {
this.client = new BedrockClient(new InetSocketAddress(targetServer, targetPort));
client.connect().whenComplete((session, throwable) -> {
if (throwable != null) {
clientSession.disconnect("Failed to connect to server");
return;
}
this.serverSession = session;
session.setPacketHandler(new ServerToClientHandler(clientSession));
});
}
@Override
public boolean handle(LoginPacket packet) {
// TODO: detect client version and map login
return serverSession.sendPacket(packet);
}
@Override
public boolean handle(MovePlayerPacket packet) {
// TODO: map packet fields
return serverSession.sendPacket(packet);
}
// etc...
}
VersionBridge.javapublic class VersionBridge {
public static BedrockCodec getCodec(int protocolVersion) {
switch (protocolVersion) {
case 291: return Bedrock_v291.V291_CODEC;
case 388: return Bedrock_v388.V388_CODEC;
case 422: return Bedrock_v422.V422_CODEC;
case 486: return Bedrock_v486.V486_CODEC;
default: return Bedrock_v560.V560_CODEC;
}
}
public static PacketMapper getMapper(int from, int to) {
return MappingsLoader.load(from, to);
}
}
MappingsLoader.javapublic class MappingsLoader {
public static PacketMapper load(int from, int to) {
Path path = Paths.get("mappings/packets", from + "_to_" + to + ".json");
if (!Files.exists(path)) return null;
try {
Map<String, Object> mappings = new ObjectMapper().readValue(path.toFile(), Map.class);
return new PacketMapper(mappings);
} catch (IOException e) {
System.err.println("Failed to load mappings from " + path);
return null;
}
}
}
mappings/ и обновляться вручную или парситься из репозиториев (Geyser, PMMP, Nukkit, etc.).VersionBridge.LoginPacket.Если хочешь — могу помочь с авто-скриптом для генерации маппингов из Geyser/Nukkit/PocketMine.