[РЕШЕНО]Как вывести List<String> с серверной части TileEntity в GuiContainer

Версия Minecraft
1.12.2
API
Forge
30
2
0
WLGUI.png
Есть такой интерфейс. После ввода имени игрока и нажатия "+" или "-" отправляется пакет который редактирует String List внутри TileEntity, а ниже поля для ввода должен выводиться список имён в листе. Однако информация о листе на клиенте и сервере отличается. На сервере данные правильные на клиенте нет(возможно это происходит из-за ошибки в методе добавления имён в лист). ну вот собственно вопрос: Как вывести List<String> с серверной части TileEntity в GuiContainer?


UPD:

Итоговый вариант:
WhiteListGui:
@Override
protected void actionPerformed(GuiButton B) {
    if(B.id == 1) {
        this.tileentity.addToWhiteListNames(this.gtf.getText());
    }
    if(B.id == 2) {
        this.tileentity.removeFromWhiteListNames(this.gtf.getText());
    }
}

TileEntity:
public void addToWhiteList(String name) {
    if(this.world != null && name != "" && name != null && !this.whitelist.contains(name)) {
        WhiteList WhiteList = new WhiteList(this.pos, name, 1);
        CommonProxy.simpleNetworkWrapper.sendToServer(WhiteList);
    }
}
public void removeFromWhiteList(String name) {
    if(this.world != null && name != "" && name != null && this.whitelist.contains(name)) {
        WhiteList WhiteList = new WhiteList(this.pos, name, 0);
        CommonProxy.simpleNetworkWrapper.sendToServer(WhiteList);
    }
}

public void setWhiteList(List<String> newwhitelist) {
    this.whitelist = newwhitelist;
    this.markDirty();
    if (this.world != null) {
        IBlockState state = this.world.getBlockState(this.getPos());
        this.world.notifyBlockUpdate(this.getPos(), state, state, 3);
    }
}

SWhiteList:
@Override
public IMessage onMessage(final WhiteList message, MessageContext ctx) {
    if(message.getAction() == 1) {
        tileentity.whitelist.add(message.getName());
        CWhiteList CWhiteList = new CWhiteList(message.getPosition(), cmte.coreminerwhitelistnames, 1);
        CommonProxy.simpleNetworkWrapper.sendToAll(CWhiteList);
    }

    if(message.getAction() == 0) {
        tileentity.whitelist.remove(message.getName());
        CWhiteList CWhiteList = new CWhiteList(message.getPosition(), cmte.getCoreMinerWhiteListNames(), 0);
        CommonProxy.simpleNetworkWrapper.sendToAll(CWhiteList);
    }
    return null;
}

CWhiteList:
public class CWhiteList implements IMessage, IMessageHandler<CWhiteList, IMessage> {
    private List<String> whitelist;

    public CWhiteList(List<String> whitelist) {
        this.whitelist = whitelist;
    }

    @Override
    public void toBytes(ByteBuf buf) {
        buf.writeShort(this.whitelist.size());
        for (String name : this.whitelist) {
            ByteBufUtils.writeUTF8String(buf, name);
        }
    }

    @Override
    public void fromBytes(ByteBuf buf) {
        short size = buf.readShort();
        this.whitelist = new ArrayList<>();
        for(int index = 0; index < size; index++) {
            this.whitelist.add(ByteBufUtils.readUTF8String(buf));
        }
    }

    @Override
    public IMessage onMessage(final CWhiteList message, MessageContext ctx) {
        tileentity.setWhiteList(message.whitelist);
        return null;
    }
}
 
Последнее редактирование:
Решение
То есть в методе addToWhiteList нужно отправить Client side пакет, который содержит данные листа с сервера?
Тебе нужно отправлять клиентский пакет с данными клиента. При обработке пакеты ты заменяешь данные на сервере клиентскими данными (которые ты получил из пакета). После того, как данные на сервере обновились, кидаешь серверный пакет клиенту. Уже в этом пакете ты обновляешь данные клиента (взяв данные с сервера, естественно).
1,371
112
241
Ты не получаешь список имён с сервера (либо не обновляешь).
Пиши пакет, который после отправки нового игрока или при открытии гуишки обновляет данные листа для клиента, получив данные с сервера. При закрытии своей гуишки не забудь лист очищать.
 
30
2
0
То есть в методе addToWhiteList нужно отправить Client side пакет, который содержит данные листа с сервера?
Тогда наверное нужно записать List<String> в ByteBuf?
Если да, то как записать и читать листы в ByteBuf я тоже не знаю.
 
