[1.7.10] Пакети

Версия Minecraft
1.7.10
API
Forge
45
2
3
Делаю блоки автоботании. Сделал. Для отображения количества мани столкнулся с проблемой что мана что юзает ae2 для крафта и nbt она на сервере а для отображения нужна мана на клиенте. Я посммотрел много туториалов на етом форуме и несумел сделать то что нужно. Мб рукожоп. Может кто сможет чтото посоветувать или возможно даст чейто мод где можно подсмотреть
 
Привет! Да, проблема знакомая. В Minecraft 1.7.10 данные на сервере и клиенте живут отдельно, и чтобы отображать ману на клиенте, её нужно синхронизировать.

Синхронизация через пакеты:
Forge позволяет отправлять данные с сервера на клиент с помощью сетевых пакетов. Тебе нужно создать кастомный пакет, который будет передавать текущее значение маны с сервера на клиент. На клиенте ты сможешь использовать это значение для отображения.
Вот пример реализации из книжки по моддингу - тык

Пример простого пакета:
Создай класс для пакета, который будет отправлять ману. Вот пример:
Java:
public class ServerMessagePacket implements IMessage {

    // Набор полей данных пакета
    private String message;
    private int number;

    public ServerMessagePacket() {
    }

    /**
     * @param message Сообщения, которое будет выводиться на серверной стороне.
     * @param number Число, которое будет выводиться на серверной стороне.
     */
    public ServerMessagePacket(String message, int number) {
        this.message = message;
        this.number = number;
    }

    /**
     * Читает данные пакета из ByteBuf при получении.
     */
    @Override
    public void fromBytes(ByteBuf buf) {
        message = ByteBufUtils.readUTF8String(buf);
        number = buf.readInt();
    }

    /**
     * Записывает данные пакета в ByteBuf перед отправкой.
     */
    @Override
    public void toBytes(ByteBuf buf) {
        ByteBufUtils.writeUTF8String(buf, message);
        buf.writeInt(number);
    }

    public static class Handler implements IMessageHandler<ServerMessagePacket, IMessage> {

        /**
         * Данный метод вызывается для обработки входящих данных из пакета.
         */
        @Override
        public IMessage onMessage(ServerMessagePacket packet, MessageContext ctx) {
            String message = packet.message;
            int number = packet.number;
            // Получаем игрока, который прислал нам пакет.
            EntityPlayerMP player = ctx.getServerHandler().playerEntity;

            // Отправляем сообщение игроку
            player.addChatMessage(new ChatComponentText("Вывожу текст \"" + message + "\" с числом \"" + number + "\""));

            return null; // В ответ ничего не отправляем
        }
    }
}

На сервере отправляй пакет, когда мана меняется:

YourMainClass.NETWORK.sendToPlayer((ServerPlayerEntity) player, new ManaUpdatePacket(currentMana));

Где подсмотреть:
Посмотри исходники Botania или AE2. В Botania есть система управления маной, а в AE2 — синхронизация данных между сервером и клиентом. Это может помочь понять, как всё устроено.

Но новичку могу посоветовать, пока, использовать готовую библиотеку - ElegantNetworking

Если что-то непонятно, пиши, помогу разобраться! Удачи с модом :)
 
Если что-то непонятно, пиши, помогу разобраться! Удачи с модом :)
Выйди из темы, GPT-бот.

Пакетная система хорошо расписана в учебнике. Если это блок с тайлом, можно использовать стандартный Description пакет для передачи NBT на клиент, без необходимости городить свою систему обработки.
 
Как вариант что-бы на 1.7.10 передать данные тайла, можно использовать внутренние методы getDescriptionPacket() и onDataPacket

Java:
public class TileManaSomething extends TileEntity {
    private int manaValue; // Условная мана

    @Override
    public void updateEntity() { // Метод обновления, вызывается каждый тик
        if (!world.isRemote) {
            // Тригеррит обновление блока в мире, заставляя отослать Description packet который в данном примере содержит нбт-данные тайла
            worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
        }
    }

    @Override
    public void writeToNBT(NBTTagCompound tag) {
        super.writeToNBT(tag); // Не забываем вызвать метод записи из TileEntity, т.к. там пишутся важные данные
        tag.setInteger("mana", manaValue); // Записываем нашу ману
    }
    
    @Override
    public void readFromNBT(NBTTagCompound tag) {
        super.readFromNBT(tag); // Здесь тоже не забываем вызвать метод из TileEntity, на этот раз чтения
        manaValue = tag.getInteger("mana"); // Получаем нашу ману
    }

    @Override
    public Packet getDescriptionPacket() { // Возвращает наш Description Packet, в который мы пишем нбт-данные тайла
        NBTTagCompound tag = new NBTTagCompound();
        writeToNBT(tag);
        return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, getBlockMetadata(), tag);
    }

    @Override
    public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) {
        readFromNBT(packet.func_148857_g()); // Читаем данные которые пришли
    }
}

Вуаля, теперь можно передавать данные на клиент

P.S. Вызывать worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); каждый тик - идея не очень хорошая, лучше ограничить таймером, а всю структуру с синхронизацией отделить в абстрактный класс дабы не засирать мод одним и тем же кодом
 
Как вариант что-бы на 1.7.10 передать данные тайла, можно использовать внутренние методы getDescriptionPacket() и onDataPacket

Java:
public class TileManaSomething extends TileEntity {
    private int manaValue; // Условная мана

    @Override
    public void updateEntity() { // Метод обновления, вызывается каждый тик
        if (!world.isRemote) {
            // Тригеррит обновление блока в мире, заставляя отослать Description packet который в данном примере содержит нбт-данные тайла
            worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
        }
    }

    @Override
    public void writeToNBT(NBTTagCompound tag) {
        super.writeToNBT(tag); // Не забываем вызвать метод записи из TileEntity, т.к. там пишутся важные данные
        tag.setInteger("mana", manaValue); // Записываем нашу ману
    }
   
    @Override
    public void readFromNBT(NBTTagCompound tag) {
        super.readFromNBT(tag); // Здесь тоже не забываем вызвать метод из TileEntity, на этот раз чтения
        manaValue = tag.getInteger("mana"); // Получаем нашу ману
    }

    @Override
    public Packet getDescriptionPacket() { // Возвращает наш Description Packet, в который мы пишем нбт-данные тайла
        NBTTagCompound tag = new NBTTagCompound();
        writeToNBT(tag);
        return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, getBlockMetadata(), tag);
    }

    @Override
    public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) {
        readFromNBT(packet.func_148857_g()); // Читаем данные которые пришли
    }
}

Вуаля, теперь можно передавать данные на клиент

P.S. Вызывать worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); каждый тик - идея не очень хорошая, лучше ограничить таймером, а всю структуру с синхронизацией отделить в абстрактный класс дабы не засирать мод одним и тем же кодом


А markDirty() не подойдет? Он своей жизнью живет на обновление чанка?

1744059787308.png
 
Назад
Сверху