Бэк-офис для игр.



1. Концепция и общее описание


Значительное количество компьютерных online игр требуют сохранения результатов игр, ранжирования игроков, обращения игровой валюты. Игроки получают, выигрывают, проигрывают и расходуют игровые ресурсы. Организуются разного вида соревнования. Игроки общаются между собой, используя внутри игровой чат. Периодически огранизуются соревнования, отличающиеся друг от друга структурой и параметрами. Как правило, разработчики таких игр создают собственные WEB службы для обеспечения этого функционала.

Бэк-офис для игр предоставляет универсальный сервис для произвольной игры, предъявляющей подобные требования, полностью абстрагируясь от содержательной части игры.

WEB интерфейс системы обеспечивает разработчику и администратору игр регистрацию, настройку и управление игрой.

WEB API системы предоставляет игровым программам полный доступ к сущностям игры, фиксацию результатов игровых событий, обеспечивает общение между игроками и администратором игры в режиме online. Все запросы к WEB API начинаются с префикса https://[url сервера]/Api/Data/[method]


− Понятия, используемые в системе.

Server.  Сервер системы. WEB сервер, обеспечивающий выполнение заявленные сервисы системы.

Client.  Клиент. Игровая программа, использующая ресурсы системы.

SuperAdmin.  Администратор системы. Уникальная роль в системе. На данный момент это автор системы. Его функции:

GameAdmin.  Администратор (разработчик) игр. Уникальная роль в конкретной игре. Может быть владельцем нескольких игр. Его функции:

Gamer.  Игрок

Обязанностей не имеет кроме как играть в созданную разработчиком игр игру. Имеет логин, е-мейл, игровую валюту, рейтинг и определенные разработчиком игр игровые ресурсы. Имея единственную (в системе) учетную запись, может играть в разные игры разных авторов.

Game.  Игра

Ограничивает общепринятое понятие игры следующим определением: «Игра есть совокупность параметров, ресурсов, игроков и их активов полученных или выигранных игроками в процессе соревнований». Собственные обязательные свойства:
  • Название игры
  • Название игровой валюты
  • стартовая сумма в единицах этой валюты при регистрации игрока в игре (стартовый бонус)

GameParam.  Параметр игры

Некий произвольный параметр, определяющий течение игры. Целое число. Разработчик имеет полную свободу назначения параметров. Параметры игры и их значения «по умолчанию» наследуются соревнованиями.
Собственные обязательные (при создании) свойства:
  • Название
  • Значение по умолчанию, целое
Системой определен один фиксированный параметр, обязательный для всех соревнований. Это «Количество фреймов в матче». Удалять его или создавать параметр с таким же названием нельзя, допускается только изменять его значение в конкретных соревнованиях. Этот параметр автоматически создается при создании новой игры. Кроме того, разработчик может добавить единственный на игру параметр с признаком "Рейтинг". Этот параметр используется в соревнованиях как награда от администратора игры победителям, увеличивая их игровой рейтинг.

GameResourceType.  Тип игрового ресурса

Опеределяет перечень игровых ресурсов. Может принимать только два значения: "Число" и "Список". Ресурс со списочным типом полезен для группировки ресурсов с числовым типом по категориям. Присутствие списочного типа необязательно.

GameResource.  Игровой ресурс

Произвольное значение, получаемое, выигрываемое, покупаемое у администратора игры или у других игроков, продаваемое другим игрокам. Цена ресурса номинируется администратором игры в единицах игровой валюты, или на «бирже» игроком – продавцом. Целое число.

SystemCurrency.  Системная валюта

Дублоны ( D). Курс системной валюты устанавливается администратором системы для каждого администратора игр отдельно. Получается администратором игр при регистрациии. Покупается у администратора системы. Расходуется при внутри игровых операциях в качестве комиссионных.

GameCurrency.  Игровая валюта (¤)

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

GamerRating.  Рейтинг игрока

Особый вид ресурса игрока в игре. Не покупается, не продается, только получается при регистрации в игре и зарабатывается/теряется в процессе соревнований. Вычисление изменений рейтинга выполняется игровой программой по результатам сыгранных игроком игр. Стартовый рейтинг равен 100.

Competition.  Соревнование

Непосредственный акт игры нескольких (более одного) игроков с параметрами настраиваемыми администратором игры. Параметры соревнования есть параметры игры с измененными значениями. Соревнования определены 3 видов: Чемпионат, Турнир, Первенство. Кроме соревнований разработчик может реализовать произвольный акт игры нескольких игроков с установкой значений параметров, определенных в игре (Свободный матч) одним из игроков. Система фиксирует состояние игрока относительно соревнования.

Frame.  Фрейм

