Клиентские пакеты
Клиентские пакеты, это одна из вещей, без которых не обходится практически ни один магический мод.
В этой статье мы разберёмся, для чего нужны клиентские пакеты, как их использовать и рассмотрим применение на практическом примере.
Что такое клиентские пакеты
Клиентские пакеты представляют из себя функции, которые отправляются с сервера на клиент и там выполняются, принимают данные при отправке. Они являются способом общения сервера с игроками и очень полезны.
Чтобы отправить пакет нам нужно получить объект клиента. На клиент всегда отправляются только клиентские пакеты .
Методы
Давайте начнём с методов:
//получили объект клиента конкретного игрока
Network.getClientForPlayer(айди игрока);
//получили объекты клиентов всех игроков
Network.getConnectedClients();
//отправит на все клиенты пакет с сервера
Network.sendToAllClients(name, data: object);
//добавит клиентский пакет
Network.addClientPacket(name, func: (data: object) => void);
//отправит сообщение всем клиентам
Network.sendServerMessage(text);
//превратит серверный айди в локальный (который на клиенте)
Network.serverToLocalId(id: string | number);
//отправит на клиент пакет с сервера
<NetworkClient>.send(name, data: object);
//отправит клиенту текст в чат
<NetworkClient>.sendMessage(text);
Мы бы могли разобрать клиентские пакеты на основе примера банальной отправки текста в чат, но давайте будем креативнее! Помните, мы писали анимацию траты денег? Давайте применим её. Мы будем вызывать её с числом, которое будет являться новым уровнем опыта, которое получил игрок.
Создание пакета
Наш пакет будет запускать на клиенте анимацию с текстом, приходящим из данных пакета. В нашем примере мы применим TypeScript, но лишь для демонстрации приходящих данных.
Network.addClientPacket("packet.example.start_animation", (data: { text: string }) => {
if(!data.text) {
return; //если мы не получили данные, анимация не появится
}
animator.init(data.text); //запускае м анимацию
});
Применение пакета
Отправим наш пакет с сервера на клиент по имени пакета и передадим данные об уровне в качестве текста для анимации.
Callback.addCallback("ExpLevelAdd", (level, playerUid) => {
const client = Network.getClientForPlayer(playerUid); //получили объект клиента в серверном калбеке.
if(client != null) {
client.send("packet.example.start_animation", { text: level }); //отправили данные по имени пакета полученному клиенту
}
});
Дело в том, что нам нужно запустить её на конкретном устройстве, конкретному игроку.
Это позволит избежать редких ошибок.
Синхронизация айди
Представим, мы с сервера отправляем данные о айди предмета на клиент. Снова применим TypeScript для демонстрации.
Network.addClientPacket("packet.example.sync_id", (data: { id: number, count: number, data: number, extra?: ItemExtraData }) => {
const id = data.id //что же не так?
});
Код кажется правильным, но айди на сервере и на клиенте могут отличаться. Давайте получим правильный айди при помощи метода Network.serverToLocalId
и отобразим частицу предмета над игроком.
Network.addClientPacket("packet.example.sync_id", (data: { id: number, count: number, data: number, extra?: ItemExtraData }) => {
const id = Network.serverToLocalId(data.id);
const position = Entity.getPosition(Player.getLocal());
Particles.addBreakingItemParticle(
id, //айди предмета
0, //дата частицы
position.x + 0.5, //по середине по x
position.y + 2, //на 2 блока выше позиции игрока по y
position.z + 0.5 //по середине по z
);
});
Если у вас не осталось вопросов, могу вас поздравить! А если нет, всегда можно перечитать статью и попрактиковаться. Вот несколько задач для вас по возрастанию сложности:
- Напишите клиентский пакет, который будет выводить в чат название предмета. Чтобы получить имя, можете применить метод
IDRegistry.getNameByID(id: number)
. - Напишите метод, который выведет имена всех игроков в чат на клиенте.
- Напишите собственную простенькую анимацию, которая отобразит имена и количество здоровья всех игроков на клиенте.
- Напишите метод, который отсортирует инвентарь по айди измерения. Например если игрок находится в обычном мире, все предметы будут выброшены кроме тех, которые отображают какие-то числа измерения. Например если измерением является обычный мир, предмет будет помещён в слот с номером 1 (если это возможно, иначе к ближайшему возможному), потому-что айди измерения 1. После этого отправьте клиенту пакет и оповестите его о сортировке через
Game.tipMessage(text)
, сообщив, какие предметы были выложены и по какому измерению.