Ігрова API
Ігрова API - це API для написання своєї версії фронтенду або взаємодії з інформацією про гру зсередини гри.
Можна використовувати для телеграм-ботів, нативних застосунків або браузерних розширень.
Точки входу
Всі дії виконуються через дві точки входу:
game.php - авторизація, отримання завдань, відправка відповідей, розблокування штрафних підказок;
game_au.php - перевірка, чи є нові дії від інших гравців, які слід відобразити. Наприклад, хтось вбив правильну відповідь.
В усі запити слід додавати GET параметр JSON. Тоді результат буде приходити у форматі JSON.
Авторизація
Використовується login.php
POST параметри:
user - логін гравця;
pass - пароль гравця.
Необхідно зберегти cookie та всі їх передавати в подальші запити.
Якщо у відповіді буде рядок із іменем login_error - отже, авторизація не відбулась.
Дані завдання
Використовується game.php
GET параметри:
gid - ID гри
tid - [опціонально] ID рівня
У відповідь надходить JSON в utf-8 із різними даними, зокрема опціональними (якщо тип зазначений із «?» - може бути відсутній).
Імена класів та типи не приходять - вони просто для ілюстрації.
class PublicContext { int version = 1; // Версія протоколу ?string error ; // Помилка ?string login_error; // Помилка при логіні string domain_time_zone; // Часова зона поточного домену ?int game_id; // ID гри ?int task_id; // ID поточного рівня ?int user_id; // ID залогіненого гравця ?string user_name; // Логін гравця ?int team_id; // ID команди гравця, в одиночних іграх може співпадати із ID поточного гравця ?int refresh_time_ms; // Час останнього оновлення сторінки, unix_time в мілісекундах ?int refresh_check_limit_ms; // Проміжок часу в мілісекундах, протягом якого не слід без причини смикати сервер PublicGame game; // Дані про гру /*?PublicGamep[]*/ available_games; // Дані про активні/найближчі ігри домену; доступно, якщо робити запит без gid PublicTask task; // Дані про поточне завданння PublicLastAnswers last_answers; // Моніторинг нещодавно введених відповідей ?PublicAnswerResult answer_result; // Результат останнього введення відповідей ?PublicAnswerForm answer_form; // Дані про форму відповідей /* ?[n => PublicCode] */ codes; // Дані про коди /* ?PublicHint[] */ hints; // Підказки ?int n_bonuses; // Загальна кількість бонусів, якщо вони є у завданні ?int compact_n_bonuses; // Загальна кількість бонусів, якщо автор обрав компактний режим бонусів ?int compact_bonus; // Сумарний отриманий бонус/штраф, якщо автор обрав компактний режим бонусів /* ?string[] */ compact_bonus_answers; // Відомі відповіді на бонуси, якщо автор обрав компактний режим бонусів /* ?string[] */ compact_bonus_hints; // Підказки на введені бонуси, якщо автор обрав компактний режим бонусів /* ? PublicBonus[] */ bonuses; // Бонуси /* ? PublicBonus[] */ global_bonuses; // Наскрізні бонуси /* ?PublicTaskButton[] */ active_tasks; // Доступні наразі завдання /* ?PublicTaskButton[] */ closed_tasks; // Вже закриті завдання - тільки у штурмі } class PublicGame { int id; // ID гри string name; // Назва гри int start_time; // Час старту гри в unix_time int end_time; // Час закінчення гри в unix_time ?int type; // Тип гри: 0 або відсутній - штурмова послідовність, 1 - лінійна послідовність ?bool single; // Одиночна або командна гра } class PublicTask { int n; // Номер завдання string name; // Назва завдання ?string task; // Текст завдання ?string answer_format; // Формат відповіді ?int n_codes; // Скільки всього кодів у завданні ?int need_n_codes; // Скільки потрібно кодів для проходження завдання ?int start_time_ms; // Час початку завдання в unix_time мілісекундах ?int time_left_ms; // Скільки лишилось часу в мілісекундах до автопереходу ?int delay_left_ms; // Затримка в мілісекундах до появи завдання int is_complete; // Завдання вже закінчено } class PublicLastAnswers { /* ?PublicLastAnswer[] */ answers; // Масив з інформацією про відповіді int last_update_ms; // Час останнього оновлення в unix_time мілісекундах } class PublicLastAnswer { int time_ms; // Час у unix_time мілісекундах, коли відправлено відповідь ?string user; // Хто ввів відповідь, в одиночних іграх відсутній string answers; // Введені відповіді через кому string type; // Одне зі значень: right, wrong, repeat - правильно, але вже було, nonsubmit - не прийнято через блокування ?string bonus; // Отриманий бонус або штраф за відповіді } class PublicAnswerResult { int task_id; // ID рівня, для якого пораховано: /* ?strings[] */ right_answers = []; // правильні відповіді /* ?strings[] */ wrong_answers = []; // неправильні /* ?strings[] */ repeat_answers = []; // правильні, але повторні /* ?strings[] */ nonsubmit_answers = []; // не прийняті через блокування ?string bonus = ''; // Бонус, отриманий за відповіді ?string penalty = ''; // Штраф, отриманий за відповіді } class PublicAnswerForm { public bool show_finish_task = false; // Чи потрібно показувати кнопку, яка закриває завдання. Якщо потрібно, то завдання можна закрити, відправивши код !finish! bool hide_answer_form = false; // Відповіді більше не прийматимуться, можна прибрати поле вводу ?int block_time_left_ms; // Скільки часу лишилось до зняття обмеження на введення. Час у мілісекундах. Якщо penalty не 0, отже, відповіді можна вводити, але зі штрафом за неправильні. ?int limit_n_answers; // Обмеження на кількість неправильних відповідей. Константа - як задана автором. ?int time_limit; // Час у секундах. За який проміжок часу враховується обмеження на кількість відповідей limit_n_answers. Якщо 0, то limit_n_answers - обмеження на весь рівень. ?int penalty; // Штраф за кожну неправильну відповідь понад дозволеного. ?int n_answers_left; // Скільки відповідей команда може вбити до того, як почне діяти обмеження. Міняється після кожного введення відповідей. Якщо 0 - обмеження активне. } class PublicCode { ?string name; // Назва коду ?string answer; // Відповідь на код ?string user_name; // Хто вбив перший ?int user_id; // Хто вбив перший ?int answered_ms; // Коли вбив перший } class PublicBonus { ?int n; // Номер бонусу ?int bonus; // Отримуваний бонус або штраф, якщо значення відʼємне. В секундах або балах. ?string answer; // Відповідь на бонус ?string description; // Опис бонусу (загадка) ?string hint; // Підказка, якщо бонус вирішено ?int time_to_open_ms; // Час у мілісекундах до відкриття бонусу ?int time_to_close_ms;// Час у мілісекундах до закриття бонусу ?bool is_closed; // Час на введення бонусу вичерпаний - більше для введення відповідей він не доступний ?string user_name; // Хто вбив перший ?int user_id; // Хто вбив перший ?int answered_ms; // Коли вбив перший } class PublicHint { int n; // Номер підказки ?int time_to_open_ms; // Час у мілісекундах до відкриття підказки ?int id; // ID штрафної підказки - необхідно для її використання ?string description; // Опис підказки ?string hint; // Текст підказки ?int penalty; // Штраф за штрафну підказку ?int any_code; // Якщо є, означає, що підказка може відкрити будь-який код /*int[]*/ codes; // Перелік кодів, які може відкрити підказка }
Варіанти помилок
В error можуть прийти такі помилки:
- NO_GAME_ID - не вказаний gid
- NO_GAME - неправильний gid
- NO_USER - необхідно залогінитись
- NO_TEAM - командна гра, а гравець не в команді
- TEAM_NO_ANONYMOUS - анонімний гравець не може грати в ігри з обмеженням складу команди
- TEAM_TOO_BIG - у команді більше гравців, ніж обмеження складу
- TEAM_GAME_NOT_REQUESTED - команда не подала заявку
- TEAM_GAME_NOT_ACCECPTED - команда не прийнята у гру
- GAME_NOT_STARTED - гра ще не почалась
- GAME_FINISHED - гра закінчилась
- SEQUENCE_ERROR - помилка в призначеній автором послідовності рівнів
Відправка відповідей
Використовується game.php
GET параметри:
gid - ID гри;
tid - ID рівня, в який треба ввести відповідь (якщо не зазначати, то є ризик вбити відповідь з минулого рівня у рівень з обмеженням на введення);
a - відповіді, які треба ввести, через кому.
Взяття штрафних підказок
Використовується game.php
GET параметри:
gid - ID гри;
hint_id - ID підказки, яку треба розблокувати;
hint_code - [опціонально] номер коду, який треба відкрити штрафною підказкою.
Оновлення сторінки
Використовуються game_au.php, game.php
Якщо гра командна, то у відповіді на game.php приходитиме refresh_check_limit_ms.
Це час у мілісекундах, після якого можна перевіряти, чи є зміни в движку від дій співкомандників.
Якщо смикати сервер частіше, то є ризик отримати бан по IP на певний час.
refresh_check_limit_ms - не константа і може мінятись у залежності від навантаження на сервер.
Якщо будь-який із таймерів у грі закінчується раніше, ніж refresh_check_limit_ms, то слід оновити сторінку за допомогою game.php. При цьому refresh_check_limit_ms можна проігнорувати.
Оптимально
За допомогою game_au.php перевіряємо, чи треба оновлювати сторінку.
GET параметри:
gid - ID гри;
tid - ID завдання;
time - час, отриманий у refresh_time з відповіді game.php.
У відповідь прийде JSON:
class PublicAutoUpdateResult { ?string error; // Помилка ?bool refresh; // Треба оновити сторінку, хтось вбив правильний код або взяв штрафну підказку ?bool reload; // Хтось пройшов рівень ?bool refersh_monitoring; // Є нові неправильні відповіді в моніторингу. Можна їх завантажити, якщо потрібно. ?int next_check_ms; // Скільки чекати (в мілісекундах) до наступної перевірки - вираховується сервером в залежності від навантаження. }
Якщо в JSON є поля refresh, reload або refersh_monitoring, то за допомогою game.php оновлюємо сторінку.
Не оптимально
За допомогою game.php регулярно завантажуємо нову версію.
В цьому випадку період, з яким ви смикаєте сервер, беріть як refresh_check_limit_ms, помножений на 3.