Минимальный игровой акт. Фрейм является неделимой единицей структуры любого соревнования.

Match.  Матч

Совокупность фреймов. Матч может состоять из одного или более фреймов. Иначе говоря, online встреча фиксированного состава игроков.

Round.  Раунд

Применим только к турниру. Совокупность матчей, проводимых «на одном уровне»

Tournament.  Турнир

Пирамидальная последовательность раундов. В каждом из матчей может быть только один победитель, выходящий в следующий раунд. Победитель матча определяется по вычисленным игровой программой результатам фреймов матча. Параметры могут изменяться от раунда к раунду. Собственные свойства:

  • Название
  • Количество партнеров в матче (NP). От 2 до 10.
  • Количество раундов (NR). От 2 до 10. Важно: NPNR — общее количество игроков турнира не рекомендуется делать большим, чем 256.
  • Дата окончания подписки. Регистрация игроков для участия в турнире заканчивается не позднее истечения этой даты.
  • Дата начала. Турнир начинается не ранее этой даты.
  • Вступительный взнос. Целое. Сумма в единицах игровой валюты, уплачиваемая игроком при подписке.
  • Вступительный рейтинг. Игрок с меньшим рейтингом не может участвовать в турнире.
  • Стимул от Автора. Параметр в целых единицах игровой валюты. По умолчанию – 0.
  • Количество фреймов в матче. Устанавливаемое значение наследуется параметрами раундов. Количество фреймов в матче не должно быть меньше чем количество партнеров в матче

Championship.  Чемпионат

Соревнование, в котором каждый игрок играет в матче каждый с каждым. В матче участвуют только два игрока. Места по окончанию чемпионата определяются игровой програмой. Допустима ничья в каждом из матчей. Собственные свойства:

  • Название
  • Количество игроков. Не рекомендуется делать большим, чем 256.
  • Дата окончания подписки. Регистрация игроков для участия в чемпионате заканчивается не позднее истечения этой даты.
  • Дата начала. Чемпионат начинается не ранее этой даты.
  • Вступительный взнос. Целое. Сумма в единицах игровой валюты, уплачиваемая игроком при подписке.
  • Вступительный рейтинг. Игрок с меньшим рейтингом не может участвовать в турнире.
  • Стимул от Автора. Параметр в целых единицах игровой валюты. По умолчанию – 0.
  • Количество фреймов в матче.

Anteriority.  Первенство.

Игроки, участвующие в первенстве не состязаются друг с другом непосредственно. Выполняя некоторые, определяемые игрой, задания, игроки показывают результаты, по которым определяется победитель. Собственные свойства те же, что и у чемпионата.

FreeMatch.  Свободный матч.

Не регламентируемые администратором игры матчи между игроками. Значения параметров, определенных в игре, устанавливаются самими игроками.

Chat.  Чат.

Система предоставляет сервис мгновенных сообщений как между администратором игры и игроками, так и между игроками. Возможно отправлять сообщения группам игроков. Группы в чате напрямую соответствуют играм. Администратор игр состоит во всех группах, соответствующих принадлежащим ему играм. Игрок состоит во всех группах, соответствующих играм, в которых он зарегистрирован.


− Активы системы

− Валюты. Система курсов.

Система имеет два уровня валют: Валюта системы и валюты игр. Валюта системы находится под управлением администратора системы и является активом администраторов игр. Валюта системы с позиции администратора системы имеет неограниченный объем. Иначе говоря, администратор системы имеет бесконечное количество единиц валюты системы Администраторы игр получают стартовый капитал в валюте системы во время регистрации в системе. Размер стартового капитала может меняться системным администратором. Валюта системы расходуется администраторами игр при разблокировании игры (на время или навсегда) и при регистрации нового игрока (последнее только на рабочем сайте). Суммы этих комиссий зафиксированы в валюте системы D. Кроме того, на рабочем сайте системой взимается налог на операции обмена внутри игровой валюты (в %% от объема, но не менее 1 D). Администраторы игр имеют возможности приобретать валюту системы за рубли РФ.

Администраторы игр управляют своими внутри игровыми валютами. Называют валюту, назначают стартовую сумму валюты (при регистрации игры), которую получают игроки при регистрации в игре, Игровая валюта с позиции администратора игр имеет неограниченный объем. Иначе говоря, администратор игр имеет бесконечное количество единиц валюты каждой из своих игр. изменяют курс валюты игры, изменяют комиссионные ставки за операции покупки или конвертации валюты.