1,371
112
241
То есть в методе addToWhiteList нужно отправить Client side пакет, который содержит данные листа с сервера?
Тебе нужно отправлять клиентский пакет с данными клиента. При обработке пакеты ты заменяешь данные на сервере клиентскими данными (которые ты получил из пакета). После того, как данные на сервере обновились, кидаешь серверный пакет клиенту. Уже в этом пакете ты обновляешь данные клиента (взяв данные с сервера, естественно).
 
1,074
72
372
При обработке пакеты ты заменяешь данные на сервере клиентскими данными (которые ты получил из пакета)
Так себе идея. Конфликт гарантирован если два игрока одновременно зайдут в интерфейс.
 
1,371
112
241
два игрока одновременно зайдут в интерфейс.
Судя по тому, что человек делает вайтлист, то доступ есть только у одного.

Если доступ есть у нескольких игроков к этому интерфейсу, тогда лист придётся дополнительно чистить при подаче с клиента на сервер (на стороне сервера). Иначе выйдет так, что будет несколько одинаковых имён игрока, либо уже убранный игрок вновь окажется в листе. (Автору темы)
 
30
2
0
Судя по тому, что человек делает вайтлист, то доступ есть только у одного.
Доступ только у владельца.

Тебе нужно отправлять клиентский пакет с данными клиента. При обработке пакеты ты заменяешь данные на сервере клиентскими данными (которые ты получил из пакета).
Эту часть сделал, а обновить данные клиента не могу так как не знаю как записывать и читать листы в ByteBuf
 
Последнее редактирование:
346
25
94
Думаю что должно быть не так. Можно поподробнее?
Записываешь размер коллекции, а дальше циклом саму коллекцию, в чтении читаешь размер и далее циклом от нуля до n читаешь саму коллекцию.
 
1,371
112
241
Доступ только у владельца.


Эту часть сделал, а обновить данные клиента не могу так как не знаю как записывать и читать листы в ByteBuf
Обычный цикл forech (for(String str : list)). Затем записываешь в буфер размер коллекции.
При чтении сначала получаешь размер коллекции. Затем этот размер используешь в обычном цикле. В цикле получаешь необходимые String'и и зписываешь их в лист.
Не будет, если использовать Set коллекцию.
Мы исходим из того, что человек использует List коллекцию, а не Set.
 
30
2
0
"А надо Set, так что замечание очень уместеное."
Я правильно понимаю, что set это лист в котором нет повторяющихся элементов?

Обычный цикл forech (for(String str : list)). Затем записываешь в буфер размер коллекции. При чтении сначала получаешь размер коллекции. Затем этот размер используешь в обычном цикле. В цикле получаешь необходимые String'и и зписываешь их в лист.
Попытался реализовать:

Для read вроде получилось.
public void fromBytes(ByteBuf buf):
for(int index = 0; index < size; index++) {
       this.whitelist.add(ByteBufUtils.readUTF8String(buf));
}

А с write думаю без примера кода не разберусь.
 
434
41
110
А с write думаю без примера кода не разберусь.
Предложу альтернативное решение, которое может сработать. ByteBuf поддерживает запись массива байт, насколько помню.
А что есть строка? (Массив байт) -> Получаем массив байт из строки (специальный метод есть), потом записываем, а когда нужно - читаем байты, и восстанавливаем строку new String(new byte[]{/*массив байт*/}).
А чтобы затолкать в 1 строку, несколько имен игроков, используй String#join и String#split
 
30
2
0

_SupCM_,​


fromBytes:
@Override
public void fromBytes(ByteBuf buf) {
    short size = buf.readShort();
    List<String> whitelist = new ArrayList<>();
    for(int index = 0; index < size; index++) {
        whitelist.add(ByteBufUtils.readUTF8String(buf));
    }
}
toBytes:
@Override
public void toBytes(ByteBuf buf) {
    buf.writeShort(this.whitelist.size());
    for (String name : this.whitelist) {
        ByteBufUtils.writeUTF8String(buf, name);
    }
}

Вот код fromBytes и toBytes. Работает нормально(на каждом этапе проверил. Всё пишется и читается). Однако в onMessage, лист всё равно попадает пустым. Думаю дело в том, что в этом коде в методе load было: return new T2ListPacket(list);. Я в методе fromBytes, полагаю, так сделать не могу.
 
Сверху