تعمل وحدة تحكّم Stadia التي تم فلاشها مثل ذراع تحكم عادي في الألعاب، ما يعني أنّه لا يمكن الوصول إلى جميع أزرارها باستخدام Gamepad API. باستخدام WebHID، يمكنك الآن الوصول إلى الأزرار غير المتوفّرة.
منذ إيقاف Stadia، خشى الكثيرون أن تنتهي وحدة التحكّم كقطعة أجهزة غير مفيدة في مكبّر النفايات. لحسن الحظ، قرّر فريق Stadia فتح وحدة تحكّم Stadia من خلال توفير برنامج ثابت مخصّص يمكنك تثبيته على وحدة التحكّم من خلال الانتقال إلى صفحة وضع البلوتوث في Stadia. يؤدي ذلك إلى ظهور وحدة تحكّم Stadia كوحدة تحكّم عادية في الألعاب يمكنك ربطها عبر كابل USB أو لاسلكيًا عبر البلوتوث. إنّ صفحة Stadia Bluetooth التي تم عرضها بفخر في Project Fugu API Showcase تستخدم WebHID وWebUSB، ولكنّ هذا ليس موضوع هذه المقالة. في هذه المشاركة، سأشرح كيفية التحدّث إلى وحدة تحكّم Stadia عبر WebHID.
استخدام وحدة تحكّم Stadia كجهاز تحكّم عادي في الألعاب
بعد الفلاش، ستظهر وحدة التحكّم لنظام التشغيل على أنّها وحدة تحكّم ألعاب عادية. اطّلِع على لقطة الشاشة التالية لمعرفة ترتيب الأزرار والمحاور الشائع على جهاز تحكم ألعاب عادي. وفقًا لما هو محدّد في مواصفات Gamepad API، تحتوي أجهزة التحكّم في الألعاب العادية على أزرار من 0 إلى 16، أي 17 زرًا في المجمل (يُحتسَب لوحة التوجيه على أنّها أربعة أزرار). إذا جرّبت وحدة تحكّم Stadia في الإصدار التجريبي من أداة اختبار لوحات الألعاب، ستلاحظ أنّها تعمل على أكمل وجه.
ومع ذلك، إذا احتسبت عدد الأزرار على وحدة تحكّم Stadia، ستجد أنّها 19 زرًا. إذا جرّبت الأزرار بشكل منهجي واحدًا تلو الآخر في أداة اختبار لوحة الألعاب، ستلاحظ أنّ زرَّي المساعد والتقاط لا يعملان. حتى إذا كانت سمة جهاز التحكّم في الألعاب buttons
كما هو محدّد في مواصفات جهاز التحكّم في الألعاب مفتوحة، يتمّ ربط الأزرار من 0 إلى 16 فقط لأنّ وحدة تحكّم Stadia تظهر كجهاز تحكّم عادي في الألعاب. سيظل بإمكانك استخدام الأزرار الأخرى، ولكن لن تتوقع معظم الألعاب وجودها.
استخدام WebHID لتقديم المساعدة
بفضل WebHID API، يمكنك التحدث إلى الزرَّين 17 و18 غير المتوفّرين. وإذا أردت، يمكنك أيضًا الحصول على بيانات عن جميع الأزرار والمحاور الأخرى المتاحة حاليًا من خلال Gamepad API. الخطوة الأولى هي معرفة كيفية إبلاغ وحدة تحكّم Stadia ببياناتها لنظام التشغيل. وتتوفّر طريقة واحدة لإجراء ذلك وهي فتح "وحدة تحكّم أدوات مطوّري البرامج في Chrome" على أي صفحة عشوائية وطلب قائمة غير مفلتَرة بالأجهزة من WebHID API. يمكنك بعد ذلك اختيار وحدة تحكّم Stadia يدويًا لإجراء مزيد من الفحص. يمكنك الحصول على قائمة غير مفلتَرة بالأجهزة من خلال تمرير صفيف خيارات filters
فارغ.
const [device] = await navigator.hid.requestDevice({filters: []});
في أداة الاختيار، يبدو الإدخال قبل الأخير مثل وحدة تحكّم Stadia.
بعد اختيار جهاز "Stadia Controller rev. A"، سجِّل عنصر HIDDevice
الناتج في وحدة التحكّم. يكشف ذلك عن productId
(37888
، أي 0x9400
في نظام الترميز الست عشري) وvendorId
(6353
، أي 0x18d1
في نظام الترميز الست عشري) لوحدة تحكّم Stadia. إذا بحثت عن vendorID
في جدول معرّفات مورّدي USB الرسمي، ستلاحظ أنّ 6353
يرتبط بما تتوقّعه: Google Inc.
.
يمكنك اتّباع مسار بديل للخطوات الموضّحة أعلاه، وهو الانتقال إلى chrome://device-log/
في شريط عنوان URL، والضغط على الزر محو، ثم توصيل وحدة تحكّم 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 في وحدة التحكّم ثم رفع إصبعك عنه، يتم تسجيل حدثَين في وحدة التحكّم. يمكنك اعتبارهما حدثَي "ضغطة زر مساعد Google" و "رفع الضغط عن زر مساعد Google". باستثناء timeStamp
، يبدو أنّ الحدثَين متطابقَين للوهلة الأولى.
تعرض سمة reportId
لواجهة HIDInputReportEvent
بادئة التعريف التي تبلغ بايتة واحدة لهذا التقرير، أو 0
إذا كانت واجهة HID لا تستخدِم أرقام تعريف التقارير. في هذه الحالة، يكون 3
. يكمن السر في السمة data
، والتي يتم تمثيلها على شكل DataView
بحجم 10. يوفّر DataView
واجهة من المستوى الأدنى لقراءة وكتابة أنواع أرقام متعددة في ArrayBuffer
ثنائي. للحصول على تمثيل أكثر سهولة من هذا التمثيل، يمكنك إنشاء Uint8Array
من ArrayBuffer
، حتى تتمكّن من الاطّلاع على الأعداد الصحيحة الفردية التي تبلغ 8 بت وغير الموقّعة.
const data = new Uint8Array(event.data.buffer);
عند تسجيل بيانات أحداث تقارير الإدخال مرة أخرى، تبدأ الأمور في الوضوح أكثر ويصبح من الممكن فك ترميز أحداث "زرّ المساعِد مطبوع" و "زرّ المساعِد مرفوع". يبدو أنّ الرقم الصحيح الأول (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) والأزرار مساعِد والتقاط (التي يتم التحكّم فيها من خلال WebHID API). أسفل صورة جهاز التحكّم، يمكنك الاطّلاع على بيانات WebHID الأوّلية، ما يتيح لك التعرّف على جميع الأزرار والمحاور في جهاز التحكّم.
الاستنتاجات
بفضل البرامج الثابتة الجديدة، يمكن الآن استخدام وحدة تحكّم Stadia كوحدة تحكّم ألعاب عادية تتضمّن 17 زرًا، وهو عدد كافٍ في معظم الحالات للتحكّم في ألعاب الويب الشائعة. إذا كنت بحاجة إلى بيانات من جميع الأزرار الـ 19 على وحدة التحكّم لأي سبب، يتيح لك WebHID الوصول إلى تقارير الإدخال من المستوى الأدنى التي يمكنك فك ترميزها من خلال الهندسة العكسية لها واحدًا تلو الآخر. إذا كتبت برنامج تشغيل WebHID كاملاً بعد قراءة هذه المقالة، يُرجى التواصل معي، وسيسرّني ربط مشروعك هنا. مع أطيب التحيّات،
الشكر والتقدير
راجع فاروق فريد هذه المقالة.