Система курсов. Представляет собой дерево, вершиной которого является валюта системы. Узлы первого уровня - адинистраторы игр. Несмотря на то, что администратор игры не имеет собственной валюты, существует курс администратора игры. Узлы второго - валюты игр. При регистрации администратора игр его курс по отношению к валюте системы, устанавливается в 1. Администратор системы имеет возможность изменять этот курс. При регистрации игры администратором игр, валюте этой игры присваивается курс по отношению к курсу администратора игры, равный 1. Администраторы игр могут изменять курсы валют своих игр. Функционирование системы курсов проще пояснить на примерах.

Пример 1. Игрок игры G1 c валютой V1 и курсом K1 хочет обменять сумму S1 на сумму S2 в валюте V2 с курсом K2 игры G2 того же администратора A1. То есть, продать валюту V1 и купить валюту V2. При этом сумма продажи S1 будет уменьшена на величину комиссии С. Комиссия вычисляется по установленной администратором игр процентной ставке, но не более чем фиксированное значение, также устанавливаемое администратором игр. В этом случае игрок получит S2 = (S1-С)*K1/K2 единиц валюты V2.

Пример 2. То же, что и в примере 1, но V2 это курс K2 игры G2 другого администратора A2. При этом курс администратора A1 - KA1, а курс администратора A2 - KA2. В этом случае игрок получит S2 = (S1-С)*K1*KA1/(K2*KA2) единиц валюты V2.

− Ресурсы. Биржа.

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


− Чат.

Все участники системы: администратор системы, администраторы игр и игроки имеют возможность общаться друг с другом с помощью встроенной системы мгновенных сообщений. При этом администратор системы видит и общается только с администраторами игр, администраторы игр с администратором системы, игроками, зарегистрированными в его играх и с группами игроков. Группа в чате однозначно соответствует (и копирует название) игре. Игроки могут общаться с администраторами игр, группами игроков, в которых они зарегистрированы, а также персонально с каждым из игроков, зарегистрированным в той же игре, что и он.


− Игрок: Операции в браузере.

Игрок выполняет большинство своих действий непосредственно в игровой программе. Кроме собственно игровых актов, игрок может покупать игровые активы и продавать их на бирже. WEBAPI предоставляет такую возможность, описанную ниже. Исключением является операция оплаты покупки игровой валюты, которая может выполняться только в браузере. Это требование Яндекс кошелька. Браузерная покупка игроком активов показана здесь.

Биржевые операции состоят из выставления на продажу или покупки "лотов". Каждый лот включает один или несколько игровых ресурсов, принадлежащих игроку, выставляющего лот. Ресурс, выставленный на продажу в составе лота, исключается из активов игрока. Например, игрок имел 10 "жизней", а выставил 5. У него осталось 5 жизней для использования в игре. Игрок, выставляющий лот на продажу может назначать цену по каждому ресурсу, включенному в лот, а также изменять количество и цену ресурса. Соответственно изменению количества ресурса изменяется и количество этого ресурса, доступного для использования. Эти действия возможны до тех пор, пока лот не будет куплен целиком другим игроком. Покупка оплачивается игровой валютой. В приведенном примере покупатель -- qwerty2, продавец -- qwerty0.


− Сценарий разработчика/администратора игр.

После ознакомления с настоящим руководством, разработчику (а в дальнейшем под этим логином и администратор) игры, использующей сервисы, представляемые системой, рекомендуется тщательно продумать набор необходимых параметров игр и ресурсов в них используемых. При этом необходимо иметь ввиду, что использование (либо не использование) тех или иных параметров непосредственно в соревновании, никак не регламентируется системой, а только самой игровой програмой. Если нужный параметр или ресурс отсутствует в списке зарегистрированных в системе, он не может быть учтен системой. В то же время возможны ситуации, когда тот или иной параметр фрейма не может быть задан явно, например расклад карт в карточной игре. Система предоставляет механизм для хранения такой произвольной информации в виде JSON строки.

Неизбежно, в процессе разработки игровой программы у разработчика возникнет необходимость тестировать её, с возможностью оперативного изменения состава и значений параметров и ресурсов игры, удаления/добавления соревнований, их результатов и многое другое. Для этого система имеет тестовый сайт https://gamebackoffice.ru , на котором и выполняется тестирование программ.

Только на тестовом сайте разработчик имеет возможность зарегистрироваться сам и зарегистрировать свою игру. На рабочем сайте https://gamebackoffice.ru эти действия невозможны. Во избежание использования тестового сайта в качестве рабочего, учетная запись разработчика игр на нем блокируется через 180 дней и, соответственно, использование игр становится невозможным. Этот период отсчитывается с момента регистрации разработчика/администратора игр. Разблокировать учетную запись разработчика/администратора игр может только администратор системы. После окончания отладки игровой программы, Администратор системы по согласованию с разработчиком игры экспортирует логин администратора и/или его программы на рабочий сайт. Через 60 дней после экспорта отлаженной игры на рабочий сайт она блокируется (на рабочем сайте). Этот бесплатный период предоставляется администратору игр для привлечения игроков. По истечении этого срока администратор игры может разблокировать игру самостоятельно на срок 60, 365, 730 дней или навсегда. Все платежи администраторов игр администратору системы осуществляются в системной валюте (D).

