الألعاباللغوية
Logo
اللغة

إعداد الحزمة والمنصة

استخدم الحزمة داخل builds الحديثة، أو اعتمد على النسخة العامة التي تحقنها المنصة تلقائيًا في ألعاب ZIP المرفوعة. لا تبنِ طبقات wrapper خاصة فوق SDK.

Setup
9 أسطر
1
# Preferred for packaged games
2
npm install gamehub-sdk
3
4
# GameHub-hosted ZIP uploads
5
# No manual install or script tag is required. The platform injects:
6
<script src="/sdk/gamehub-sdk.js" data-game-slug="your-game-slug"></script>
7
8
# Local standalone testing only
9
<script src="https://gamesbeta.ksaa.gov.sa/sdk/gamehub-sdk.js"></script>
مهم: SDK يعمل كنسخة singleton ويبدأ التهيئة تلقائيًا. على المطور انتظار ready() ثم استخدام الدوال العامة مباشرة.

تهيئة وقت التشغيل

اقرأ سياق التشغيل القادم من GameHub: بيانات اللعبة، المصادقة والجلسة، بيانات الدوري والمباراة، غرفة اللعب الجماعي، peer id، اللاعب الحالي، والمشاركين.

TypeScript / JavaScript — package usage
17 أسطر
1
// Bundled app: React, Angular, Vue, Phaser, Vite, Webpack, etc.
2
import GameHubSDK from "gamehub-sdk";
3
4
const sdk = GameHubSDK || window.GameHubSDK;
5
6
await sdk.ready(); // no init() call is required
7
8
const bootstrap = sdk.getBootstrap();
9
console.log({
10
version: sdk.version,
11
gameSlug: bootstrap.gameSlug,
12
leagueId: bootstrap.leagueId,
13
matchId: bootstrap.matchId,
14
peerId: bootstrap.peerId,
15
currentPlayer: bootstrap.currentPlayer,
16
players: bootstrap.players,
17
});
JavaScript — injected global
10 أسطر
1
// If your game does not use a bundler, use the injected global.
2
await window.GameHubSDK.ready();
3
4
const sdk = window.GameHubSDK;
5
const bootstrap = sdk.getBootstrap();
6
7
if (bootstrap.matchId) {
8
const match = await sdk.getMatchContext();
9
renderParticipants(match.participant1, match.participant2);
10
}

يرجع BootstrapData

gameSlugstring | nullslug اللعبة الحالي.
leagueId / gameId / matchIdstring | nullسياق الدوري والمباراة عندما يتم تشغيل اللعبة من الدوري.
matchMatchContext | nullسياق المباراة بعد تحميله من getMatchContext.
playersBootstrapPlayer[] | nullقائمة اللاعبين التي يرسلها المضيف، تشمل peerId و role و displayName و avatar.
currentPlayerBootstrapPlayer | nullاللاعب الحالي المطابق لقيمة peerId.
roomBootstrapRoom | nullملخص غرفة اللعب الجماعي عند توفره.

لا يوجد init

SDK يبدأ تلقائيًا عند تحميله. استخدم ready() كحاجز انتظار فقط.

سياق غني

getBootstrap() يحتوي بيانات اللعبة والدوري والمباراة والغرفة واللاعب الحالي.

حزمة واحدة

استخدم gamehub-sdk داخل اللعبة مباشرة ولا تنسخ ملفات SDK أو تبني wrapper منفصل.

الجلسات والنتائج

أرسل نتائج الألعاب المستقلة مع بيانات اختيارية. في غرف اللعب الجماعي يمنع SDK تعدد الإرسال بحيث يكتب المضيف النتيجة فقط.

