ما هي واجهة RESTful API التي ستستخدمها لخادم ألعاب قائم على الأدوار؟

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

  •  03-07-2019
  •  | 
  •  

سؤال

كيف يمكنك تصميم خادم ألعاب قائم على الأدوار باعتباره RESTful API؟على سبيل المثال، خادم الشطرنج، حيث يمكنك لعب لعبة الشطرنج ضد عميل آخر بنفس واجهة برمجة التطبيقات.ستحتاج إلى طريقة ما لطلب لعبة والتفاوض بشأنها مع العميل الآخر، وطريقة ما للعب الحركات الفردية للعبة.

هل هذا مرشح جيد لواجهة برمجة تطبيقات REST (RESTful)؟أم يجب أن يتم تصميم هذا بطريقة مختلفة؟

هل كانت مفيدة؟

المحلول

ما هي الموارد التي تحاول تصميمها؟ يبدو أن لدي أربعة: أنت ، خصمك ، اللعبة الخاصة (الجلسة ، مثيل) ودولة مجلس اللعبة. لذلك سيبدأ بشيء مثل

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

لدينا مقدمة جيدة/نظرة عامة على infoq.

نصائح أخرى

أفكر في شيء مثل:

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

بقدر ما يتعلق الأمر بالموارد الأساسية. لست متأكدًا من كيفية التعامل مع "هل تحرك اللاعب الآخر بعد؟" فكرة ، رغم ذلك. لقد فكرت ببساطة في الحصول على كتلة Get request حتى يتم تشغيل الخطوة-لقد وضع موكلي إحداثيات انتقالي إلى

/game/13/move/1

ثم سيحصل

/game/13/move/2

لن يستجيب الخادم على الفور ، ولكن يحافظ على اتصال الاتصال حتى يتحرك اللاعب الآخر (أي وضعه على هذا الموقع). هل هذا ما يشير إليه ناكاجيما باسم "المذنب"؟

تشارلي ، لست متأكدًا تمامًا مما قصدته بـ "الرمز المميز" الذي يدور حوله-هل هذا يحل نفس المشكلة دون الحاجة إلى الاقتراع أو اتصال الحظر؟

بالنسبة لمعرفات اللاعب ، هل من المنطقي تصميم أولئك كمورد في جزء من عنوان URL؟ كنت أخطط لاستخدام مصادقة مستخدم HTTP (حيث يتم إرسال المستخدم/المرور كجزء من كل طلب). لا يزال بإمكانك الحصول على معظم الموارد دون مصادقة ، ولكن إذا حاولت ، على سبيل المثال ،

PUT /game/13/move/2

سوف يمنحك إذنًا تم رفض الإذن إذا لم يكن لديك بيانات الاعتماد الصحيحة لتلك اللعبة.

حسنًا ، الفكرة الأساسية للراحة هي أنك تنقل الحالة ؛ تريد أن يكون لديك "حالة جلسة" ضئيلة أو معدومة على الخادم. لذلك لا ترغب في استخدام حالة الجلسة و keepalive ، وهو ما يفعله المذنب. لكن فكر في مثال لعبة اللعب على حدة: لديك نسخة من اللوحة ، وأنت تبادل التحركات. مكتب البريد لا يعرف عن اللعبة.

الآن ، سأعترف أن هذا ينمو في ذهني وأنا أفكر في الأمر - في الواقع ، قد أكتب مقالًا يستند إلى هذا السؤال - ولكن هذه هي الفكرة ، كبعض القصص:

  1. تريد أن تلعب لعبة الشطرنج على الخط ، لذلك تذهب إلى URI معروفة للحصول على واحدة. تعود إلى صفحة تُظهر من ، إذا كان أي شخص ، ينتظر بدء لعبة.
  2. يمكنك اختيار أحد الأشخاص الذين ينتظرون اللعب ، وانقر على الرابط المناسب. يمكنك الحصول على عرض جديد (Ajax Magic هنا إذا كنت تريد) مع إعداد اللوحة. أحدكم هو أبيض ، يتحرك أبيض أولاً.
  3. كل من لديه الحق في التحرك يدخل خطوة ، ويرتكب (مثل خلع يدك عن القطعة في اللعبة.) تحديثات اللوحة والحق في الانتقال إلى اللاعب الآخر.