При регистрации разработчика/администратора игр в системе он указывает кроме логина и пароля также и e-mail, для подтверждения которого, ему отправляется электронное письмо с ссылкой на страницу подтверждения регистрации. Настоятельно рекомендуется установить признак "Использовать Юmoney кошелек", и ввести номер Яндекс кошелька в соответствующее поле. Яндекс кошелек используется на рабочем сайте системы для платежей администраторов игр администратору системы, а также при покупке игровой валюты игроками. Отказ от использования Яндекс кошелька существенно затруднит эти расчеты. При выборе признака "Использовать Яндекс кошелек" будет предложено настроить HTTP уведомления на сайте Юmoney. Это необходимо для автоматизации учета платежей игроков.
   На тестовом сайте платежи через Яндекс-деньги эмулируются, реально они выполняются только на рабочем сайте.

Разработчик игр может зарегистрировать неограниченное количество игр. Регистрация игры выполняется в соответствующей форме.

Все поля — обязательны.

После регистрации игры слева появляется дерево ссылок настроек игры.

Настройка параметров игры. Пример:

Разработчик имеет полную свободу в наименовании параметров игры и установки их значений по умолчанию, за исключением параметра «Количество фреймов в матче», который автоматически создается при регистрации игры с значением по умолчанию, равным 3. Параметр игры может быть видимым игроку в игровой программе (в примере параметр "Сложность") и изменяемый игроком в свободных матчах или анализируемый игроком при выборе участия или не участия в соревнованиях, назначенных администратором игры, а также невидимым (в примере параметр "Коэффициент 1"), используемым в некоторых внутри игровых вычислениях. Названия параметров должны быть уникальными в масштабе игры. Удаление параметров возможно только для параметров, созданных разработчиком игры только на тестовом сайте.

Настройка типов ресурсов игры. Пример:

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

Настройка значений числовых ресурсов игры. Пример:

Настройка значений списочных ресурсов игры. Пример:

Комиссионные ставки. Операции в игре или в целом в системе сопровождаются комиссионными сборами и налогами. Пример: Системные ставки устанавиливаются администратором системы и могут отличаться от игры к игре. Внутри игровые ставки могут изменяться администратором игр.


− Настройка соревнований

Общим для всех видов соревнований является необходимость для администратора игр создавать и настраивать соревнования.

− Турнир

Создание турнира. Исключая очевидный атрибут "Название", остальные атрибуты требуют некоторых пояснений.

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

Сразу после создания турнира становится доступным турнирная таблица. Игроки могут подписываться на турнир. Когда подпишутся все, либо после даты окончания подписки появится возможность "посеять" игроков по матчам первого раунда.Турнир с "посеянными" игроками выглядит следущим образом: Распределение игроков по матчам не регламентируется системой и администратор игр имеет полную свободу выбора того, как распределить игроков. Очевидно, что не следует соединять в одном и том же матче игроков с высоким рейтингом. Администратору игр не нужно дожидаться, когда на турнир подпишется всё допустимое количество игроков. При этом игрок(ки) (уже во время турнира), не встретившие в текущем раунде партнеров, автоматически перемещаются вверх по турнирной таблице до тех пор, пока не окажутся в том месте, где уже есть или может появиться партнер(партнеры). Закрытие подписки завершает настройку и сопровождение турнира.

− Чемпионат

Создание и настройка чемпионата мало отличается от создания и настройки турнира. Отсутствует параметр "Количество раундов" (неприменимо) и настройка параметров матчей относится ко всему чемпионату в целом.

Также, в отличие от турнира отсутствует необходимость для администратора игр выполнять распределение игроков по матчам. Подписывающийся игрок сразу попадает в одно из свободных мест таблицы чемпионата.

− Первенство

Создание и настройка первенства не предполагает процедуры подписывания игроков на участие в первенстве, их распеределения по местам и др. Поэтому вместо даты окончания подписки указывается просто дата окончания. Игрок может выполнить игровое задание начиная с даты начала первенства и заканчивая датой окончания. Разработчик игры может использовать дату окончания для запрета вступать в это соревнование после нее, но может и игнорировать ее. Настройки параметров те же, что и у чемпионата.

− Регистрация игрока, вход в игру и аутентификация