JavaScript — sessions.js
15 أسطر
1
// Submit a normal score when a standalone game ends.
2
async function submitFinalScore(score, gameState) {
3
await GameHubSDK.ready();
4
5
const result = await GameHubSDK.submitScore(score, {
6
mode: gameState.mode, // "single" | "two_players_local" | "two_players_online"
7
correctAnswers: gameState.correctAnswers,
8
totalQuestions: gameState.totalQuestions,
9
durationMs: gameState.durationMs,
10
level: gameState.level,
11
});
12
13
if (result.skipped) return; // online guest/viewer: host will submit
14
if (!result.success) showSubmitError(result.error);
15
}

معاملات submitScore

المعاملالنوعمطلوبالوصف
scorenumberمطلوبالنتيجة النهائية، ويجب أن تكون عددًا صحيحًا غير سالب.
meta.mode"single" | "two_players_local" | "two_players_online"اختياريوضع اللعب المستخدم لتجميع لوحة الصدارة.
meta.correctAnswersnumberاختياريعدد الإجابات الصحيحة لتحليل مكافحة الغش.
meta.totalQuestionsnumberاختياريإجمالي الأسئلة المعروضة للاعب.
meta.durationMsnumberاختياريالوقت المستغرق بالمللي ثانية، ويستخدم في التحقق من مكافحة الغش.
meta.roomCodestringاختياريكود غرفة اللعب الجماعي إن وجد.

يرجع Promise<object>

successbooleanهل نجح استدعاء SDK.
acceptedbooleanهل قبل الخادم النتيجة بعد اجتياز مكافحة الغش.
timeTakennumberمدة اللعب المحسوبة من الخادم بالمللي ثانية.
errorstring?رسالة الخطأ عندما تكون success بقيمة false.
skippedboolean?تظهر عندما يتجاهل SDK الإرسال لأن اللاعب ليس المضيف في غرفة جماعية.

مباريات الدوري

عند تشغيل اللعبة من مباراة دوري، يوفر SDK سياق المباراة ويتيح للمضيف إرسال الفائز ونتائج المشاركين وتفاصيل النتيجة.

JavaScript — league-match.js
22 أسطر
1
await GameHubSDK.ready();
2
3
const bootstrap = GameHubSDK.getBootstrap();
4
const match = await GameHubSDK.getMatchContext();
5
6
if (bootstrap.matchId && match) {
7
showSideA(match.participant1.name, match.participant1.members);
8
showSideB(match.participant2.name, match.participant2.members);
9
}
10
11
// Submit the bracket result. Use the participantId from match context.
12
await GameHubSDK.submitMatchResult({
13
winnerId: match.participant1.participantId,
14
scores: {
15
[match.participant1.participantId]: 12,
16
[match.participant2.participantId]: 8,
17
},
18
details: {
19
durationMs: 94000,
20
reason: "normal_finish",
21
},
22
});

حقول سياق المباراة

يرجع MatchContext | null

idstringمعرّف مباراة الدوري الحالية.
leagueIdstringمعرّف الدوري الذي تنتمي إليه المباراة.
gameIdstringمعرّف اللعبة المطلوبة لهذه المباراة.
participant1{ participantId, name, members[] }الفريق أو اللاعب الأول، مع أسماء الأعضاء عند توفرها.
participant2{ participantId, name, members[] }الفريق أو اللاعب الثاني، مع أسماء الأعضاء عند توفرها.
statusstringحالة المباراة في جدول الدوري.

معاملات submitMatchResult

المعاملالنوعمطلوبالوصف
winnerIdstringاختياريمعرّف participantId للفائز كما هو موجود في match.participant1 أو match.participant2.
scoresRecord<string, number>اختياريخريطة نتائج المشاركين، حيث يكون المفتاح هو participantId والقيمة هي النتيجة.
reasonstringاختياريسبب إنهاء المباراة مثل normal_finish أو timeout أو forfeit.
detailsRecord<string, unknown>اختياريأي تفاصيل إضافية تحتاجها لوحة الإدارة أو التحليلات.
في اللعب الجماعي، استدع submitMatchResult من المضيف فقط. إذا استدعاه لاعب ضيف أو مشاهد فسيعيد SDK نتيجة skipped بدون إرسال طلب للشبكة.