لا تحتاج إلى أي شيء من حيث حالة الخادم --- على الرغم من أنك قد ترغب في تمديد هذا من خلال تتبع التحركات وما إلى ذلك ، على سبيل المثال ، ومسألة من لديه الحق في التحرك يمكن حسابها بالكامل من صفحة اللوحة: إذا كان لديك الحق ، فلديك نموذج لإدخال خطوة ؛ عند إرسال النموذج إلى الوراء ، تُرجع الاستجابة صفحة لك بدون فتحة لإدخال خطوة.

من خلال "The Token" أعني بعض التمثيل التعسفي لتلك الحالة واحدة من الحالة "خطوتي"/"تحركتك".

يبدو كما لو أن الموارد التي تحتاجها

  • صفحة رئيسية "العثور على لعبة"
  • صفحة مستخدم إذا كنت تتتبع الإحصائيات وما شابه
  • URI فريدة من نوعها لكل لعبة نشطة.

شكرا ، تشارلي. ما زلت غير واضح كيف يتم إخطارك عن تحرك الخصم في مخططك. بالطبع ، يمكن حساب مسألة من لديه الحق في التحرك ببساطة-إما من مورد اللوحة ، أو باستخدام مورد منفصل ينص صراحةً على دوره في التحرك. ولكن كيف يعرف العميل أن هذا المورد قد تغير؟ هل يتعين عليهم ببساطة الاستطلاع باستمرار ، وتذكر الحالة السابقة ، حتى يلاحظ أن شيئًا ما قد تغير؟ في نموذج مكتب البريد ، يقوم مكتب البريد "بدفع" رسالة إلى العميل (صندوق البريد الخاص بك) ، وهو أمر غير ممكن في HTTP.

أفترض أن هذا جزء من سؤال أكثر عمومية: إذا كان هناك مورد REST أريد مراقبته للتغييرات أو التعديلات ، فما هي أفضل طريقة للقيام بذلك؟ وهل هناك شيء يمكن أن يفعله الخادم لتسهيل ذلك للعميل؟

أعتقد أنني سأقوم بالفعل بنشر هذا كمسألة منفصلة لأنني أعتقد أنه مثير للاهتمام في حد ذاته.

تم تحريره لإضافة: ما هي الطريقة المريحة لمراقبة مورد REST للتغييرات؟

لا أعتقد أن الراحة خيار جيد لمثل هذا التطبيق. التحولات والعمليات التي تحتاج إلى القيام بها (جعل التحرك ، عرض السجل التحرك ، التراجع ، الحصول على الاقتراح ، الإخطار بدوره) لا تعين بدقة لمفهوم الموارد. (ربما تكون الصعوبات أكثر وضوحًا إذا نظر المرء إلى كيفية ظهور واجهة برمجة تطبيقات مريحة للألعاب الأكثر تعقيدًا مثل Scrabble أو Monopoly.)

أعتقد أن أي واجهة برمجة تطبيقات REST المعقولة قد ينتهي بها الأمر إلى أن تكون غلافًا حول شيء غير مشدود ، مثل بروتوكول الدولة الذي أرسل تدوين اللعبة المحمولة ذهابا وايابا.

أعتقد أنك تستطيع نموذج انها راحة. تنفيذ سيكون الأمر أكثر صعوبة ، لأنك ستحتاج إما مذنب) -esque الحل أو يجب أن تقوم بإجراء استقصاء الخادم على فاصل زمني قصير نسبيًا عبر Ajax.

فيما يتعلق بكيفية فضح واجهة مريحة ، أقول إنك تحتاج إلى لوحة تشغيل مع إحداثيات ، وقطع يمكن أن تشغل تلك الإحداثيات ، والإجراءات التي تغير تلك الإحداثيات.

عندما يقوم اللاعب بالتحرك ، سيتم إنشاء إجراء جديد. بعد التحقق من التحقق من صحة للتأكد من أنه مسموح به ، يمكنك تحديث حالة اللعبة ، ثم تقديم أي استجابة مطلوبة لتحديث واجهة المستخدم.

لذلك هذا في الأساس كيف سأضعه في وضع تصميمه. جانب التنفيذ هو ما أعتبره صعوبة أكبر هنا.

لا أعتقد أنه كل ما يتذمر ، ناكاجيما. يمكنك تمرير البيانات ، على سبيل المثال في JSON ، في موقف اللوحة ، للحركات ، ومع رمز مميز لمن لديه الخطوة التالية. سيكون تمامًا مثل اللعب عبر البريد.

