#3) Учимся одностороннему общению сервер>клиент без особых заморочек (IT-??)

Тут научимся кидать данные с сервера в клиент парой окольных путей.​

  • Путь №1 - использование HTML файлов для передачи параметров.
Клиент получает всё наполнение HTML файла на сервере. Зная это, мы можем воспользоваться умением клиента парсить данные с текста (ParseInt, ParseString, ...)

Возьмём простейшую хтмлку и докинем ей пару параметров:
HTML:
<html><head><body>You are either not on a quest that involves this NPC, or you don't meet this NPC's minimum quest requirements.
</body></html>
ParameterInt=123
ParameterString=text

Пора зайти в интерфейс, класс NPCDialogWnd.uc. Конкретно нас интересует функция HandleLoadHtmlFromString.

Находим кусочек:
C:
ParseString(param, "HTMLString", htmlString);

Это и есть наша стринга, которая уже содержит вышеуказанные параметры. Да, можно парсить новые параметры сразу с param, как хотите, в целом и так и так будет работать.

Далее всё просто - мы ещё раз парсим эти данные, указав тип и имя параметра.
C:
local int int_param;
local string string_param;

ParseInt(htmlString, "ParameterInt", int_param);
ParseString(htmlString, "ParameterString", string_param);
На выходе переменные будут равны:
int_param = 123
string_param = text

Самое простое для чего это используется - изменение размеров окна хтмлки. Что бы работало корректно, необходимо маленько скорректировать абсолютные размеры элементов.

  • Путь №2 - UIEvent, AITimer или как я "придумал" систему эвентов в системе эвентов
Сразу скажу, что понятия не имею "чётамвявах", данные опыты только с PTS'ом. Говорю я о функции SendUIEvent(talker, ...) в АИ.
Позволяет она швырнуть 2(3) ИНТа + 6 стрингов, но блоки стрингов ограничены размером пакета, так что бесконечные тексты туда не засунешь

В клиент уходит запрос, который состоит, из:
  • 90000 - выдуманный нами и уникальный ИД эвента, что бы разделять то, что мы шлём
  • 100, 200 и text - полноценная информация, которую мы будем использовать
C:
SendUIEvent(talker, 90000, 100, 200, "text", "", "", "", "", "");


Далее снова переходим в клиент и начинаем допихивать куски, которые помогут принимать этот пакет в любом окне:
C:
RegisterEvent( EV_AITimer );
function OnEvent(int Event_ID, string param)
{  
        case EV_AITimer:
            AIOnEvent(Param);
        break;      
    }      
}
А теперь к тому, почему это система эвентов в системе эвентов - мы приняли её в стандартном OnEvent и перекинули с самодельный, который по сути займётся тем же - спарсит ИД и пойдёт выполнять нужное действие.
C:
function AIOnEvent(string Param)
{
    local int     Event;
    local int i1, i2;
    local string s1;
    Parseint(Param, "EventID", Event);
   
    switch(Event)
    {      
    case 90000:
        Parseint(Param, "Ask", i1);
        Parseint(Param, "Reply", i2);
        ParseString(Param, "Param1", s1);
        break;
    }
}

Где переменные в клиенте заполнились тем, что мы в них кинули из сервера:
i1 = 100
i2 = 200
s1 = text

Как использовать - решайте сами.
 

