четверг, февраля 07, 2008

Серверные скрипты (Extensions). SmartFoxServer

Серверные скрипты (я так обозвал термин Extensions, т.к. дословный перевод, типа расширение или серверное расширение, на мой взгляд, менее точны и понятны) - это Java или Actionscript 1.0 (Javascript/ECMA-262) код, для реализации серверной логики.

Применительно к ActionScript (другие варианты я рассматривать не буду), скрипты содержатся в файлах типа .as, размещенных в директории sfsExtensions (для Windows это "C:\Program Files\SmartFoxServerPRO_1.6.0\Server\sfsExtensions\").

Для того, чтобы сервер обрабатывал скрипт, необходимо зарегистрировать его в файле конфигурации config.xml. Выглядит это примерно так:

<Extensions>
<extension name="myExt" className="myExtension.as" type="script" />
</Extensions>

Здесь name - имя скрипта, к которому осуществляет обращение клиент, className - имя файла скрипта.

Кроме того, можно динамически закрепить скрипт за динамически создаваемой комнатой (см. SmartFoxClient.createRoom).

Теперь можно из клиента посылать запрос на выполнение скрипта (см. SmartFoxClient.sendXtMessage):

server.sendXtMessage("myExt", "helloWorld", obj);

Сообщения, получаемые клиентом от серверного скрипта обрабатываются примерно так:

smartfox.onExtensionResponse = function(resObj:Object, type:String) {
var cmd:String = resObj._cmd
if (cmd == "myCommand")
{ // Handle the response here
}
}


Роль серверных скриптов в архитектуре сервера хорошо видна на диаграмме:


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

Основные функции серверных скриптов:

init() - инициализация серверного скрипта. Вызывается автоматически, как только сервер загрузил скрипт.

destroy() - вызывается перед уничтожением серверного скрипта.

handleRequest(cmd, params, user, fromRoom)
cmd - имя запроса. При формировании запроса, для снижения трафика, рекомендуется делать имена короткими.
params - объект с данными, котторые передал клиент серверу.
user - объект пользователя.
fromRoom - идентификатор комнаты, из которой поступил запрос.

handleInternalEvent(eventObject) - реагирует на внутренние события сервера.
Список событий сервера:
userJoin - пользователь вошел в зону/комнату.
userExit - пользователь вышел из комнаты.
userLost - пользователь отключился
newRoom - создана новая комната
roomLost - в зоне была уничтожена комната
loginRequest - пользователь послал запрос на авторизацию
spectatorSwitched - в игровой комнате, наблюдатель переключился в игрока.

Проверим на практике.
Создаем свой серверный скрипт и попробуем посмотреть, как он будет реагировать на события.

Создаем скрипт test.as в вышеописанной директории:
function init() {
trace("Initialization")
}

function destroy() {
trace("Destruction")
}

function handleRequest(cmd, params, user, fromRoom) {
trace("cmd="+cmd+" params="+params+" user="+user+" fromRoom="+fromRoom);
}

function handleInternalEvent(evt) {
trace("eventName="+evt.name);
}


Поместим в Config.xml в нашу созданную ранее зону запись:
<Extensions>
<extension name="tst" className="test.as" type="script" />
</Extensions>

Теперь рестартуем сервер. Или нажимаем "Reload Zones" для перезагрузки зон (?).

Чтобы просмотреть результаты трейсов, можно использовать окно консоли или зайти в SFS Admin Tool в раздел Zone Browser -> Extensions View -> Trace Window.
В серверной консоли можно посмотреть результат трейсов из init и destroy. Просмотреть эти трейсы в реальных условиях в Admin Tool невозможно, так как скрипты, прописанные в конфигурации инициализируются сразу после старта сервера и удаляются непосредственно перед выключением. Однако рядом есть кнопочка "Reload Ext.", где скрипт убивается и опять инициализируется. Здесь то мы и видим наши трейсы.

Что ж, наш скрипт исправно работает, и трейсит все события. Он даже принимает наш запрос:
smartfox.sendXtMessage("tst", "testCommand", {value:1}, "xml");

Интересная особенность - сервер не обрабатывает запрос, если третий параметр (объект с данными запроса) установлен в null. Если некорректно задать другие параметры, это еще объяснимо, но если мне не нужно передавать никакие данные?

Теперь попробуем получить ответ от сервера. Добавим в серверный скрипт в метод handleRequest новый код:
function handleRequest(cmd, params, user, fromRoom) {
trace("cmd="+cmd+" params="+params+" user="+user+" fromRoom="+fromRoom);
var response = {}
response._cmd = "response"
_server.sendResponse(response, -1, null, [user])
}

И в свою очередь, добавим клиенту обработчик события onExtensionResponse:

. . .

this.__sfs.addEventListener(SFSEvent.onExtensionResponse, this.onExtensionResponse);

. . .

public function onExtensionResponse(evt:SFSEvent):void {
trace("Пришел ответ от серверного скрипта: "+evt.params.dataObj);
}

Теперь наш клиент получает на свой запрос ответ от серверного скрипта.

3 комментария:

janvarev комментирует...

С интересом слежу за серией публикаций по SmartFoxServer. Очень обстоятельно написано, приятно, хотя у самого руки пока не доходят попробовать :)

Racer комментирует...

Реал-тайм обучение :). В контексте проекта казуальной он-лайн игры.
Думаю дальше будет еще интереснее.

Константин комментирует...

А у меня все ок кроме трейса пришел ответ от сервера - он не отображается