[RGame Engine] Расширения движка, обработчики команд и событий

[RGame Engine] Расширения движка, обработчики команд и событий

roxblnfk
Копия моей статьи с ныне мёртвого develnet.ru
В начало


Учимся использовать сеть в движке, отправлять и обрабатывать события сервера.

(Файлы CLASS TRChatTool.php, CLASS TRCommanderCL.php, CLASS TRProcEventsCL.php, CLASS TRCommander.php и CLASS TRPlayer.php)

TRPlayer

По праву этот класс — не столько расширение движка, сколько одна из основных его частей. Каждый элемент массива <strong>$Players</strong> является объектом класса <strong>TRPlayer</strong>. Из названия ясно, что это "персональный" класс игрока (пользователя).


Рассмотрим переменные (кроме ссылок на основные объекты других классов):

  • $GID (int) - Game ID - игровой идентификатор. Т.е. это ID игрока в массиве $Players объекта класса TRGame
  • $CID (int) - Connection ID - идентификатор сетевого подключения в объекте класса rxnetsv. $CID и $GID очень редко будут совпадать, поэтому не путайте их. $CID нужен для прямого обращения к подключению пользователя (или для получения некоторой информации касательно этого подключения).
  • $Online (bool) - статус игрока. Выставляется автоматически сетевым протоколом. Не рекомендуется выставлять "вручную", просто берите его значение для своих нужд. Если вы хотите, чтобы пользователи с offline статусом могли существовать, то редактируйте функцию onDisconnect класса TRGame (сейчас они автоматически выбрасываются из памяти).
  • $Status (int) - обозначает статусное положение клиента на сервере. Уже в первой версии проекта был написан код авторизации. Так вот, при $Status==0 пользователь является неавторизованным. Такой пользователь может только авторизовываться, а когда авторизуется, то его статус меняется на 1 и пользователь получит доступ к другим возможностям (например чат). В коде будет частенько встречаться какое-нибудь условие с переменной $Status (если отключится игрок со статусом 0, то об этом ни кто не узнает, см. ф-ию kickPlayer()).
  • $Name (false/str) - Ну тут ясно, что это имя пользователя после его авторизации.


Функции этого класса связаны напрямую с обслуживанием профиля:

  • processMe() — самооброботка подключения, если оно установлено. Сюда входит автоматическая отправка буферизованных данных, и вызов функции sockRead().
  • sockRead() — получение данных от пользователя и автоматический вызов функции command() применительно к полученным данным.
  • sockSend() — сиюсекундная отправка данных, если параметр $stack==false, иначе данные идут в буфер программы.
  • command() — отправка пакетов в класс TRCommander (о классе и пакетах см. ниже).
  • getIP() — получить внешний IP адрес пользователя. Функция демонстрирует использование переменно $CID в виде обращения к информации о подключении.

TRCommander

И подошли, наконец-то, к одному из самых интересующих вопросов: как отправить информацию, получить её на другой стороне и обработать нужным мне кодом? И путь нам в классы TRCommanderCL и TRCommander. Если во время прочтения следующего ниже текста вы начнёте сомневаться в том, что полностью понимаете прочитанное, то ознакомьтесь сначала с разделом Сетевой протокол движка (точнее с его заметками), может поможет!

После получения пакета, класс сетевого протокола его расшифровывает и аккуратненько у себя складывает. Далее игровой движок, изымает расшифрованный пакет, и посылает на обработчик команд — в класс TRCommander(CL). Обработчик (функции processServer(), processPlayer()) перед обработкой контента $con смотрит на команду (заголовок) $com, указывающую на код, которым будет производиться обработка. Функция обработчика насыщена комментариями, и вам нужно просто в них разобраться, чтобы ориентироваться, куда добавлять свой код.


Вот пример обработки пакета с командой 100500447 — чат сообщение. Контент этого пакета обрабатывается функцией addMessage() класса TRChatTool. В данном случае в роли контента должен выступать массив, как указанно в комментарии.

switch($com){
 // ........
 // чат TRChatTool array(type,time,user,message)
 case 100500447: return $this->RGame->RChatTool->addMessage($con);
}

На этом этапе рекомендуется попробовать выполнить задачку: разместите на форме любой компонент (например, EditBox), добавьте в обработчик сервера и клиента обработку новой (вашей) команды.

В событии изменения значения EditBox'a поставьте отправление пакета, содержащего вашу команду, а в качестве контента возьмите значение EditBox'a (как это сделать - смотрите на примере кода отправки чат-сообщения)

[Как нибудь засниму и вставлю на это место видео с решением этой задачки и поясню некоторые косяки организации кода (нет)]

TRChatTool

Чат-расширение, которое расширяет не движок, а только функционал программы (базовый инструмент для работы с чатами).

Объект этого класса размещается в переменной $RChatTool объекта класса TRGameClient. Думаю о нём нечего говорить, там всё должно быть понятно...

TRProcEventsCL

С обработчиком команд вроде ясно - что-то на сервере происходит, об этом надо сказать клиенту => просто создаём новую команду, добавляем туда контент и отправляем... Но разных событий может быть неограниченное количество, а коммандер особо засорять новыми и новыми командами не хочется... Можно, конечно, выделить один заголовок (команду) на группу событий, а какое событие конкретно произошло - объявить в контенте. Например, возьмём команду 1234567890 для событий "пользователь присоединился", "пользователь отсоединился", "пользователь сменил имя" и т.д. В принципе это оптимальное решение. Но под этот случай уже есть готовый код.

Написана удобная система событий (эвентов/ивентов, кому как удобнее), предназначенная для отправки "не обязательной" информации о событиях. К примеру, сообщение о том, что кто-то покинул сервер можно обрабатывать на оставшихся клиентах, а можно и не обрабатывать, в отличие от другой информации — чат-сообщения, например. Т.е. в чат мы обязаны выводить сообщения от других пользователей, но вот "Пользователь 123 покинул нас" можем и не выводить по разным причинам. Ну а серверу ваши ненужные события знать не нужно, поэтому удобная передача событий реализована только от сервера на клиент:

Вот код на сервере, выполняемый при отсоединении пользователя от сервера:

$this->sendEvent(1,'PlayerLeaveServer',array($gid,$Player->Name),false);

Первый параметр "1" говорит о том, что об этом событии узнают только пользователи со значением параметра $Status > 1.

'PlayerLeaveServer' - название функции класса TRProcEventsCL, которая будет обрабатывать это событие.

Третий параметр описывает детали события (пока это ID и имя покинувшего сервер).


Попробуйте теперь найти в описании класса TRProcEventsCL (обработчик событий) функции PlayerLeaveServer() и PlayerJoinedToServer(). Допишите их код так, чтобы о входе и выходе пользователя сообщалось в чате.

В случае с этими функциями код добавления сообщения производится всего одной функцией $this->RGame->RChatTool->addMessage()

Report Page