Для использования игровой программы игрок должен (при первом запуске) зарегистрироваться в системе. Если игрок впервые регистрируется в любой (в том числе от разных авторов) игре системы, создается его учетная запись в системе и он регистрируется в игре. В дальнейшем он просто регистрируется в игре. Каждая регистрация игрока в игре сопровождается взиманием комиссии с администратора игр в валюте системы (только на рабочем сервере). Взимание комиссии отражается в браузере адмиисратора игр.
Регистрация: POST метод. В WebSocket не реализован.

method = register
request body:
responce:

Игрок, зарегистрированный в игре, должен выполнить вход в игру. Для этого вызывается
POST метод: В WebSocket не реализован.
method = token,
request body:
responce:

При успешном входе в систему ответ имеет другую структуру:
responce:

Подробнее о значениях возвращаемых параметрах. Токены доступа: access_token, refresh_token и wsacess_token. После успешного входа игрока по логину и паролю, доступ к методам системы контролируется jwt токенами. Первый токен, access_token предназначен собственно для контроля доступа к GET и POST методам, а второй, refresh_token для обновления access_token. Токены access_token и refresh_token должны быть обновлены возможно быстрее сразу после выполненного входа, по крайней мере не позже чем через refreshtimeout секунд. На данный момент первый (после логина) refreshtimeout = 60 сек.
По истечении этого времени токены становятся не актуальны. Обновление access_token-а выполняется POST методом method = RefreshToken. В заголовки запроса должен быть добавлен заголовок "Authorization", формата:
"Bearer [refresh_token]" (пробел обязателен!). При успешном обновлении токенов access_token и refresh_token:
responce:

Здесь уже refreshtimeout = 86 400 000 сек. (сутки).
Параметры userid и connectid могут быть полезны для игровой программы. Например для фильтрации данных. Различие между этими параметрами состоит в том, что userid есть идентификатор игрока в целом в системе, в то время как connectid – идентификатор подключения игрока к системе в конкретной игре.

Клиент может запоминать и безопасно хранить access_token с помощью которого выполнять последующие входы в системы без логина и пароля. Для этого используется POST метод method = TryLogin,
request body:

После успешного входа в систему получения и обмена необходимых токенов игровая программа должна подключиться к WebSocket. и отправить WebSocket команду GameConnect(). Первое подключение к WebSocket предваряется HTTP POST запросом по адресу [Url системы]/SR/negotiate?negotiateVersion=1 с пустым телом и заголовоком Authorization, формата: "Bearer [wsacess_token]" (пробел обязателен!). Сразу за этим необходимо отправить WebSocket команду GameConnect() для сопоставления системой ID WebSocket соединения с внутрисистемным ID подключения клиента (в дальнейшем упоминается как ssfconnectid. Ssfconnectid Фактически уникальный ключ сетевого соединения клиента, его ID регистрации (UserId) и ID игры). Необходимость существования дополнительного ID подключения клиента одновременно с ID WebSocket соединения обусловлена тем, что при кратковременных потерях связи и восстановлении её, ID WebSocket соединения меняется, а системе необходимо знать, что это тот же клиент, а не новый.

Здесь необходимо более детальное описание механизма восстановления связи при кратковременных потерях связи клиента с системой.
Имеет место сочетание следующих обстоятельств:

  1. Система не допускает множественные подключения одного и того же игрока к одной и той же игре.
  2. При обрыве соединения клиента и сервера, клиент узнает об этом примерно на 20 секунд позднее, чем сервер.
  3. Необходимо сохранить состояние клиента в игре при кратковременных потерях связи.
  4. Необходимо обеспечить переподключение игрока к игре при более длительных обрывах связи или некорректных отключениях.

При "штатном" отключении клиента по WebSocket сигналу GameDisconnect, система удаляет информацию о подключении клиента из памяти сервера, и игрок может вновь подключиться к игре даже с другого устройства. В тоже время, если игрок все еще подключен к игре необходимо, запретить второе и следующие подключения. Это обеспечивается за счет того, что, хотя повторное подключение и предоставляет те же логин и пароль, оно отличается другим значением строки deviceid. Если же отключение произошло по причине обрыва связи или ошибки игровой программы, информация о подключении клиента продолжает храниться на сервере и, во первых, отклонит переподключение того же клиента, а во вторых может ввести в заблуждение других участников игры. Такое поведение исключается за счет паузы в 60 - 80 секунд, в течение которых сервер хранит состояние клиента (и игрок, запускающий игровую программу с того же устройства, а значит с тем же deviceid) свободно входит в систему в сохраненное состояние. С другой стороны, после истечения этой паузы игрок уже может подключиться к игре и с другого устройства, но уже без сохраненного на сервере состояния. Переподключение клиента после восстановления подключения к Интернет должно выполняться с помощью следующей последовательности операций:

  • Запросить у сервера информацию о том, сохранено ли его состояние на сервере. Для этого выполняется GET запрос CheckConnect. Получение ответа 200 (ОК) означает, что состояние хранится на сервере и повторный релогин не требуется
  • Ответ 401 (Unauthorized) означает, что сервер очистил данные о подключении клиента. В этом случае клиент должен выполнить повторный вход в систему с помощью метода TryLogin и access_token, и, в случае неудачи, вход с использованием логина и пароля.