تبدأ بالذهاب إلى اللعبة والبحث عن شريك ، لذلك

/game/

يمنحك قائمة من الناس ينتظرون. عندما تأتي ، إذا لم يكن هناك أحد ينتظر ، فستحصل على معرف لعبة ؛ وإلا فإنك تختار شخصًا ينتظر والحصول على معرف اللعبة الذي لديهم.

/game/gameID

يظهر لك اللوحة. تحتاج إلى شيء لإنشاء قرار من يلعب باللون الأبيض ، سأترك ذلك كتمرين. تمنحك عملية الحصول على اللوحة ، لذلك يرسل المنشور خطوة ؛ إذا لم يكن لديك هذه الخطوة ، فستحصل على خطأ. تجد النتيجة من خلال GET التالي.

الجحيم ، في هذا النموذج ، لا أستخدم معرف Gamer ، على الرغم من أنه قد يكون جيدًا حتى لا يتمكن أحد من التسلل إلى اللعبة ككيبتزر.

لذا فإن تفكيرك هو أنه بدلاً من جعل الإجراءات كائنًا من الدرجة الأولى ، سيتم التعامل مع كل خطوة كتحديث للعبة نفسها؟ إنها بالتأكيد طريقة مختلفة للقيام بذلك ، على الرغم من أنني أعتقد أنني أفضل تقسيم كائن الإجراء إلى كيانه من الدرجة الأولى لعدة أسباب. السبب الأكبر هو أنني أعتقد أنه أكثر قابلية للاختبار. سواء كانت خطوة صالحة أم لا ، يمكن أن تعيش في كائن الإجراء ، بدلاً من الحاجة إلى القلق بشأن وجود اللوحة في حالة صالحة في جميع الأوقات. منحت ، لا أعرف ما الذي سيستتبعه أي منهما ، لكن هذا يبدو أفضل بالنسبة لي.

السبب الآخر ، الذي يمكنك دحضه تمامًا عبر Yagni ، هو أن كائن الإجراء الأول من الدرجة الأولى سيوفر تاريخًا من التحركات. ربما مثيرة للاهتمام ، ولكن ما لم يكن هناك حاجة إلى نقطة نقاش.

أحد المطورين في Planet.jabber منخرط في Chesspark, ، مجتمع الشطرنج عبر الإنترنت. إنهم يستخدمون Jabber/XMPP على نطاق واسع ؛ اذا لم اكن مخطئ، هذه هي منشوراته في هذا الموضوع.

XMPP هو بروتوكول فوري للرسائل ، يعتمد تقريبًا على تبادل رسائل XML الصغير. هناك مكتبات لمعظم اللغات ، بما فيها جافا سكريبت. لست متأكدًا من أنها ستناسب مشكلتك.

بالنسبة للعبة بسيطة مثل الشطرنج، فإن الأمر يتعلق فقط بتحديد نوع الوسائط.

فيما يلي مثال لما قد يكون نوع وسائط مبسطًا للغاية لتصميم لعبة الشطرنج.

سأقوم بتخطي إدارة العديد من الألعاب التي قد تكون قيد التشغيل على نفس الخادم وأقوم فقط بتصميم لعبة قيد التشغيل بالفعل.

عادةً ما تكون الخطوة الأولى هي تحديد فهرس للتطبيق.

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 يحدد القطعة الفعلية في هذه اللوحة.قد توفر طلبات الحصول على URI هذا معلومات حول هذه القطعة بالذات.

يجب أن تحتوي كل قطعة على move وصلة.


كان قرار التصميم البديل الذي كان من الممكن أن أتخذه هنا هو توفير رابط فردي لكل حركة صالحة.قد تكون هناك أسباب وجيهة للقيام بذلك، ولكني أردت أن أوضح أنه ليس مطلوبًا.من المحتمل أن يكون هناك عدد قليل من الموارد الأخرى التي قد ترغب في تضمينها للتعامل مع أشياء مثل مساعدة العميل على تحديد من هو الدور وما إلى ذلك.

بالنسبة للألعاب الأكثر تعقيدًا، مثل Civilization أو RTS أو FPS أو MMOG وما إلى ذلك، قد لا تكون هذه IMO عملية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top