Сразу скажу, что понятия не имею "чётамвявах", данные опыты только с PTS'ом. Говорю я о функции SendUIEvent(talker, ...) в АИ.
Позволяет она швырнуть 2(3) ИНТа + 6 стрингов, но блоки стрингов ограничены размером пакета, так что бесконечные тексты туда не засунешь
В "явах" еще проще - это все шлется через пакет ExSendUIEvent, который так же можно слать как душе угодно и откуда угодно.
Вобще, в теории, можно по идее отослать до 10 стрингов, как 5 параметров для каждого из двух сисстрингов, ид которых отсылаются в пакете + как уже выше сказано просто 2 инта, которые шлются там же отдельно.
Java:
    @Override
    protected void writeImpl()
    {
        writeEx(Opcode.ExSendUIEvent);
        writeD(_objectId);
        writeD(_style);
        writeD(0x00); // unk
        writeD(0x00); // unk
        writeS(String.valueOf(_mode));

        if (_mode >= 0 && _style < 6)
        {
            writeS(String.valueOf(_value1 / 60));
            writeS(String.valueOf(_value1 % 60));
            writeS(String.valueOf(_value2 / 60));
            writeS(String.valueOf(_value2 % 60));
        }
        else
        {
            writeS(String.valueOf(_value1)); // 1-й инт
            writeS(String.valueOf(_value2)); // 2-й инт
            writeS(String.valueOf(_sysStringId1));
            writeS(String.valueOf(_sysStringId2));
        }

        writeElements(); // параметры для сисстрингов
    }
 
который так же можно слать как душе угодно и откуда угодно.
размышлял над этим, действительно в яве способ ещё более интересный получается, т.к. с сорцом сервера всё ограничивается лишь фантазией (откуда кидать), в то время как пэтос - костыли на нпц, ну или анальные допилы
 
  • Мне нравится
Реакции: kick
А теперь при отсылке большого количества стрингов- вы будете в клиенте получать не слабый такой залаг.
Потому что стринг в байтовом выражении самый большой объем занимает.
 
Ну разве что флудить пакетом ну я хз, сотнями раз в секунду.
Ну и я вобще-то сомневаюсь что будут в этом пакете слать простыни текста в несколько килобайт хотя бы.
 
Ну разве что флудить пакетом ну я хз, сотнями раз в секунду.
Ну и я вобще-то сомневаюсь что будут в этом пакете слать простыни текста в несколько килобайт хотя бы.
Поверьте встречались клиенты которые там почти сборники Достоевского пытались отсылать. Ведь все зависит от того что именно вам нужно отсылать. А вдруг к примеру кучу айтемов. Бывают и такие запросы- причем айтемы кастомные.
 
А теперь при отсылке большого количества стрингов- вы будете в клиенте получать не слабый такой залаг.
Потому что стринг в байтовом выражении самый большой объем занимает.
скажем так: наше дело реализация, а оптимизаций пусть занимается кто-то другой
 
Последнее редактирование:
Не, в принципе, если отправлять небольшой объем данных и редко - очень даже вариант, хотя и костыль, если же слать длинную строку - парс этой строки уже будет лагать
 
Кстати, я чего тут подумал - есть же по идее еще удобный пакет для отправки чего-то клиенту в интерфейс.
Я про ExBR_BroadcastEventState, позволяющий отправить клиенту 6 числовых значений + 2 строки.
Точнее числовых значений можно отправить 7, но на _eventId логичней просто повесить какое-то определенное значение, по которому будет детектиться что в пакете пришли нестандартные данные для использования в чем-то своем.
Java:
    @Override
    protected void writeImpl()
    {
        writeEx(Opcode.ExBR_BroadcastEventState);
        writeD(_eventId);
        writeD(_eventState);
        writeD(_param0);
        writeD(_param1);
        writeD(_param2);
        writeD(_param3);
        writeD(_param4);
        writeS(_param5);
        writeS(_param6);
    }
 
В обратную сторону из интерфейса можно слать произвольный String до 1024 символов через функцию:
RequestPCCafeCouponUse(string);

На сервер уходит пакет: D0:19(для 273 ХФ) с этой строкой.
Удобно, т.к в большинстве случаев этот пакет почти не используется, ну и + строка, это строка.
 
А еще можно не заморачиваться с отправкой на сервер в особых пакетах, а просто слать в Say2 строку, задавая ей какой-то особый префикс, чтобы такие строки не в чат выводило, а по особому обрабатывало.
Вобщем тот же принцип что и с войсед командами, начинающимися с точки.
 