Предложенный ниже программный компонент GBOClientStd использует пакет Microsoft.AspNetCore.SignalR.Client версии 3.1.9 и обеспечивает необходимый протокол переподключений.

Начиная с момента входа в игру, игрок должен выбрать тип соревнования, в котором он намерен играть и информировать о своем выборе систему. Это необходимо для корректной маршрутизации сообщений клиентам системы о событиях в самой системе и действиях игроков. Выбор типа соревнования выполняется методом EntersToCompType. Отказ от выбора — LeaveCompType.

После выбора типа соревнования, игрок выбирает собственно соревнование, в котором он намерен принять участие. Список доступных для выбора соревнований а также методы для его получения зависят от типа соревнования и описаны ниже. Для изменения выбора соревнования используется метод EnterToCompetition. Состояние подключения игрока: UserInCompState устанавливается в READY. Отказ от выбора — LeaveCompetition, Состояние игрока —> UNDEFINED. Здесь "выбор" соревнования означает только намерение игрока, но не начало собственно участия в соревновании. Возможность начала матча может зависеть от наличия подключившихся к игре других игроков, выбора ими того же соревнования.

При выполнении всех (определяемых игровой программой) условий, соревнование начинается со старта первого фрейма.

− Жизненный цикл соревнований.

− Фрейм

Именно во фрейме игровой программой реализуется внириигровой процесс, будь то ходы в шахматах, удары в биллиарде, решение головоломки. Игровая программа с подачи игрока вызывает метод GamerStartsFrame, который передает Id матча игрока, и его CustomParams. Сервер изменяет и запоминает состояние игрока в матче: UserInCompState, (переводит его в состояние INCOMP). Это необходимо для корректного обслуживания запросов и маршрутизации сообщений игроков во время фрейма. На протяжении фрейма возможен обмен произвольными данными между игроками с использованием метода InvokeNeigborMethod. JSON строка CustomParams запоминается сервером для каждого фрейма и по каждому из игроков. Основное предназначение этой строки — некоторые внутри фреймовые параметры, например, карточный расклад. Собственно фрейм стартует либо когда все участники стартовали методом GamerStartsFrame, либо по окончании ожидания опоздавших. Это определяется игровой программой.
Принципиально фрейм может окончиться в следующих случаях:

  1. первый из участников выполнил игровое задание
  2. все участники выполнили игровое задание
  3. некоторые участники выполнили игровое задание и истекло время ожидания отключившихся/опоздавших игроков

Подсчет очков (голов, секунд, других произвольных характеристик игры), а также определение факта окончания фрейма, целиком и полностью — ответственность игровой программы. Исходными данными для этого являются как собственные действия игрока, так и информация, полученная от его партнеров по матчу. Рузультаты фрейма отправляются на сервер только одним из участников. Методы для записи результатов и последующего получения общих резельтатов специфичны для каждого типа соревнований и описываются ниже.

− Жизненный цикл турнира

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

  1. В турнире еще остались "места" для того, чтобы игрок мог подписаться на участие в турнире, либо игрок уже подписался. Если срок окончания подписки не истек.
  2. Турнир начался и игрок присутствует в одном из не завершенных матчей.
Игрок выбирает турнир и подписывается на участие в нем с помощью метода SubscribeToTournir. После того, как игроки подпишутся на участие в турнире и срок окончания подписки истечет, администратор игры выполняет "посев" игроков и (обязательно) закрывает подписку. После наступления даты начала турнира игроки могут приступать к игре.

Особенностью турниров, как типа соревнования, является то, что окончание каждого матча выявляет единственного игрока — победителя, который переходит в следующий раунд. И так вплоть до победы в финале, который выявляет победителя турнира. Из этого следует запрет на понятие "ничья", возможность досрочной победы в матче, случай, при котором требуется дополнительый фрейм, отсутствие необходимости учитывать внутри фреймовые результаты (например, количество забитых голов) при определении победителя турнира.