الأسئلة

اجلب الأسئلة المنشورة مباشرة من المنصة. يستخدم SDK قيمة gameId عندما يوفرها المضيف، وإلا يستخدم slug اللعبة.

JavaScript — questions.js
26 أسطر
1
// All parameters are optional.
2
async function loadQuestions() {
3
await GameHubSDK.ready();
4
5
// Returns an array of question objects directly (empty array on error)
6
const questions = await GameHubSDK.getQuestions({
7
difficulty: "medium", // "easy" | "medium" | "hard" (optional)
8
category: "science", // any string (optional)
9
limit: 20, // 1–100, defaults to 100 (optional)
10
});
11
12
console.log(questions.length); // number of questions returned
13
14
// Each question shape:
15
// {
16
// id: string
17
// type: string
18
// prompt: string
19
// choices: string[]
20
// answer: string | number
21
// explanation: string
22
// difficulty: "easy" | "medium" | "hard"
23
// category: string
24
// points: number
25
// }
26
}

خيارات getQuestions

المعاملالنوعمطلوبالوصف
difficulty"easy" | "medium" | "hard"اختياريتصفية الأسئلة حسب مستوى الصعوبة.
categorystringاختياريتصفية الأسئلة حسب وسم التصنيف مثل science أو history.
limitnumberاختياريالحد الأقصى لعدد الأسئلة المعادة من 1 إلى 100.

يرجع Promise<Question[]>

[n].idstringمعرّف السؤال الفريد.
[n].promptstringنص السؤال.
[n].choicesstring[]خيارات الإجابة، وتكون فارغة للأسئلة المفتوحة.
[n].answerstring | numberقيمة الإجابة الصحيحة أو رقمها.
[n].difficulty"easy" | "medium" | "hard"مستوى الصعوبة.
[n].categorystringوسم التصنيف.
[n].pointsnumberقيمة النقاط.

شكل كائن السؤال

الحقلالنوعالوصف
idstringمعرّف السؤال الفريد.
typestringنوع السؤال مثل multiple_choice.
promptstringنص السؤال المعروض للاعب.
choicesstring[]خيارات الإجابة، وتكون فارغة للأسئلة المفتوحة.
answerstring | numberقيمة الإجابة الصحيحة أو رقمها.
explanationstringشرح اختياري يظهر بعد الإجابة.
difficulty"easy" | "medium" | "hard"مستوى صعوبة السؤال.
categorystringوسم التصنيف المستخدم للتصفية.
pointsnumberقيمة النقاط المخصصة لهذا السؤال.
آلية العمل: يتم تقديم الأسئلة من مجموعة MongoDB مرتبطة باللعبة. يتم إرجاع الأسئلة المنشورة فقط، ويتم اختيار النتائج عشوائيًا في كل طلب. published

اللعب الجماعي بصلاحية المضيف

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

المضيف هو المصدر

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

الضيف يرسل نية

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

حماية النتيجة

submitScore و submitMatchResult يعملان من المضيف فقط داخل الغرفة. غير المضيف يحصل على skipped.

