Какой RESTful API вы бы использовали для пошагового игрового сервера? - PullRequest
10 голосов
/ 02 января 2009

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

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

Ответы [ 10 ]

4 голосов
/ 02 января 2009

Хорошо, основная идея REST в том, что вы передаете состояние; Вы хотите, чтобы на сервере было мало или не было «состояния сеанса». Таким образом, вы не захотите использовать состояние сеанса и keepalive, что делает Comet. Но подумайте о примере игры по почте: у вас обоих есть копия доски, и вы обмениваетесь ходами. Почтовое отделение не знает об игре.

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

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

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

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

Похоже, что вам нужны ресурсы

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

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

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

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

/game/13/move/1

, а затем получит

/game/13/move/2

Сервер не будет отвечать немедленно, но будет держать соединение открытым до тех пор, пока другой игрок не переместится (т. Е. PUT в это место). Это то, что Накадзима называет «кометой»?

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

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

PUT /game/13/move/2

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

3 голосов
/ 02 января 2009

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

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

у нас есть хорошее введение / обзор по InfoQ .

2 голосов
/ 17 мая 2010

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

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

2 голосов
/ 02 января 2009

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

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

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

Отредактировано, чтобы добавить: Что такое RESTful способ мониторинга ресурса REST на предмет изменений?

1 голос
/ 25 марта 2017

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

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

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

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

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

POST - полезная нагрузка JSON для ссылок, помеченных rel из move для перемещения элемента. ДОЛЖНЫ быть включены следующие поля:

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

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

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

player

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

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

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

piece

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

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

Каждый элемент ДОЛЖЕН иметь move ссылку.


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

Для более сложных игр, таких как Civilization, RTS, FPS или MMOG и тому подобное, это может быть не очень практичным IMO.

1 голос
/ 02 января 2009

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

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

1 голос
/ 02 января 2009

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

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

1 голос
/ 02 января 2009

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

Вы начинаете с того, что идете в игру и ищете партнера, поэтому

/game/

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

/game/gameID

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

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

1 голос
/ 02 января 2009

Я думаю, вы могли бы модель это ОДНОВРЕМЕННО. Реализация будет сложнее, потому что вам либо понадобится решение комета ) - esque, либо вам придется опрашивать сервер с относительно коротким интервалом через AJAX.

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

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

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

...