А еще можно не заморачиваться с отправкой на сервер в особых пакетах, а просто слать в Say2 строку, задавая ей какой-то особый префикс, чтобы такие строки не в чат выводило, а по особому обрабатывало.
Вобщем тот же принцип что и с войсед командами, начинающимися с точки.
да и игрокам на стороне ифейса не забыть запретить использование этого префикса)
 
Я как истинный бот не понял по первому пункту где мы реализуем размер окна?
 
Кстати, я чего тут подумал - есть же по идее еще удобный пакет для отправки чего-то клиенту в интерфейс.
Я про ExBR_BroadcastEventState, позволяющий отправить клиенту 6 числовых значений + 2 строки.
Точнее числовых значений можно отправить 7, но на _eventId логичней просто повесить какое-то определенное значение, по которому будет детектиться что в пакете пришли нестандартные данные для использования в чем-то своем.
Java:
    @Override
    protected void writeImpl()
    {
        writeEx(Opcode.ExBR_BroadcastEventState);
        writeD(_eventId);
        writeD(_eventState);
        writeD(_param0);
        writeD(_param1);
        writeD(_param2);
        writeD(_param3);
        writeD(_param4);
        writeS(_param5);
        writeS(_param6);
    }
можно чуть подробней как это обработать на стороне клиента?
 
можно чуть подробней как это обработать на стороне клиента?
Насколько помню там есть обработка особых эвентовых окон для некоторых эвентов по их эвентид как раз - вот на эту тему и поискать там в коде интерфейса и туда вклиниться.
Известные мне эвентиды
Java:
    public static final int APRIL_FOOLS = 20090401;
    public static final int EVAS_INFERNO = 20090801; // event state (0 - hide, 1 - show), day (1-14), percent (0-100)
    public static final int HALLOWEEN_EVENT = 20091031; // event state (0 - hide, 1 - show)
    public static final int RAISING_RUDOLPH = 20091225; // event state (0 - hide, 1 - show)
    public static final int LOVERS_JUBILEE = 20100214; // event state (0 - hide, 1 - show)
    public static final int APRIL_FOOLS_10 = 20100401; // event state (0 - hide, 1 - show)
Смотри вобщем в интерфейсе классы начинающиеся на BR_Event
 
Последнее редактирование:
Насколько помню там есть обработка особых эвентовых окон для некоторых эвентов по их эвентид как раз - вот на эту тему и поискать там в коде интерфейса и туда вклиниться.
Известные мне эвентиды
Java:
    public static final int APRIL_FOOLS = 20090401;
    public static final int EVAS_INFERNO = 20090801; // event state (0 - hide, 1 - show), day (1-14), percent (0-100)
    public static final int HALLOWEEN_EVENT = 20091031; // event state (0 - hide, 1 - show)
    public static final int RAISING_RUDOLPH = 20091225; // event state (0 - hide, 1 - show)
    public static final int LOVERS_JUBILEE = 20100214; // event state (0 - hide, 1 - show)
    public static final int APRIL_FOOLS_10 = 20100401; // event state (0 - hide, 1 - show)
Смотри вобщем в интерфейсе классы начинающиеся на BR_Event
уже разобрался как через ExSendUIEvent посылать/принимать, BIT_hack направил в нужное русло
 
А еще можно не заморачиваться с отправкой на сервер в особых пакетах, а просто слать в Say2 строку, задавая ей какой-то особый префикс, чтобы такие строки не в чат выводило, а по особому обрабатывало.
Вобщем тот же принцип что и с войсед командами, начинающимися с точки.
Я прям вижу как в строку отправляется 20 байт вместо 4 байт, при записи инт значения как строку (2.147...ккк), особенно если таких записей нужно отправить сотни в одном пакете и летит ошибка с BufferUnderflowException либо просто крашится клиент

В любом случае, это решение как internet explorer, морально и физически устарело и будет актуально для старых клиентов и простых кастомных пакетов.
 
Назад
Сверху Снизу