Написание плагина для оболочки клиента TimeZero
Требования:
I. Требования к плагину:
В плагине обязательно должно быть тем или иным образом указано имя (ник) лица, его написавшего.
Интерфейс плагина должен быть выполнен так, чтобы с ним было удобно работать, элементы управления не должны "наползать" друг на друга.
Если плагин предназначен для каких-либо расчётов - обязательно обрабатывайте возможные ошибки и информируйте пользователя о них.
Информирующие диалоговые окна обязательно должны содержать имя плагина. Его следует указывать в заголовке или в теле сообщения.
Плагин обязательно должен представлять из себя один файл, если это необходимо - все изображения/звуки/видео, требуемые для работы плагина, должны быть в виде ресурсов, присоединённых к нему. Ограничения на создание файлов в процессе работы нет (распаковка ресурсов, сохранение настроек и пр.).
Плагин не должен изменять каких-либо данных в файлах настроек/локализации клиента. Разрешается только чтение.
Плагин не должен требовать установку или наличие какого-либо дополнительного софта для своей работоспособности.
II. Плагин нужно отправить на электронный адрес full_bugs@timezero.ru, где указать:
В теме письма "Плагин" и название плагина (пример: "Плагин - Киборг").
Ник и/или реальное имя человека его написавшего.
Полное описание плагина, все возможности и особенности (это необходимо для модерации).
III. В приложении(attachment) к письму:
Должен быть ZIP-архив с исходниками плагина с названием: "Название плагина (source).zip".
Должен быть ZIP-архив с откомпилированным плагином.
Отдельно (вне архивов) должен быть прикреплён текстовый файл с кратким описанием плагина и его возможностями (для публикации на сайте).
IV. Исходник плагина должен быть хорошо откомментирован и оформлен. В письме должно указываться используете ли вы какие-либо дополнительные компоненты и, если они требуют регистрации в системе - подробно описать это. Обязательно укажите версию среды разработки.
Необходимые технические аспекты:
Плагин для оболочки игрового клиента TimeZero является библиотекой (dll) с расширением tzp. Чтобы изменить директиву расширения вашего плагина — укажите {$E tzp} после строки с названием вашей библиотеки. (library MyPlugInName;)
Инициализация плагина в оболочке клиента:
— В момент загрузки плагина оболочка клиента вызывает функцию PluginVerifying, в ней плагин должен вернуть своё имя и версию, формата Major.Minor.Release.Build (без точек). В имени плагина допускаются русские символы.
function PluginVerifying: TPlugInfo; begin // Возвращаем оболочке игрового клиента имя плагина Result.PluginName := 'MyPlugInName'; // Возвращаем оболочке игрового клиента версию плагина Result.PluginVersion := 1000; end;
Данная функция должна быть добавлена в раздел exports где перечисляются функции, доступные для вызова из оболочки клиента.
Запись информации о плагине выглядит следующим образом:
TPlugInfo = record
// Имя плагина. (Допускаются русские символы)
PluginName : WideString;
// Версия плагина. Major.Minor.Release.Build (без точек)
PluginVersion : Word;
end;
— Если функция успешно выполнилась оболочка клиента вызывает процедуру PluginInitialization и передаёт ей в параметрах ссылку на класс, через который плагин будет общаться с GUI и игровым клиентом.
procedure PluginInitialization(PlugClass:TPlugInInterface); begin // Свяжем указатель с глобальной переменной плагина PlugInterface := PlugClass; end;
PluginInitialization также необходимо добавить в раздел exports.
Переменная PlugInterface — класс "интерфейса" общения оболочки игрового клиента с плагином (см. ниже).
Завершение работы плагина:
— В момент закрытия оболочки клиента или удаления плагина вызывается процедура PluginFinalization (без параметров). Если вам необходимо совершить какие-то действия в момент закрытия плагина (сохранение настроек; освобождение объектов) вы можете сделать их в теле этой процедуры. В таком случае, не забудьте добавить её в раздел exports.
Листинг описания класса "интерфейса" общения оболочки игрового клиента с плагином:
TPlugInInterface = class
private
FShortCut : TShortCut;
FIcon : TMemoryStream;
FCaption : WideString;
FOnCall : TNotifyEvent;
FOnGameEvent : TNotifyEvent;
public
// Горячая клавиша для быстрого обращения к плагину
property ShortCut: TShortCut read FShortCut write FShortCut;
// Иконка вашего плагина в формате PNG
property Icon: TMemoryStream read Ficon write FIcon;
// Заголовок плагина для ячейки меню и горячих клавиш оболочки клиента
property Caption: WideString read FCaption write FCaption;
// Событие обращения пользователя к плагину
property OnCall: TNotifyEvent read FOnCall write FOnCall;
// Оповещение плагина о возникновении игрового события
property OnGameEvent: TNotifyEvent read FOnGameEvent write FOnGameEvent;
// Процедура изменения настроек плагина (Icon, ShortCut, Caption, Events) в оболочке клиента
procedure SetPlugInParams; virtual; stdcall; abstract;
// Функция передачи данных в игру
function SetGameData(Request, Value: OleVariant; Player: WideString): Boolean; virtual;
stdcall; abstract;
// Функция получения данных из игры
function GetGameData(Value: WideString; Player: WideString): OleVariant; virtual; stdcall;
abstract;
// Функция выполнения команды в оболочке игрового клиента
function TZExecute(Command: WideString; Value: WideString; Player: WideString): OleVariant;
virtual; stdcall; abstract;
// Функция получения списка игроков загруженных в игровые закладки. gValue — служебный параметр
function GetPlayersList(const gValue: Byte = 0): TStringList; virtual; stdcall; abstract;
end;
Параметры и события плагина:
Изменять параметры плагина вы можете в любой момент работы оболочки клиента.Пример изменения параметров:
procedure PluginInitialization(PlugClass:TPlugInInterface);
begin
// Свяжем указатель с глобальной переменной плагина
PlugInterface := PlugClass;
// Изменяем параметры плагина
PlugInterface.ShortCut := Menus.TextToShortCut('Ctrl+P');
PlugInterface.Caption := 'Мой постядерный плагин';
// Сообщим оболочке клиента об изменениях
PlugInterface.SetPlugInParams;
end;
Чтобы ваш плагин мог отвечать на обращения пользователя к нему — необходимо создать обработчик событий OnCall типа TNotifyEvent, для вашего PlugInterface. Тогда при нажатии указанного в ShortCut сочетания горячих клавиш или нажатии кнопки в панели инструментов/меню выбора плагина оболочки клиента — будет срабатывать ваше событие.
Если плагин не указывает свой обработчик события OnCall — оболочка клиента не будет его отображать в меню выбора плагинов.
Событие OnGameEvent предназначено для перехвата некоторых игровых событий плагинами.
По умолчанию плагины могут видеть следующие события:
— Персонаж вошёл в игру
— Персонаж вышел из игры
Создав обработчик события OnGameEvent вам будет необходимо распознавать его тип и значение. Для этого вам потребуется добавить небольшой класс, отвечающий за его описание.
— Класс, описание игрового события:
TGameEvent = class
private
FEventName : WideString;
FEventValue : WideString;
FEventCode : Integer;
public
// Имя персонажа, в игровой закладке которого произошло событие
property EventName: WideString read FEventName;
// Значение события
property EventValue: WideString read FEventValue;
// Код события
property EventCode: Integer read FEventCode;
end;
Коды событий, доступных плагинам по умолчанию:
— Вход в игру (EventCode: 0)
— Выход из игры (EventCode: 1)
Пример обработчика события OnGameEvent:
procedure TMyPlugInForm.OnGameEvent(Sender: TObject);
begin
case TGameEvent(Sender).EventCode of
0 : Dialogs.MessageDlg('Персонаж "'+TGameEvent(Sender).EventValue+'" вошёл в игру.',
mtInformation,[mbOK],0);
1 : Dialogs.MessageDlg('Персонаж "'+TGameEvent(Sender).EventValue+'" вышел из игры.',
mtInformation,[mbOK],0);
end;
end;
Как применить PNG иконку к плагину:
Необходимые требования к иконке:- Высота/Ширина: 24 на 24
- Глубина цвета: 32 BPP
- Максимальный размер файла 5 Kb.
Для этого:
- Создайте текстовый документ блокнота.
- Напишите в нём следующий текст: MYICON PNG "MyPlugInIcon.png"
- Где MyPlugInIcon.png — имя вашей PNG картинки.
- Сохраните файл, рядом с вашей PNG картинкой, под именем pngicon.rc
- Создайте текстовый документ блокнота.
- Напишите в нём следующий текст: Brcc32 pngicon.rc
- Сохраните файл, рядом с вашей PNG картинкой, под именем pngicon.bat
- Запустите файл pngicon.bat (Двойным кликом мыши), в итоге вы получите файл pngicon.RES, который появится в том же каталоге.
- Скопируйте файл pngicon.RES в корневой каталог вашего плагина.
Для этого добавьте директиву {$R pngicon.res} после главного раздела uses.
Пример загрузки иконки плагина из ресурсов:
procedure PluginInitialization(PlugClass:TPlugInInterface);
var
ResourceStream : Classes.TResourceStream;
begin
// Свяжем указатель с глобальной переменной плагина
PlugInterface := PlugClass;
// Изменяем параметры плагина
PlugInterface.ShortCut := Menus.TextToShortCut('Ctrl+P');
PlugInterface.Caption := 'Мой постядерный плагин';
// Загружаем PNG иконку плагина
if Windows.FindResource(HInstance, PChar('MYICON'), 'PNG')<>0 then
begin
PlugInterface.Icon := TMemoryStream.Create;
ResourceStream := TResourceStream.Create(HInstance, 'MYICON', 'PNG');
PlugInterface.Icon.LoadFromStream(ResourceStream);
ResourceStream.Free;
end;
// Сообщим оболочке клиента об изменениях
PlugInterface.SetPlugInParams;
end;
Общение плагина с игровой flash:
Общаться с игровой flash ваш плагин может следующими способами:— Через функции SetGameData/GetGameData
— Используя функцию TZExecute указать оболочке клиента, особое игровое событие, за которым он (плагин) хочет следить. К примеру, плагин сообщит, что желает следить за перемещением персонажа по локациям, а ответ он будет получать через событие OnGameEvent.
Для второго способа — вам необходимо связаться с разработчиком оболочки игрового клиента, чтобы обсудить нюансы и получить разрешение на его использование. Почта для связи: full_bugs@timezero.ru, в теме письма необходимо указать "Плагин" и название плагина (пример: "Плагин — Киборг").
Описание функции передачи данных в игру:
function SetGameData(Request, Value: OleVariant; Player: WideString): Boolean;
• Request — имя запроса к игровой flash.
• Value — значение запроса.
• Player — имя персонажа, в игровой закладке которого будет выполнен этот запрос (см. ниже).
Функция возвращает успех передачи данных типа Boolean.
Пример использования:
if not PlugInterface.SetGameData('_root.watchUserInfo.login','Keeper Ranson','') then
Dialogs.MessageDlg('Не удалось открыть информацию о персонаже Keeper Ranson',mtWarning,[mbOK],0);
В примере используется запрос _root.watchUserInfo.login, который отвечает за отображение информации о персонаже в игровой flash. В качестве ника персонажа указано Keeper Ranson, а параметр Player пустой - это означает, что плагин не указывает оболочке клиента определённую игровую закладку, в которой следует выполнить эту функцию, она будет выполнена в текущей закладке, в случае если её тип игровой и в ней авторизирован игрок.
Описание функции получения данных из игры:
function GetGameData(Value: WideString; Player: WideString): OleVariant;
• Value — данные, которые плагин хочет получить от игровой flash.
• Player — имя персонажа, в игровой закладке которого будет выполнен этот запрос (см. ниже).
Функция возвращает ответ от игровой flash, в случае если запрос указан корректно. Возвращаемый тип — OleVariant.
Пример использования:
var
GameLogin : OleVariant;
begin
GameLogin := PlugInterface.GetGameData('_root.USER.login','');
if (TVarData(GameLogin).VType and VarTypeMask)<>varEmpty then
Dialogs.MessageDlg('Это игровая закладка с персонажем "'+String(GameLogin)+'".',
mtInformation,[mbOK],0)
else Dialogs.MessageDlg('Это не игровая закладка, либо в ней не авторизирован персонаж.',
mtWarning,[mbOK],0);
В примере используется запрос _root.USER.login, который отвечает за получение данных о нике персонажа, параметр Player снова пустой - плагин совершает запрос в текущей закладке.
Указав в запросе _root.USER.login вместо login любой из ниже перечисленных параметров вы можете получить более детальную информацию о персонаже:
login - Имя персонажа HP - Текущее количество здоровья maxHP - Максимальное количество здоровья str - Сила dex - Ловкость int - Интуиция pow - Выносливость acc - Меткость intel - Интеллект exp - Опыт (обратите внимание, что это значение текущего опыта персонажа) nextlevel - Необходимое количество опыта для достижения следующего уровня level - Уровень pro - Профессия. Идентификатор имеет следующие значения: 1=Профессия: корсар 2=Профессия: сталкер 3=Профессия: старатель 4=Профессия: инженер 5=Профессия: наемник 6=Профессия: торговец 7=Полицейский: патрульный 8=Полицейский: штурмовик 9=Полицейский: специалист 10=Профессия: журналист 11=Профессия: чиновник 12=Профессия: псионик 13=Каторжник 14=Профессия: пси-кинетик 15=Профессия: пси-медиум 16=Профессия: пси-лидер 17=Профессия: полиморф 30=Профессия: дилер propwr - Уровень профессии (значение от 0 до 1) man - Пол персонажа virus - Наличие заражения вирусом X psy - Текущий уровень пси-энергии maxPsy - Максимальный уровень пси-энергии Местонахождение: X - Первая координата местонахождения персонажа Y - Вторая координата местонахождения персонажа
(Координаты даются в формате 0..360, а не -180..180) ROOM - Номер комнаты в шахте Навыки: sk0 - Холодное оружие sk1 - Легкое оружие sk2 - Среднее оружие sk3 - Тяжелое оружие sk4 - Метательное sk5 - Энергетическое sk6 - Медицина sk7 - Минирование sk8 - Электроника sk9 - Пси-контроль sk10 - Пси-атака sk11 - Пси-медицина sk12 - Пси-искажение
Взаимодействие плагина с оболочкой игрового клиента:
Если вы хотите сообщить оболочке клиента для какого персонажа выполняется тот или иной запрос — вам следует указать ей параметр Player. В нём указывается никнейм игрока авторизированого в игровой закладки оболочки клиента.Получить никнейм вы можете организовав обработчик события OnGameEvent, который позволит вам перехватывать моменты входа и выхода персонажей в игру, или воспользоваться следующей функцией:
function GetPlayersList(const gValue: Byte = 0): TStringList;
Параметр gValue — является служебным, он вам не пригодится.
Пример использования функции:
var
PlayersList : TStringList;
PlayersStr : String;
i : integer;
begin
PlayersList := PlugInterface.GetPlayersList;
if (Assigned(PlayersList)) and (PlayersList.Count<>0) then
begin
for i:=0 to PlayersList.Count-1 do PlayersStr := PlayersStr+PWideChar(PlayersList.Strings[i])+#13#10;
Dialogs.MessageDlg('Текущий список персонажей: '+#13#10+PlayersStr,mtInformation,[mbOK],0);
end else Dialogs.MessageDlg('Игровых закладок с авторизированным персонажем - нет.',mtWarning,[mbOK],0);
SysUtils.FreeAndNil(PlayersList);
end;
Описание функции выполнения команды в оболочке игрового клиента:
function TZExecute(Command: WideString; Value: WideString; Player: WideString): OleVariant;
• Command — имя команды.
• Value — значение команды.
• Player — имя персонажа, в игровой закладке которого будет выполнена эта команда.
Функция возвращает результат обработки команды, в случае если запрос указан корректно. Возвращаемый тип — OleVariant, определяется в зависимости от типа запроса.
Пример использования:
if not PlugInterface.TZExecute('BrowserNavigate','//www.timezero.ru','') then
Dialogs.MessageDlg('Не удалось открыть страницу //www.timezero.ru',mtWarning,[mbOK],0);
Список команд функции TZExecute, доступных плагинам по умолчанию:
• GetShellHandle - Получение главного дескриптора оболочки клиента (Integer).
• BrowserNavigate - Открытие ссылки во встроенном браузере оболочки клиента. Value — URL.
• CheckIgnoring - Проверка наличия персонажа Value в списке игнорируемых у игрока Player.
• ClearGameChat - Очистка игрового чата у персонажа Player.
• SendToChat - Отправка сообщения в игровой чат персонажа Player.
Если у вас есть какие-нибудь идеи или вам необходимо получать дополнительные данные от оболочки игрового клиента — обратитесь к разработчику по почте: full_bugs@timezero.ru, в теме письма необходимо указать "Плагин" и название плагина (пример: "Плагин — Киборг").
Организация общения между идентичными плагинами по сети:
Оболочка игрового клиента позволяет плагинам организовать транспортный протокол для передачи данных между двумя, или более, модулями. PlugTalk, похож на UDP протокол. Не требует предварительной установки соединения с желаемым пользователем, быстро и эффективно доставляет данные, прост в использовании.Следует учитывать, что аналогично UDP/IP протокол PlugTalk не гарантирует доставку пакетов — следовательно разработчику плагина необходимо предусмотреть возможность ожидания ответа и реализовать схему типа «запрос-ответ».
PlugTalk работает в строковом режиме, максимальная длина данных PlugTalk-сообщения равна ~150 символов. Организовать общение между модулями можно только в том случае, если они идентичны друг другу, т.е. их MD5 сумма исполняемой библиотеки не отличается.
Доступ к функционалу происходит через метод TZExecute класса "интерфейса" общения оболочки игрового клиента с плагином.
Команды для управления протоколом передачи данных плагином:
• StartPlugTalk - Активировать протокол в закладке персонажа Player. Возвращает успех операции (Boolean).
• StopPlugTalk - Остановить работу протокола в закладке персонажа Player. Возвращает успех операции (Boolean).
• SendPlugData - Отправить данные Value от игрового персонажа персонажа Player (см. ниже). Возвращает успех операции (Boolean).
Команда SendPlugData позволяет плагину отправить, указанному в параметре Value, персонажу данные в случае если модуль активировал протокол PlugTalk.
Для успешной доставки PlugTalk-сообщения, параметр Value обязательно должен содержать имя персонажа, для которого предназначены эти данные. Рекомендуется указывать ник персонажа с первого символа в формате SysUtils.Format('[%s]',[ToPlayer]); где переменная ToPlayer является строковым идентификатором пользователя (ник), к которому уйдут последующие данные в этой строке.
Пример использования команды:
if not PlugInterface.TZExecute('SendPlugData',SysUtils.Format('[%s]%s',['Keeper Ranson','hello']),'') then
Dialogs.MessageDlg('Не удалось отправить данные ”hello” персонажу Keeper Ranson',mtWarning,[mbOK],0);Для получения входящих данных — модулю необходимо реализовать обработчик события OnGameEvent, активировать PlugTalk протокол и ожидать возникновения игрового события с EventCode равным 9.
Пример обработчика события OnGameEvent для получения входящих данных от протокола PlugTalk:
procedure TMyPlugInForm.OnGameEvent(Sender: TObject);
var
Data,Author: String;
p : Integer;
begin
case TGameEvent(Sender).EventCode of
0 : Dialogs.MessageDlg('Персонаж "'+TGameEvent(Sender).EventValue+'" вошёл в игру.',mtInformation,[mbOK],0);
1 : Dialogs.MessageDlg('Персонаж "'+TGameEvent(Sender).EventValue+'" вышел из игры.',mtInformation,[mbOK],0);
9 : begin
Data := TGameEvent(Sender).EventValue;
// Парсим автора входящих данных
p := Pos('[',Data); if p=0 then exit; Delete(Data,1,p);
p := Pos(']',Data); if p=0 then exit;
Author := Copy(Data,1,p-1); Delete(Data,1,p);
Dialogs.MessageDlg('От персонажа "'+Author+'" пришли данные: '+Data,mtInformation,[mbOK],0);
end;
end;
end;Исходя из примера, видно, что в EventValue, по аналогии с отправкой данных, первыми символами содержится ник персонажа (автор входящих данных).
Рекомендуется не совершать автоматическую отправку данных, а реализовывать её с согласия пользователя, т.е. игрок должен самолично «нажать кнопку», чтобы данные «ушли». Также, следует упомянуть, что если плагин будет слишком часто отправлять данные по протоколу PlugTalk — то к игроку, от чьего имени они уходили, будут применены соответствующие санкции.
Если у вас есть какие-нибудь вопросы, требующие более детальной конкретизации — обратитесь к разработчику по почте: full_bugs@timezero.ru, в теме письма необходимо указать "Плагин" и название плагина (пример: "Плагин — Киборг").
Тестирование работоспособности плагина:
Плагины, которые не прошли проверку администрацией игры — помечаются статусом "не поддерживается". Для возможности тестирования вашего плагина вам необходимо запускать оболочку игрового клиента с параметрами:"-debugPlugIn -PlugInName.tzp".
За плагины прошедшие проверку и размещенные в разделе управления модулями оболочки игрового клиента, выплачивается вознаграждение, в зависимости от качества и объема работы.



СКАЧАТЬ