JavaScript — Host
9 أسطر
1
// Host creates and shares a room
2
await GameHubSDK.ready();
3
4
const room = await GameHubSDK.multiplayer.createRoom({ maxPlayers: 2 });
5
if (!room.success) throw new Error(room.error);
6
7
// Share room.shareUrl or room.roomCode with other players
8
console.log("Room code:", room.roomCode);
9
console.log("Share link:", room.shareUrl);
JavaScript — Player
16 أسطر
1
// Player joins via share link or room code
2
await GameHubSDK.ready();
3
4
await GameHubSDK.multiplayer.joinRoomByLink(window.location.href);
5
// or:
6
await GameHubSDK.multiplayer.joinRoom("ROOM_CODE", { displayName: "Player 2" });
7
// view-only:
8
await GameHubSDK.multiplayer.joinRoom("ROOM_CODE", { asViewer: true });
9
10
// Listen for events from other players
11
GameHubSDK.multiplayer.on("message", (msg) => {
12
console.log(msg.eventName, msg.payload);
13
});
14
15
// Send player intent to the room
16
GameHubSDK.multiplayer.send("player_move", { x: 2, y: 1 });
JavaScript — Full Flow
39 أسطر
1
await GameHubSDK.ready();
2
3
const mp = GameHubSDK.multiplayer;
4
5
// Host owns randomness and authoritative state.
6
if (!mp.isConnected()) {
7
await mp.createRoom({ maxPlayers: 2 });
8
}
9
10
mp.on("peer_joined", () => {
11
if (!mp.isHost()) return;
12
const seed = crypto.randomUUID();
13
mp.broadcast("match_start", { seed, turn: 0 });
14
});
15
16
mp.on("match_start", ({ payload }) => {
17
buildBoardFromSeed(payload.seed);
18
});
19
20
// Players send intent. They do not mutate final state locally.
21
function onCellClick(cellId) {
22
mp.send("cell_click", { cellId });
23
}
24
25
// Host validates and broadcasts the result.
26
mp.on("cell_click", ({ fromPeerId, payload }) => {
27
if (!mp.isHost()) return;
28
const result = resolveMove(fromPeerId, payload.cellId);
29
mp.broadcast("cell_resolved", result);
30
});
31
32
// Everyone applies the same resolved state.
33
mp.on("cell_resolved", ({ payload }) => {
34
applyResolvedMove(payload);
35
36
if (payload.isFinal && mp.isHost()) {
37
GameHubSDK.submitMatchResult(payload.matchResult);
38
}
39
});

خيارات createRoom

المعاملالنوعمطلوبالوصف
maxPlayersnumberاختياريالحد الأقصى للاعبين المسموح بهم في الغرفة من 2 إلى 16.
passcodestringاختياريرمز مرور اختياري من 4 إلى 32 حرفًا لتقييد الدخول.

خيارات joinRoom

المعاملالنوعمطلوبالوصف
passcodestringاختياريرمز المرور المطلوب إذا أنشأ المضيف الغرفة برمز.
displayNamestringاختياريالاسم المعروض لهذا اللاعب في قائمة اللاعبين.
asViewerbooleanاختيارييجعل اللاعب للعرض فقط: لا send ولا broadcast ولا إرسال نتائج.

أحداث النظام

الحدثالبياناتالوصف
connected{ roomCode, peerId }تم فتح اتصال WebSocket.
disconnected{ roomCode }تم إغلاق اتصال WebSocket وقد تبدأ إعادة الاتصال.
reconnecting{ attempts, delayMs }SDK ينتظر قبل محاولة إعادة الاتصال التالية.
room_joined{ peerId, role, peers[] }يتم إطلاقه عند الانضمام إلى الغرفة بنجاح.
peer_joined{ peerId, ... }اتصل لاعب جديد بالغرفة.
peer_left{ peerId }انقطع اتصال لاعب أو غادر الغرفة.
host_changed{ peerId }تم نقل دور المضيف إلى لاعب جديد.
room_closed{ reason }أغلق المضيف الغرفة وتم قطع اتصال جميع اللاعبين.
room_left{ reason }غادر اللاعب المحلي الغرفة أو أغلقت الغرفة عليه.
error{ code }رفض الخادم رسالة مثل RATE_LIMITED أو MESSAGE_TOO_LARGE.
message{ eventName, payload, fromPeerId, seq }حدث مخصص أرسله لاعب آخر عبر send().

مرجع API

قائمة كاملة بدوال window.GameHubSDK.

الدوال الأساسية

