تعمل وحدة تحكّم Stadia التي تم تعديلها كذراع تحكّم عادي في الألعاب، ما يعني أنّه لا يمكن الوصول إلى جميع أزرارها باستخدام Gamepad API. باستخدام WebHID، يمكنك الآن الوصول إلى الأزرار المفقودة.
بعد إيقاف Stadia نهائيًا، خشي الكثيرون من أن تصبح وحدة التحكّم قطعة أجهزة عديمة الفائدة في مكب النفايات. لحسن الحظ، قرّر فريق Stadia بدلاً من ذلك إتاحة استخدام وحدة تحكّم Stadia من خلال توفير برنامج ثابت مخصّص يمكنك تثبيته على وحدة التحكّم من خلال الانتقال إلى صفحة وضع البلوتوث في Stadia. يؤدي ذلك إلى ظهور وحدة تحكّم Stadia على أنّها ذراع تحكّم عادي يمكنك توصيله باستخدام كابل USB أو لاسلكيًا عبر البلوتوث. تستخدم صفحة Stadia Bluetooth WebHID وWebUSB، وهي مدرَجة بكل فخر في معرض واجهات برمجة التطبيقات في Project Fugu، ولكن هذا ليس موضوع هذه المقالة. في هذه المشاركة، أريد أن أشرح كيف يمكنك التحدّث إلى وحدة تحكّم Stadia من خلال WebHID.
وحدة تحكّم Stadia كجهاز تحكّم عادي في الألعاب
بعد التحديث، تظهر وحدة التحكّم على أنّها وحدة تحكّم عادية في الألعاب لنظام التشغيل. راجِع لقطة الشاشة التالية لمعرفة الترتيب الشائع للأزرار والمحاور على وحدة التحكّم العادية. وفقًا لما هو محدّد في مواصفات Gamepad API، تحتوي أجهزة التحكّم العادية في الألعاب على أزرار من 0 إلى 16، أي 17 زرًا إجمالاً (يتم احتساب لوحة الاتجاهات كأربعة أزرار). إذا جرّبت وحدة التحكّم في Stadia على العرض التوضيحي لأداة اختبار لوحة الألعاب، ستلاحظ أنّها تعمل بشكل ممتاز.
ومع ذلك، إذا احتسبت الأزرار على وحدة تحكّم Stadia، ستجد أنّ عددها 19. إذا حاولت تجربتها بشكلٍ منتظم واحدة تلو الأخرى في أداة اختبار لوحة الألعاب، ستلاحظ أنّ زرَّي المساعد والتقاط لا يعملان. حتى إذا كانت سمة جهاز التحكّم في الألعاب buttons
كما هو محدّد في مواصفات جهاز التحكّم في الألعاب مفتوحة النهاية، بما أنّ وحدة تحكّم Stadia تظهر كوحدة تحكّم عادية في الألعاب، يتم ربط الأزرار من 0 إلى 16 فقط. سيظل بإمكانك استخدام الأزرار الأخرى، ولكن لن تتوقّع معظم الألعاب توفّرها.
WebHID لإنقاذ الموقف
بفضل واجهة برمجة التطبيقات WebHID API، يمكنك التفاعل مع الزرّين 17 و18 غير المتوفّرين. وإذا أردت ذلك، يمكنك حتى الحصول على بيانات حول جميع الأزرار والمحاور الأخرى المتاحة حاليًا من خلال Gamepad API. الخطوة الأولى هي معرفة الطريقة التي تعرّف بها وحدة تحكّم Stadia نفسها على نظام التشغيل. إحدى طرق إجراء ذلك هي فتح "وحدة تحكّم أدوات مطوّري البرامج في Chrome" على أي صفحة عشوائية، وطلب قائمة غير مفلترة بالأجهزة من WebHID API. بعد ذلك، اختَر يدويًا وحدة تحكّم Stadia لإجراء المزيد من الفحص. يمكنك الحصول على قائمة غير مفلترة بالأجهزة من خلال تمرير مصفوفة خيارات filters
فارغة.
const [device] = await navigator.hid.requestDevice({filters: []});
في أداة الاختيار، يبدو الإدخال قبل الأخير مثل وحدة تحكّم Stadia.
بعد اختيار جهاز "وحدة تحكّم Stadia الإصدار A"، سجِّل العنصر HIDDevice
الناتج في "وحدة التحكّم". سيؤدي ذلك إلى الكشف عن productId
(37888
، وهو 0x9400
بالنظام الست عشري) وvendorId
(6353
، وهو 0x18d1
بالنظام الست عشري) لوحدة تحكّم Stadia. إذا بحثت عن vendorID
في جدول معرّفات مورّدي USB الرسمي، ستجد أنّ 6353
يرتبط بما تتوقّعه: Google Inc.
.
بدلاً من الخطوات الموضّحة أعلاه، يمكنك الانتقال إلى chrome://device-log/
في شريط العناوين، والضغط على الزر محو، وتوصيل وحدة تحكّم Stadia، ثم الضغط على إعادة تحميل. ويوفّر لك ذلك المعلومات نفسها.
هناك بديل آخر وهو استخدام أداة HID Explorer التي تتيح لك استكشاف المزيد من تفاصيل أجهزة HID المتصلة بجهاز الكمبيوتر.
استخدِم رقمَي التعريف هذين، vendorId
وproductId
، لتحسين ما يظهر في أداة الاختيار من خلال الفلترة بشكل صحيح حسب جهاز WebHID المناسب.
const [stadiaController] = await navigator.hid.requestDevice({filters: [{
vendorId: 6353,
productId: 37888,
}]});
الآن، تم التخلص من الضوضاء الصادرة من جميع الأجهزة غير ذات الصلة، ولم تظهر سوى وحدة تحكّم Stadia.
بعد ذلك، افتح HIDDevice
من خلال استدعاء الطريقة open()
.
await stadiaController.open();
سجِّل HIDDevice
مرة أخرى، وسيتم ضبط العلامة opened
على true
.
عندما يكون الجهاز مفتوحًا، استمع إلى أحداث inputreport
الواردة من خلال ربط أداة متتبِّع الأحداث.
stadiaController.addEventListener('inputreport', (e) => {
console.log(e);
});
عند الضغط على زر مساعد Google في وحدة التحكّم ورفع إصبعك عنه، يتم تسجيل حدثَين في Play Console. يمكنك اعتبارها حدثَي "الضغط على زر مساعد Google" و "رفع الإصبع عن زر مساعد Google". وباستثناء timeStamp
، يبدو الحدثان متشابهَين للوهلة الأولى.
تعرض السمة reportId
للواجهة HIDInputReportEvent
بادئة تعريفية مكوّنة من بايت واحد لهذا التقرير، أو 0
إذا كانت واجهة HID لا تستخدم أرقام تعريف التقارير. في هذه الحالة، تكون القيمة 3
. يتم تخزين كلمة المرور في السمة data
، ويتم تمثيلها كـ DataView
بحجم 10. يوفر DataView
واجهة منخفضة المستوى لقراءة وكتابة أنواع أرقام متعددة في ArrayBuffer
ثنائي. للحصول على شيء أكثر قابلية للفهم من هذا التمثيل، يمكنك إنشاء Uint8Array
من ArrayBuffer
، حتى تتمكّن من رؤية الأعداد الصحيحة غير الموقّعة الفردية ذات 8 بت.
const data = new Uint8Array(event.data.buffer);
عندما تسجّل بيانات أحداث تقرير الإدخال مرة أخرى، ستبدأ الأمور في أن تصبح أكثر منطقية وستصبح أحداث "الضغط على زر مساعد Google" و "رفع الإصبع عن زر مساعد Google" قابلة للفهم. يبدو أنّ العدد الصحيح الأول (8
في كلا الحدثين) مرتبط بضغطة الزر، ويبدو أنّ العدد الصحيح الثاني (2
و0
) مرتبط بما إذا تم الضغط على زر مساعد Google أم لا.
اضغط على زر التقاط بدلاً من زر مساعد Google، وستلاحظ أنّ العدد الصحيح الثاني يتغيّر من 1
عند الضغط على الزر إلى 0
عند تحريره. يتيح لك ذلك كتابة "برنامج تشغيل" بسيط جدًا يتيح لك استخدام الزرّين المفقودين.
stadia.addEventListener('inputreport', (event) => {
if (!e.reportId === 3) {
return;
}
const data = new Uint8Array(event.data.buffer);
if (data[0] === 8) {
if (data[1] === 1) {
hidButtons[1].classList.add('highlight');
} else if (data[1] === 2) {
hidButtons[0].classList.add('highlight');
} else if (data[1] === 3) {
hidButtons[0].classList.add('highlight');
hidButtons[1].classList.add('highlight');
} else {
hidButtons[0].classList.remove('highlight');
hidButtons[1].classList.remove('highlight');
}
}
});
باستخدام أسلوب الهندسة العكسية هذا، يمكنك، زرًا زرًا ومحورًا محورًا، معرفة كيفية التواصل مع وحدة تحكّم Stadia باستخدام WebHID. بعد إتقان هذه العملية، يصبح الباقي مجرد عمل ميكانيكي لربط الأعداد الصحيحة.
الشيء الوحيد الذي ينقصنا الآن هو تجربة الربط السلس التي تتيحها Gamepad API. لأسباب تتعلق بالأمان، عليك دائمًا المرور بتجربة أداة الاختيار الأولية مرة واحدة من أجل استخدام جهاز WebHID، مثل وحدة تحكّم Stadia، ولكن بالنسبة إلى عمليات الربط المستقبلية، يمكنك إعادة الربط بالأجهزة المعروفة. يمكنك إجراء ذلك من خلال استدعاء الطريقة getDevices()
.
let stadiaController;
const [device] = await navigator.hid.getDevices();
if (device && device.vendorId === 6353 && device.productId === 37888) {
stadiaController = device;
}
عرض توضيحي
يمكنك الاطّلاع على وحدة تحكّم Stadia التي يتم التحكّم فيها بشكل مشترك من خلال Gamepad API وWebHID API في عرض توضيحي أنشأته. ننصحك بالاطّلاع على رمز المصدر الذي يستند إلى المقتطفات الواردة في هذه المقالة. لتبسيط الأمر، أعرض فقط الأزرار A وB وX وY (التي تتحكّم بها Gamepad API)، والزرَّين مساعد Google وتسجيل (الذي يتحكّم به WebHID API). أسفل صورة وحدة التحكّم، يمكنك الاطّلاع على بيانات WebHID الأولية، ما يتيح لك التعرّف على جميع الأزرار والمحاور في وحدة التحكّم.
الاستنتاجات
بفضل البرامج الثابتة الجديدة، يمكن الآن استخدام وحدة تحكّم Stadia كوحدة تحكّم عادية مزوّدة بـ 17 زرًا، وهو عدد كافٍ في معظم الحالات للتحكّم في ألعاب الويب الشائعة. إذا كنت بحاجة إلى بيانات من جميع الأزرار الـ 19 على وحدة التحكّم لأي سبب كان، تتيح لك WebHID الوصول إلى تقارير الإدخال المنخفضة المستوى التي يمكنك فك تشفيرها عن طريق إجراء هندسة عكسية لها واحدًا تلو الآخر. إذا أمكنك كتابة برنامج تشغيل WebHID كامل بعد قراءة هذه المقالة، يُرجى التواصل معي، وسأضيف رابطًا إلى مشروعك هنا بكل سرور. نتمنى لك تجربة WebHIDing ممتعة.
الإقرارات
راجع هذه المقالة François Beaufort.