Окончание фрейма.
При наступлении события окончания фрейма один из участников (игровая программа) записывает результаты фрейма и, одновременно получает данные по всем сыгранным фреймам матча с помощью метода WriteFrameReadMatchResults. Игровая программа использует полученные данные для определения факта окончания матча и победителя в матче. Определившая факт окончания матча игровая программа (непременно одна из участвующих в матче) вызывает метод сервера EndOfRound. Сервер запоминает победителя в матча, переводит его в следующий раунд и оповещает об этом все игровые программы, игроки которых выбрали данный турнир и участвуют в нем. Если же матч не закончен, игровая программа оповещает других участников матча, используя метод свободных сообщений InvokeNeigborMethod.

Фиксированный состав участников матча турнира (определенный "сеянием" турнира) требует синхронизации времени старта матча. О конкретном времени старта игроки могут договориться между собой с помощью чата, но установить его должен только один из них. Для этого предусмотрен метод SetTournRoundStart. Также это позволяет обработать ситуацию "опоздавшего" или "передумавшего" игрока и начать матч без него. Отсутствие такого механизма может привести к блокировке турнира целиком. При установке времени старта матча, кроме оповещения через WEB Socket интерфейс, можно указать необходимость оповещения участников матча через e-mail (опционально, включает e-mail напоминание за 6 часов до назначенного времени старта).

Вполне возможна ситуация, когда количество подписавшихся на участие в турнире игроков окажется меньше общего количества игроков, в результате чего в самом младшем раунде в одном или нескольких матчах окажется по одному игроку. В таком случае исключается необходимость синхронизации времени старта и собственно разыгрывания фреймов. Здесь достаточно игровой программе вызвать метод EndOfRound, после чего игрок перемещается вверх по турнирной пирамиде до раунда, в котором уже есть или могут появится другие участники турнира. Вызывать метод GamerStartsFrame при этом не обязательно.

− Жизненный цикл чемпионата

Список чемпионатов, доступных для того чтобы подписаться на участие в них, или начать/продолжить участие в них доступен с использованием методов Champs. В список попадают чемпионаты, дата окончания которых больше чем текущая дата и сыграны не все матчи. Игрок выбирает чемпионат и подписывается на участие в нем с помощью метода SubscribeToChamp. Поскольку в чемпионате каждый игрок встречается с каждым, процедура "сеяния" игроков не имеет смысла, подписавшиеся игроки могут начинать матч сразу после наступления времени начала чемпионата. В матче чемпионата всегда ровно два игрока.

В чемпионате отпадает необходимость фиксации времени старта конкретного матча. Игрок может начать игру с любым игроком чемпионата не занятом игрой с другими игроками. Это не запрещает игрокам предварительно договориться о времени их встречи. По окончанию фрейма игровые программы участников матча записывает результаты фрейма методом WriteFrameResults. Это может выполнить либо каждая из обеих программ (записать результаты своего игрока), либо одна из них (записать результаты обоих игроков). Здесь же игровая программ определяет победителя во фрейме и (строго одна из двух) увеличивает количество выигранных победителем фреймов на 1 методом WriteChampFrameScore. Одновременно с этим определяется факт окончания матча на основе данных по сыгранным фреймам, получаемым методом GetMatchResultsDetail. Если матч окончен, одна из двух программ вычисляет распределение рейтинга между участниками матча, записывает результаты вычисления рейтинга и счет по очкам в матче (например: победа 3:0, ничья 2:2 - дело вкуса разработчика) и сообщает системе об окончании матча методом WriteChampPlaceScore. Матч окончен. В ответ система отправляет участникам матча сообщение о факте окончания чемпионата. Если при этом окончился и чемпионат, одна из двух программ вычисляет и записывает итоговые результаты чемпионата в целом, а также распределяет места, призы и рейтинговый бонус (если есть) среди участников чемпионата, записывая результаты чемпионата методом WriteChampPrefs.

Чемпионат, как вид соревнования, допускает, что к моменту окончания не все матчи будут сыграны и, соответсвенно, не будут выявлены чемпионы и распределены призы и рейтинговый бонус. Для этого предусмотрена возможность для администратора игр принудительно распределить призы и рейтинговый бонус среди участников чемпионата. Для этого должны выполняться два условия: Дата окончания чемпионата закончилась и не все матчи чемпионата сыграны. Распределение призов и рейтингового бонуса выполняется из таблицы чемпионата.

− Жизненный цикл первенства

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

Клиент начинает фрейм первенства отправляя серверу команду StartAnterFrame. Сервер транслирует эту команду игрокам, принимающим участие в данном первенстве.

По завершении фрейма клиент записывает свои результаты сыгранного фрейма WriteFrameResult.

