Какой RESTful API вы бы использовали для пошагового игрового сервера?

StackOverflow https://stackoverflow.com/questions/405588

  •  03-07-2019
  •  | 
  •  

Вопрос

Как бы вы смоделировали пошаговый игровой сервер в качестве RESTful API?Например, шахматный сервер, где вы могли бы сыграть партию в шахматы против другого клиента того же API.Вам понадобится какой-то способ запрашивать игру и согласовывать ее с другим клиентом, а также какой-то способ разыгрывать отдельные ходы игры.

Является ли это хорошим кандидатом для REST (RESTful) API?Или это должно быть смоделировано по-другому?

Это было полезно?

Решение

Какие ресурсы вы пытаетесь смоделировать?Кажется, у меня их четыре:Вы, ваш оппонент, конкретная игра (сессия, экземпляр) и состояние игрового поля.Итак, все должно начинаться с чего-то вроде

/game
/game/gameID/gamer/gamerID
/game/gameID/board

у нас есть хорошее вступление / обзор по Информация.

Другие советы

Я думаю о чем-то вроде:

/game/<gameID>/move/<moveID>

что касается основных ресурсов.Однако я не уверен, как справиться с идеей "другой игрок уже перешел?".Я думал о том, чтобы просто заблокировать запрос GET до тех пор, пока ход не будет воспроизведен - т.е.мой клиент передал бы координаты моего переезда в

/game/13/move/1

и тогда бы ПОЛУЧИЛ

/game/13/move/2

Сервер ответит не сразу, но сохранит соединение открытым до тех пор, пока другой игрок не переместится (т.е.ПОМЕСТИТЬ в это место).Это то, что накадзима называет "кометоподобным"?

Чарли, я не совсем уверен, что ты имел в виду под "токеном", за которым сейчас очередь - решает ли это ту же проблему без необходимости опроса или блокировки соединения?

Что касается идентификаторов игроков, имеет ли смысл моделировать их как ресурс в части URL-адреса?Я планировал просто использовать HTTP-аутентификацию пользователя (где user / pass отправляется как часть каждого запроса).Вы все еще могли бы ПОЛУЧИТЬ большинство ресурсов без аутентификации, но если бы вы попытались, скажем,

PUT /game/13/move/2

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

Итак, основная идея REST заключается в том, что вы передаете состояние;вы хотите, чтобы на сервере практически не было "состояния сеанса".Таким образом, вы бы не хотели использовать состояние сеанса и keepalive, что делает Comet.Но подумайте о примере игры "Играть по почте":У вас обоих есть копия доски, и вы обмениваетесь ходами.Почтовое отделение не знает об игре.

Теперь, я признаю, что это растет в моем сознании по мере того, как я думаю об этом - на самом деле, я мог бы написать статью, основанную на этом вопросе, - но вот идея, как некоторые истории:

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

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

Под "токеном" я просто подразумеваю некоторое произвольное представление этого одного бита состояния "Мой ход" / "твой ход".

Кажется, что ресурсы, которые вам нужны, следующие

  • Домашняя страница "найти игру"
  • Страница пользователя, если вы отслеживаете статистику и тому подобное
  • уникальный URI для каждой активной игры.

Спасибо, Чарли.Мне все еще непонятно, как вы получаете уведомление о ходе противника в вашей схеме.Конечно, вопрос о том, кто имеет право на ход, может быть решен просто - либо на основе ресурса board, либо с помощью отдельного ресурса, в котором явно указано, чья очередь делать ход.Но как клиент узнает, что этот ресурс изменился?Должен ли он просто постоянно опрашивать, запоминая предыдущее состояние, пока не заметит, что что-то изменилось?В модели почтового отделения почтовое отделение "отправляет" сообщение клиенту (вашему почтовому ящику), что невозможно в HTTP.

Я полагаю, что это часть более общего вопроса:если есть ресурс REST, который я хочу отслеживать на предмет изменений, каков наилучший способ сделать это?И есть ли что-то, что сервер может сделать, чтобы облегчить это для клиента?

Я думаю, что на самом деле я опубликую это как отдельный вопрос, поскольку я думаю, что это интересно само по себе.

Отредактировано для добавления: Что такое RESTful-способ мониторинга ресурса REST на предмет изменений?

Я не думаю, что REST - хороший выбор для такого приложения.Преобразования и операции, которые вам нужно выполнить (выполнить перемещение, просмотреть историю перемещений, отменить, получить предложение, включить уведомление), не совсем соответствуют концепции ресурсов REST.(Трудности, возможно, становятся более очевидными, если учесть, как может выглядеть RESTful API для более сложных пошаговых игр, таких как Scrabble или Monopoly.)

