Иконка ресурса

(tiny) Система пакетов

Крч в 1.13 и далее Forge решил сильно поменяться, причём не в лучшую сторону (хотя некоторые штуки они сделали прикольно), и потому мой сетевой код слегк сломался.

Вот обновлённая версия, которая работает примерно так же, с теми же плюсами (один небольшой класс, идеально для маленьких модов где вам нужен аж один апдейт по сети послать):

Java:
public final class Network {

    private static final ResourceLocation CHANNEL = new ResourceLocation(MODID, "channel");

    @SubscribeEvent
    public static void init() { // я вызываю это из FMLCommonSetupEvent, вроде ок
        String version = JarVersionLookupHandler.getImplementationVersion(MyMod.class).orElse("DEBUG");
        // ^ это версия протокола, можете ставить свою строку, но менять её тогда когда отсылаемые вами пакеты меняются
        NetworkRegistry.newEventChannel(
                CHANNEL,
                () -> version, // собственно тут эту версию фордж получает динамически, неясно нафига конечно
                version::equals, // проверка версии на клиенте, можно какие-то условия в лябмде описать
                version::equals // аналогично, на сервене
        ).registerObject(Network.class); // регистрируем объект в котором будут @SubscribeEvent методы
    }

    @SubscribeEvent
    @OnlyIn(Dist.CLIENT)
    public static void on(ServerCustomPayloadEvent e) { // не ведитесь на тупое название класса, этот метод вызывается когда клиент получает пакет от сервера
        PacketBuffer payload = e.getPayload();
        Context ctx = e.getSource().get();
        
        switch (payload.readByte()) { //наш "айди" пакета
            case 0:
                float a = payload.readFloat();
                int b = payload.readInt();
                // этот код выполняется в сетевых потоках, с игрой из него взаимодействовать нежелательно
                // но желательно из PacketBuffer'a тут считывать инфу
                ctx.enqueueWork(() -> {
                    // а вот этот enqueueWork выполнит код уже в потоке игры, тут можно блоки сеттить и так далее, взаимодействовать с игрой
                    PlayerEntity player = Minecraft.getInstance().player;
                    if (player != null) {
                        // чего-то делаем с клиенским плеером, это всё пример
                    } else {
                        // опять же, куски моего кода, у вас как вы напрогаете то так и будет
                        LogManager.getLogger(MyMod.class).warn("Clientside player was null on sync!");
                    }
                });
                ctx.setPacketHandled(true);
                break;
            case 1:
                // etc
    }

    @SubscribeEvent
    public static void on(ClientCustomPayloadEvent e) {
        PacketBuffer payload = e.getPayload();
        Context ctx = e.getSource().get();
        ServerPlayerEntity player = ctx.getSender();
        if (player == null) { // это моя проверка, вы себе уже как хотите прогайте
            return;
        }
        switch (payload.readByte()) {
            case 0:
                // точно то же самое что и в методе выше
                ctx.enqueueWork(() -> {...});
                ctx.setPacketHandled(true);
                break;
            case 1:
                // etc
        }
    }

    public static void sendPacket1ToClient(ServerPlayerEntity player, float a, int b) {
        PacketBuffer payload = new PacketBuffer(Unpooled.buffer());
        payload.writeByte(0); // наш "айди", так-то мы просто шлём любые наборы байт по нашему каналу туда-сюда, вы можете слать что хотите, "айди" это я для вас расжёвываю прост
        payload.writeFloat(a);
        payload.writeInt(b);
        player.connection.sendPacket(new SCustomPayloadPlayPacket(CHANNEL, payload));
    }

    @OnlyIn(Dist.CLIENT)
    public static void sendSomePacketToServer(..data) {
        PacketBuffer payload = new PacketBuffer(Unpooled.buffer());
        payload.writeByte(123); // id
        payload.writeSomething(..data);
        ClientPlayNetHandler connection = Minecraft.getInstance().getConnection();
        if (connection == null) {
            // на меня идея ругалась что может быть null, делаем ошибку со своим текстом чтобы из крашлога было ясно что за бред, так-то null оно быть не должно по идее крч
            throw new IllegalStateException("No client-to-server connection");
        }
        connection.sendPacket(new CCustomPayloadPacket(CHANNEL, payload));
    }

    // и больше таких методов пишите для своих пакетов, можете попробовать найти как там слать всем трекающим игрокам, или всем игрокам в радиусе/мире, мне это было не нужно
Сверху