В то время как турниры предоставляют однозначный формальный признак победы игрока в матче, первенства не имеют этого призака. В связи с этим возникает проблема распределения мест победителей первенства и распределения призов и рейтинга. Возможны два способа решения этой проблемы. Можно выполнять такое распределение средствами самой игровой программы в момент когда последний из игроков первенства закончит свой матч. Этот способ имеет существенный недостаток: Количество участников первенства может изменяться в течении первенства, и, следовательно точно определить "последнего" невозможно. Отбросим этот способ. Можно выполнять такое распределение каждый раз, когда игрок заканчивает матч первенства. То есть результаты будут переопределяться в течении первенства. Этот способ представляется допустимым, несмотря на то, что рейтинг и сумма игровой валюты уже сыгравших свои матчи в первенстве будут изменяться без их участия (1). И последний способ -- администратор игры выполнит такое распределение принудительно, после окончания первенства (2). Выбор между (1) и (2) способом разработчик игры может жестко запрограммировать либо организовать специальный параметр.

По окончании матча клиент получает текущие результаты первенства по всем матчам с помощью метода GetAnterResultsDetail, исследует содержимое поля Results всех полученных FrameResult, определяет текущее распределение победителей и записывает результаты выполнив метод WriteAnterPrefs. Для реализации способа (2) необходимо поля Prize и Rate в каждом из AnterResult метода WriteAnterPrefs установить в 0.


− 2. API.

Система предоставляет API для взаимодействие с играми, созданными и зарегистрированными в системе. API состоит из двух технологий: REST API и WebSocket. В REST API используются GET и POST http запросы, WebSocket -- для передачи событий от сервера к клиентским программам, а также для обработки и маршрутизации команд между клиентскими программами одной и той-же игры. Кроме того, все методы (кроме получения и обновления токенов доступа) REST API имеют двойников в API WebSocket.
При описании API методов системы методы REST API и API WebSocket будут описываться вместе. Для упрощения интеграции игровой программы с системой, автором системы создан и рекомендуется для использования и свободно распространяемый программный компонент GBOClientStd на платформе .NET Standart 2.0. Разработчик игр может свободно использовать и локально редактировать этот компонент.

Этот компонент предоставляет класс Connector, обеспечивающий связь с системой и классы моделей данных. Модели данных описываются далее по мере необходимости. Класс Connector реализует паттерн soliton, получить инстанс класса: Connector.Instance(gameID, gboUrl, Action<string> updateAccessToken) или (при повторном получении инстанса: public static Connector Instance()). Здесь string gameID Id игры в системе, string gboUrl URL системы updateAccessToken   метод, вызываемый Connector-ом после обновления access_token и передающий его игровой программе для запоминания . Формат URL REST API запросов: https://www.[домен системы]/Api/Data/[method], MIME-тип application/json, кодировка - utf8.

− Методы API

Префикс для всех URL методов REST API: [Url системы]/API/Data. POST методы могут вызывать WebSocket методы у клиентов.

WebSocket методы.

Системой определены 2 вида WebSocket методов:
  1. Target: "имя метода сервера" (ServerMethodName), Arguments: (список аргументов (от 1 до 4-х)), string requestid. Здесь строка requestid должна быть уникальной (UUID). Предназначение requestid состоит в необходимости организовать CallBack вызовы методов сервера, при котором клиент не слушает непрерывно соответствующий ответ сервера, но ожидает ответ только на конкретный вызов. Сервер отвечает вызовом метода ServerMethodName{requestid} у клиента. Ответ может содержать данные. В GBOClientStd таким WebSocket методам соответсыуют методы с постфиксом CallBack. Пример: метод GetActiveDetails.
  2. То же, что и предыдущий, но requestid отсутствует. Сервер не отвечает непосредственно на вызов, но может отправить клиенту(клиентам) одну или несколько команд. Клиент постоянно слушает команды сервера, инициированные таким методом. Пример: чат. Один вызывает, все слушают. В GBOClientStd таким WebSocket методам соответсвуют методы с постфиксом WebSock. Пример: метод SendMessageWebSock.

− Общие методы


− Методы чата


− Методы соревнований

− Модели данных

  • enum ERROR
  • class SsfActionResult
  • enum UserInCompState
  • enum COMPTYPE
  • class GamerActive
  • class ChangeRatingRequest
  • class Order
  • class FreeMesssage
  • class Offer
  • class Good
  • class ActiveType
  • class ExchangeOrder
  • class ExchangeEntity
  • class Interlocutor
  • class ChatMess
  • class CompApplicant
  • class AnterApplicant. Наследует CompApplicant
  • class CompParameter
  • class Competition
  • class Tournament. Наследует Competition
  • class Champ. Наследует Competition
  • class Anterior. Наследует Competition
  • class TournRound
  • class CompPlace
  • class RoundPlace наследует CompPlace
  • class NextRoundPlace
  • class FrameResult
  • class ChampPref
  • class AnterResult. Наследует ChampPref
  • class RoundStart
  • class ChampPlaceScore
  • class GamerPoints