الدالةالوصف
ready()ينتهي عند اكتمال تهيئة SDK. من الآمن انتظاره قبل أي استدعاء آخر.
isInitialized()تكون true بعد أن يحل SDK سياق اللعبة وينهي التهيئة التلقائية.
isAuthenticated()تكون true عندما يملك SDK رمز مصادقة من المنصة الحاضنة.
startSession()يبدأ جلسة لعب جديدة. يتم استدعاؤه تلقائيًا من submitScore إذا لم يتم استدعاؤه يدويًا.
playAgain()يشير إلى بدء جولة أخرى مع إعادة استخدام رمز الجلسة الحالي.
submitScore(score, meta?)يرسل النتيجة النهائية للاعب مع بيانات اختيارية. في غرف اللعب الجماعي تعيد الأطراف غير المضيفة skipped بدون كتابة.
submitMatchScore(score, meta?)يرسل نتيجة لمباراة دوري تم تشغيلها من الإدارة ويربط matchId الحالي بمحاولة الجلسة المحفوظة.
submitMatchResult(result)يرسل نتيجة مباراة في جدول الدوري مع نقاط المشاركين وبيانات الفائز.
getMatchContext()يجلب ويخزن سياق مباراة الدوري الحالية، بما يشمل أسماء المشاركين وأعضاء الفرق.
getQuestions(options?)يجلب أسئلة هذه اللعبة. يعيد مصفوفة فارغة عند الخطأ. جميع الخيارات اختيارية.
getBootstrap()يعيد حالة SDK وإعدادات المضيف: اللعبة، المصادقة، الدوري، المباراة، الغرفة، اللاعبين، واللاعب الحالي.
getGameSlug()يعيد slug اللعبة الذي تمت تهيئة SDK به.
hasActiveSession()تكون true إذا كان رمز الجلسة موجودًا حاليًا في الذاكرة.
notifyComplete(data?)يرسل رسالة GAME_COMPLETE إلى الإطار الأب.
requestClose()يطلب من المنصة إغلاق اللعبة أو الانتقال خارجها.
logEvent(name, data?)يرسل حدث تحليلات مسمى إلى المنصة الحاضنة.
isInIframe()تكون true عندما تكون اللعبة مضمنة داخل iframe.

دوال اللعب الجماعي

الدالةالوصف
multiplayer.createRoom(options?)ينشئ غرفة لعب جماعي جديدة ويصبح المستدعي هو المضيف.
multiplayer.joinRoom(roomCode)ينضم إلى غرفة موجودة باستخدام الكود المختصر.
multiplayer.joinRoomByLink(url)ينضم إلى غرفة باستخدام رابط المشاركة الكامل.
multiplayer.leaveRoom(reason?)يغادر الغرفة الحالية. عند إغلاق المضيف للغرفة يتم إرسال room_closed لجميع اللاعبين.
multiplayer.send(eventName, payload?)يبث حدثًا مخصصًا إلى جميع اللاعبين داخل الغرفة.
multiplayer.broadcast(eventName, payload?)إرسال خاص بالمضيف لتحديثات الحالة الموثوقة. الضيوف والمشاهدون يعيدون false.
multiplayer.on(eventName, handler)يشترك في حدث معين ويعيد دالة لإلغاء الاشتراك.
multiplayer.getRoom()يعيد حالة الغرفة الحالية.
multiplayer.getPeers()يعيد قائمة بجميع اللاعبين المتصلين في الغرفة.
multiplayer.isConnected()تكون true إذا كان اتصال WebSocket مفتوحًا حاليًا.
multiplayer.getRole()يعيد دور الطرف المحلي: host أو player أو viewer أو null.
multiplayer.isHost()تكون true عندما يكون هذا الطرف هو مضيف الغرفة الموثوق.
multiplayer.isViewer()تكون true عندما ينضم هذا الطرف بخيار asViewer ويكون للعرض فقط.
multiplayer.selfId()يعيد peerId المحلي لاستخدامه في تصفية الرسائل المرتدة من نفس اللاعب.