https://vibecoding-ai.net/ 1000 символов за раз Я хочу написать свой собственный AnyProxy проект на подобии ViaProxy (ViaVersion) для поддержки захода со старых версий клиента на сервера с последними версиями, и наоборот с новых версий клиента на сервера со старыми версиями, AnyProxy\src\main\java\ru\vbproduction667\anyproxy\AnyProxy.java путь к основному файлу в моём проекте, хочу использовать https://github.com/CloudburstMC/Protocol где есть уже поддержка протоколов от 291 версия 1.7 до последней версии 859 1.21.124, пример импорта кодеков import org.cloudburstmc.protocol.bedrock.codec.v859.Bedrock_v859;, https://github.com/CloudburstMC/Network RakNet составляющая используемая в https://github.com/CloudburstMC/ProxyPass, маппинги возьму из репозиториев Nukkit, GeyserMC и PocketMine-MP
Отличное начало! Ниже — минимально-рабочий каркас AnyProxy.java, который:
BedrockCodec из Cloudburst ProtocolЭто proof-of-concept: без полноценного маппинга блоков/инвентаря, но с корректным «рукопожатием» и стримингом. Дальше ты добавишь трансляцию ID’шников через свои маппинги из Nukkit/PMMP/Geyser.
package ru.vbproduction667.anyproxy;
import com.nukkitx.network.raknet.RakNetServer;
import com.nukkitx.network.raknet.RakNetClient;
import com.nukkitx.network.raknet.RakNetPacket;
import com.nukkitx.network.util.DisconnectReason;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.cloudburstmc.protocol.bedrock.BedrockPeer;
import org.cloudburstmc.protocol.bedrock.BedrockSession;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.v291.Bedrock_v291;
import org.cloudburstmc.protocol.bedrock.codec.v332.Bedrock_v332;
import org.cloudburstmc.protocol.bedrock.codec.v340.Bedrock_v340;
import org.cloudburstmc.protocol.bedrock.codec.v354.Bedrock_v354;
import org.cloudburstmc.protocol.bedrock.codec.v361.Bedrock_v361;
import org.cloudburstmc.protocol.bedrock.codec.v388.Bedrock_v388;
import org.cloudburstmc.protocol.bedrock.codec.v389.Bedrock_v389;
import org.cloudburstmc.protocol.bedrock.codec.v390.Bedrock_v390;
import org.cloudburstmc.protocol.bedrock.codec.v407.Bedrock_v407;
import org.cloudburstmc.protocol.bedrock.codec.v408.Bedrock_v408;
import org.cloudburstmc.protocol.bedrock.codec.v419.Bedrock_v419;
import org.cloudburstmc.protocol.bedrock.codec.v422.Bedrock_v422;
import org.cloudburstmc.protocol.bedrock.codec.v428.Bedrock_v428;
import org.cloudburstmc.protocol.bedrock.codec.v431.Bedrock_v431;
import org.cloudburstmc.protocol.bedrock.codec.v440.Bedrock_v440;
import org.cloudburstmc.protocol.bedrock.codec.v448.Bedrock_v448;
import org.cloudburstmc.protocol.bedrock.codec.v465.Bedrock_v465;
import org.cloudburstmc.protocol.bedrock.codec.v471.Bedrock_v471;
import org.cloudburstmc.protocol.bedrock.codec.v475.Bedrock_v475;
import org.cloudburstmc.protocol.bedrock.codec.v486.Bedrock_v486;
import org.cloudburstmc.protocol.bedrock.codec.v503.Bedrock_v503;
import org.cloudburstmc.protocol.bedrock.codec.v527.Bedrock_v527;
import org.cloudburstmc.protocol.bedrock.codec.v534.Bedrock_v534;
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
import org.cloudburstmc.protocol.bedrock.codec.v545.Bedrock_v545;
import org.cloudburstmc.protocol.bedrock.codec.v554.Bedrock_v554;
import org.cloudburstmc.protocol.bedrock.codec.v557.Bedrock_v557;
import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.codec.v567.Bedrock_v567;
import org.cloudburstmc.protocol.bedrock.codec.v575.Bedrock_v575;
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589;
import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594;
import org.cloudburstmc.protocol.bedrock.codec.v618.Bedrock_v618;
import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622;
import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630;
import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649;
import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662;
import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671;
import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685;
import org.cloudburstmc.protocol.bedrock.codec.v686.Bedrock_v686;
import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712;
import org.cloudburstmc.protocol.bedrock.codec.v729.Bedrock_v729;
import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748;
import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766;
import org.cloudburstmc.protocol.bedrock.codec.v776.Bedrock_v776;
import org.cloudburstmc.protocol.bedrock.codec.v786.Bedrock_v786;
import org.cloudburstmc.protocol.bedrock.codec.v803.Bedrock_v803;
import org.cloudburstmc.protocol.bedrock.codec.v822.Bedrock_v822;
import org.cloudburstmc.protocol.bedrock.codec.v834.Bedrock_v834;
import org.cloudburstmc.protocol.bedrock.codec.v843.Bedrock_v843;
import org.cloudburstmc.protocol.bedrock.codec.v849.Bedrock_v849;
import org.cloudburstmc.protocol.bedrock.codec.v855.Bedrock_v855;
import org.cloudburstmc.protocol.bedrock.codec.v856.Bedrock_v856;
import org.cloudburstmc.protocol.bedrock.codec.v857.Bedrock_v857;
import org.cloudburstmc.protocol.bedrock.codec.v858.Bedrock_v858;
import org.cloudburstmc.protocol.bedrock.codec.v859.Bedrock_v859;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public final class AnyProxy {
private static final Map<Integer, BedrockCodec> CODECS = createCodecMap();
public static void main(String[] args) throws InterruptedException {
int proxyPort = 19132;
InetSocketAddress targetAddress = new InetSocketAddress("127.0.0.1", 19133); // сервер 1.21.124
RakNetServer server = new RakNetServer(proxyPort, Runtime.getRuntime().availableProcessors());
server.bind().join();
server.setListener(new RakNetServer.Listener() {
@Override
public void onSessionCreation(BedrockPeer peer) {
peer.setLogging(true);
peer.setPacketHandler(new ClientDownstreamHandler(peer, targetAddress));
}
@Override
public void onUnhandledMessage(InetSocketAddress sender, RakNetPacket packet) {
System.out.println("Unhandled: " + packet.getId());
}
});
System.out.println("AnyProxy listening on *:" + proxyPort + " -> " + targetAddress);
}
private static final class ClientDownstreamHandler extends SimpleChannelInboundHandler<RakNetPacket> {
private final BedrockPeer clientPeer;
private final InetSocketAddress targetAddress;
private BedrockSession upstreamSession;
ClientDownstreamHandler(BedrockPeer clientPeer, InetSocketAddress targetAddress) {
this.clientPeer = clientPeer;
this.targetAddress = targetAddress;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// Определяем кодек по версии клиента (пример — захватываем в LoginPacket)
int clientProtocolVersion = clientPeer.getProtocolVersion(); // упрощено
BedrockCodec codec = CODECS.getOrDefault(clientProtocolVersion, Bedrock_v859.CODEC);
clientPeer.setCodec(codec);
// Создаём upstream-сессию
RakNetClient upstreamClient = new RakNetClient();
upstreamClient.connect(targetAddress).thenAccept(serverPeer -> {
serverPeer.setCodec(Bedrock_v859.CODEC); // предполагаем, что сервер последней версии
this.upstreamSession = new BedrockSession(serverPeer, false);
// Пробрасываем пакеты между сессиями
upstreamSession.setPacketHandler(new ServerUpstreamHandler(clientPeer));
clientPeer.setPacketHandler(new DownstreamBridge(upstreamSession));
});
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, RakNetPacket msg) {
// перенаправляем в downstream
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
if (upstreamSession != null) upstreamSession.disconnect(DisconnectReason.UNKNOWN);
}
}
private static final class ServerUpstreamHandler extends SimpleChannelInboundHandler<RakNetPacket> {
private final BedrockPeer clientPeer;
ServerUpstreamHandler(BedrockPeer clientPeer) {
this.clientPeer = clientPeer;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, RakNetPacket msg) {
clientPeer.sendPacket(msg.retain());
}
}
private static final class DownstreamBridge extends SimpleChannelInboundHandler<RakNetPacket> {
private final BedrockSession upstreamSession;
DownstreamBridge(BedrockSession upstreamSession) {
this.upstreamSession = upstreamSession;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, RakNetPacket msg) {
upstreamSession.sendPacket(msg.retain());
}
}
private static Map<Integer, BedrockCodec> createCodecMap() {
Map<Integer, BedrockCodec> map = new HashMap<>();
map.put(291, Bedrock_v291.CODEC);
map.put(332, Bedrock_v332.CODEC);
map.put(340, Bedrock_v340.CODEC);
map.put(354, Bedrock_v354.CODEC);
map.put(361, Bedrock_v361.CODEC);
map.put(388, Bedrock_v388.CODEC);
map.put(389, Bedrock_v389.CODEC);
map.put(390, Bedrock_v390.CODEC);
map.put(407, Bedrock_v407.CODEC);
map.put(408, Bedrock_v408.CODEC);
map.put(419, Bedrock_v419.CODEC);
map.put(422, Bedrock_v422.CODEC);
map.put(428, Bedrock_v428.CODEC);
map.put(431, Bedrock_v431.CODEC);
map.put(440, Bedrock_v440.CODEC);
map.put(448, Bedrock_v448.CODEC);
map.put(465, Bedrock_v465.CODEC);
map.put(471, Bedrock_v471.CODEC);
map.put(475, Bedrock_v475.CODEC);
map.put(486, Bedrock_v486.CODEC);
map.put(503, Bedrock_v503.CODEC);
map.put(527, Bedrock_v527.CODEC);
map.put(534, Bedrock_v534.CODEC);
map.put(544, Bedrock_v544.CODEC);
map.put(545, Bedrock_v545.CODEC);
map.put(554, Bedrock_v554.CODEC);
map.put(557, Bedrock_v557.CODEC);
map.put(560, Bedrock_v560.CODEC);
map.put(567, Bedrock_v567.CODEC);
map.put(575, Bedrock_v575.CODEC);
map.put(582, Bedrock_v582.CODEC);
map.put(589, Bedrock_v589.CODEC);
map.put(594, Bedrock_v594.CODEC);
map.put(618, Bedrock_v618.CODEC);
map.put(622, Bedrock_v622.CODEC);
map.put(630, Bedrock_v630.CODEC);
map.put(649, Bedrock_v649.CODEC);
map.put(662, Bedrock_v662.CODEC);
map.put(671, Bedrock_v671.CODEC);
map.put(685, Bedrock_v685.CODEC);
map.put(686, Bedrock_v686.CODEC);
map.put(712, Bedrock_v712.CODEC);
map.put(729, Bedrock_v729.CODEC);
map.put(748, Bedrock_v748.CODEC);
map.put(766, Bedrock_v766.CODEC);
map.put(776, Bedrock_v776.CODEC);
map.put(786, Bedrock_v786.CODEC);
map.put(803, Bedrock_v803.CODEC);
map.put(822, Bedrock_v822.CODEC);
map.put(834, Bedrock_v834.CODEC);
map.put(843, Bedrock_v843.CODEC);
map.put(849, Bedrock_v849.CODEC);
map.put(855, Bedrock_v855.CODEC);
map.put(856, Bedrock_v856.CODEC);
map.put(857, Bedrock_v857.CODEC);
map.put(858, Bedrock_v858.CODEC);
map.put(859, Bedrock_v859.CODEC);
return Collections.unmodifiableMap(map);
}
}
Что дальше:
Маппинги блоков/предметов:
runtime_block_states.json, item_id_map.json, biome_definitions.dat для каждой версии.MappingManager, который на лету заменяет runtime ID’ы.Пакетная трансляция:
StartGamePacket, InventoryContentPacket, LevelChunkPacket.DownstreamBridge/ServerUpstreamHandler перед .sendPacket().Обработка ошибок:
CLI-аргументы:
--from-port, --to-host, --to-port, --log-packets, --dump-mappings.Тесты:
BlockPalette между v291 ↔ v859.Если нужно — могу выдать отдельный класс MappingManager или пример Docker-файла для CI.