Я думаю, что любой разумный REST API, вероятно, в конечном итоге стал бы оболочкой вокруг чего-то не RESTful, такого как протокол с отслеживанием состояния, который отправил портативная игровая нотация туда-сюда.

Я думаю, ты мог бы Модель это успокаивающе. Реализующий это будет сложнее, потому что вам либо понадобится комета)-отличное решение, иначе вам пришлось бы опрашивать сервер с относительно коротким интервалом через AJAX.

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

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

Так что, в принципе, я бы смоделировал это именно так.Однако сторона реализации - это то, что я бы счел здесь большей трудностью.

Я не думаю, что это все так уж сложно, Накадзима.Вы бы передали данные, скажем, в формате JSON, для позиции на доске, для ходов и с маркером, указывающим, у кого следующий ход.Это было бы точь-в-точь как играть по почте.

Вы начинаете с того, что заходите в игру и ищете партнера, так что

/game/

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

/game/gameID

показывает вам доску.Вам нужно что-то, чтобы принять решение о том, кто играет белыми, я оставлю это как упражнение.Операция GET дает вам доску, поэтому СООБЩЕНИЕ отправляет ход;если у вас нет нужного хода, вы получите сообщение об ошибке.Вы найдете результат при следующем получении.

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

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

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

Один из разработчиков в планета.джаббер участвует в Шахматный парк, онлайн-шахматное сообщество.Они широко используют Jabber / XMPP;если я не ошибаюсь, это его посты на эту тему.

XMPP - это протокол обмена мгновенными сообщениями, грубо основанный на обмене небольшими XML-сообщениями.Существуют библиотеки для большинства языков, включая Javascript.Хотя я не уверен, что это подойдет к вашей проблеме.

Для такой простой игры, как шахматы, на самом деле речь идет всего лишь об определении медиатипа.

Вот пример того, что, вероятно, является чрезмерно упрощенным медиатипом для моделирования шахматной партии.

Я собираюсь пропустить управление несколькими играми, которые могут быть запущены на одном сервере, и просто смоделировать уже запущенную игру.

Первым шагом обычно является определение индекса для приложения.

index

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

Полезная нагрузка может выглядеть примерно так:

{
    "links": {
        "self": "http://my-chess-game.host/games/123",
        "player": "http://my-chess-game.host/players/1",
        "player": "http://my-chess-game.host/players/2",
        "me": "http://my-chess-game.host/players/1",
         ...
    }
    "board": [
        {
           "x": 0,
           "y": 1,
           "piece": null,
           "rel": "space",
           "href": "http://my-chess-game/.../boards/123/0/1/something-random-to-discourage-uri-construction"
        },
        {
           "x": 1,
           "y": 2,
           "rel": "space",
           "href": "...",
           "piece": {
               "player": "http://my-chess-game/.../players/1",
               "type": "http://my-chess-game/pieces/Bishop",
               "rel": "piece",
               "href": "http://my-chess-game/games/123/pieces/player1/Bishop/1",
               "links": [
                    { "rel": "move": "href": "http://my-chess-game/.../boards/123/..." },
                    ...
                ]
            }
        },

        ...
    ]
}

move

ОТПРАВЛЯЙТЕ полезную нагрузку JSON по ссылкам, помеченным символом rel из move чтобы переместить фигуру.НЕОБХОДИМО указать следующие поля:

  • Расположение:URI пространства для перемещения в

Успешные ответы имеют код состояния 200 и будут содержать объект, который совпадает с index полезная нагрузка с обновленным состоянием игры.

400, если пользователю не разрешено перемещать туда свою фигуру или если сейчас не его очередь.

player

ПОЛУЧИТЕ описание игрока.

В ответе ДОЛЖНЫ быть следующие поля:

  • Имя пользователя:Имя пользователя игрока
  • href:URI, идентифицирующий игрока в этой игре.

piece

Детали встроены в index полезная нагрузка, но МОГУТ существовать сами по себе.Каждый piece ДОЛЖНЫ содержать следующие поля:

  • Тип:URI, определяющий тип элемента.Например,Дж.Слон, Ладья, Король.Получение этого URI МОЖЕТ предоставить информацию о том, как эта фигура работает в игре в шахматы.
  • href:URI, идентифицирующий фактическую фигуру на этой доске.Запросы GET к этому URI МОГУТ предоставлять информацию об этом конкретном фрагменте.

Каждая деталь ДОЛЖНА иметь move Ссылка.


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

Для более сложных игр, таких как Civilization, RTSs, FPSs или MMOGs, а что нет, это может быть не так практично, IMO.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top