الانتقال إلى المحتوى الرئيسي
تربط حزمة تطوير Flock لـUnreal لعبتك بالواجهة الخلفية لـFlock: مصادقة اللاعبين، وبيانات الحفظ، والاقتصاد، والإعدادات عن بُعد، والتحليلات — كل ذلك يُضبط من Project Settings، مع عقد Blueprint مُحدَّدة الأنواع أو شيفرة C++ تُولَّد من مخطّطاتك أنت. كل ميزة تقريبًا تعمل من Blueprint. فكل استدعاء عقدة غير متزامنة قائمة بذاتها لها طرفا نجاح وفشل، ولا طرف Target توصّله — إذ تستدلّ العقد على الحزمة من الرسم الذي تقع فيه. وبضعة استدعاءات متاحة في C++ وحدها: قراءة رقع اللعبة (game patches) نفسها (وFlock Resolve Config Data تُعيد القيم بعد تطبيق الرقع أصلًا، فنادرًا ما يحتاج رسم إليها)، وتسجيل معاملة في التحليلات، وتسليم الحزمة مسجِّلًا (logger) من عندك.

نزّل حزمة تطوير Unreal

احصل على أحدث إصدار من الإضافة عبر GitHub.
كل ما يلي متاح اليوم. أما اللعب الجماعي (الفرق والجلسات ومطابقة اللاعبين واتصال اللاعبين) فله أدلّة خاصة به، أولها اللعب الجماعي.

المتطلّبات

  • Unreal Engine من 5.4 إلى 5.8. كل إصدار من 5.5 فما فوق يُبنى وتُشغَّل عليه مجموعة الاختبارات كاملةً قبل كل إصدار؛ أما 5.4 فيُبنى ويُربط في مشروع حقيقي، لكن مجموعة الاختبارات لم تُشغَّل عليه بعد.
  • مشروع C++. أما المشاريع القائمة على Blueprint فقط فتحتاج إلى تثبيت سلسلة أدوات C++ لبناء الإضافة.
مشكلة معروفة في المحرّك على 5.4 و5.5: تنتهي حزمة Development بخطأ وصول إلى الذاكرة (0xC0000005) بعد نحو 60 ثانية من إغلاقها. تكون اللعبة قد أُغلقت حينها واكتمل سجلّها. هذا خلل في المحرّك لا في الحزمة: أصلحته Epic في 5.6، ويحدث سواء شغّلت أي ميزة من Flock أم لا. حزم Shipping لا تتضمّن الجزء المعنيّ، فلا يُتوقَّع أن تتأثر، وإن لم يُقَس ذلك. إن كان لديك سكربت يحكم على تشغيل حزمة، فاقرأ سطور خروج اللعبة نفسها في سجلّها بدلًا من رمز خروج العملية.

الإعداد

1

ثبّت الإضافة

نزّل أحدث إصدار وفكّ ضغطه داخل مجلد Plugins/ في مشروعك، بحيث يصبح لديك YourProject/Plugins/FlockUnrealSdk/.ثم انقر بالزر الأيمن على ملف .uproject واختر Generate Visual Studio project files، وأعِد البناء. والإضافة مُفعَّلة افتراضيًا — تحقّق من ذلك في Edit → Plugins → Online Platform → Flock SDK.
2

اضبط الإعدادات

افتح Project Settings → Plugins → Flock SDK Settings واملأ الحقول الأربعة من صفحة لعبتك على لوحة التحكم:وتُحفظ القيم في ملف DefaultGame.ini الخاص بمشروعك.
3

اترك الإصدار يُخبز

يُحلّ معرّف إصدار اللعبة ويُخبز من تلقاء نفسه ما إن تصبح تلك الحقول صحيحة، فلا يُجري بدء التشغيل أي اتصال بالشبكة للعثور عليه. ويمكنك فرض ذلك في أي وقت عبر Tools → Flock → Resolve Game Version.
4

استدعاء Flock من C++

أضف "Flock" إلى ملف Build.cs الخاص بوحدة لعبتك. أما المشروع القائم على Blueprint فقط فلا يحتاج إلى شيء هنا.

أول استدعاء لك

تهيّئ الحزمة نفسها تلقائيًا مع لعبتك، فليس هناك ما تبدأه. سجّل دخول لاعب، ثم اقرأ شيئًا في المقابل. وأبسط تسجيل دخول هو بالجهاز: بلا شاشة حساب وبلا كلمة مرور. ويحتاج إلى أربعة أشياء:
  1. معرّف الجهاز لهذا التثبيت. اترك معرّف الجهاز فارغًا فتستخدم استدعاءات الجهاز معرّف الحزمة نفسها: GUID تُنشئه أول مرة يُحتاج إليه وتحفظه في Saved/Flock/device_id.txt، فيعود اللاعب نفسه في كل تشغيل. واقرأه بـ ThisDeviceId() على مزوّد المصادقة، أو بـ Flock Get This Device Id في Blueprint.
  2. سجّل الدخول مرة واحدة. يُحفظ تسجيل الدخول بين مرات التشغيل ويُستعاد حين تبدأ الحزمة، فتحقّق أولًا هل سجّل لاعب دخوله من قبل، ولا تسجّل الدخول إلا حين لا يكون أحد قد سجّل دخوله. فتسجيل دخول ثانٍ يُنهي جلسة التحليلات التي بدأها الأول.
  3. سجّل الجهاز، ثم سجّل الدخول عند الحاجة فقط. فتسجيل الدخول لا يُنشئ حسابًا أبدًا، ولذلك يجب أن يسجّل التشغيل الأول الجهاز. والتسجيل الذي يُنشئ الحساب يسجّل دخول اللاعب أيضًا. وحين يكون للجهاز حساب من قبل، ينجح التسجيل مع ضبط Already Registered ولا يسجّل دخول أحد: فسجّل الدخول حينها. ولا تسجّل الدخول أبدًا بعد تسجيلٍ سجّل دخول اللاعب.
  4. أحداث تسجيل الدخول. يقول On Authenticated إن لاعبًا سجّل دخوله، أيًّا كانت الطريقة. ويقول On Auth Expired إن تسجيل دخول محفوظًا لم يعد ممكنًا تجديده، فيجب أن يسجّل اللاعب دخوله من جديد.
في Blueprint، ابنِ ذلك في الـ Blueprint الذي يبدأ مسار لعبتك، مثل وضع اللعبة (game mode) أو Blueprint المستوى، انطلاقًا من Event BeginPlay (يكون Flock قد بدأ حينها):
  1. سجّل الدخول مرة واحدة. استدعِ حدثًا مخصّصًا مثل Sign In With This Device، يبدأ بـ Branch على Flock Is Authenticated. وقيمة True تعني أن تسجيل دخول محفوظًا قد استُعيد: فلا تفعل شيئًا آخر.
  2. سجّل الجهاز، ثم سجّل الدخول عند الحاجة فقط. وعند False، شغّل Flock Register With Device تاركًا Device Id فارغًا، فتستخدم معرّف هذا التثبيت. ومن On Success فيها، فكّك النتيجة وتفرّع على Already Registered: فقيمة True تشغّل Flock Login With Device وDevice Id فيها فارغ أيضًا؛ وقيمة False تعني أن التسجيل سجّل دخول اللاعب.
  3. مرّر كل On Failure عبر To String (Flock Error) إلى Print String: فالنص يقول ما الخطأ وكيف تصلحه.
حدث مخصّص Sign In With This Device بلا مُدخلات، وتُترك فيه منافذ Device Id فارغة لتُستخدم المعرّف الذي تحفظه حزمة التطوير، يتفرّع على Flock Is Authenticated: فقيمة True تطبع Already signed in؛ وقيمة False تشغّل Flock Register With Device، التي يفكّك On Success فيها النتيجة ويتفرّع على Already Registered: فقيمة True تشغّل Flock Login With Device التي تطبع Signed in، وقيمة False تطبع Registered and signed in؛ وكل On Failure يطبع الخطأ عبر To String (Flock Error)

سجّل الدخول مرة واحدة: حين لا يكون أحد قد سجّل دخوله، سجّل الجهاز؛ وحين يكون له حساب من قبل، سجّل الدخول بالمعرّف نفسه.

تُمرّر الصورة إلى العقد مُدخل Device Id الخاص بالحدث؛ فاستدعِ الحدث وهو فارغ لتستخدم معرّف هذا التثبيت. وفي C++ يجب أن تكون المعالجات المربوطة بالأحداث UFUNCTION():
النجاح يظهر في Output Log على شكل Signed in as … ثم Playing …. والإخفاق يسجّل الاستدعاء الذي أخفق، وسبب الخادم، وسطر Fix:: انظر معالجة الأخطاء. ومعرّف الجهاز الفارغ يعني معرّف هذا التثبيت في LoginWithDevice وRegisterWithDevice وLinkDevice وعُقدها؛ أما أي معرّف آخر فيُرسَل كما تمرّره تمامًا. وتسجيل الخروج يُبقيه. ويُنشأ معرّف جديد حين يختفي الملف (إعادة التثبيت على هاتف، أو حذف مجلد Saved أو تنظيفه)، ومع المعرّف الجديد يأتي لاعب جديد بلا شيء من تقدّمه: ولكي تُبقي اللاعبين عبر إعادة التثبيت أو جهاز جديد، قدّم لهم ربط الحسابات (بريدًا إلكترونيًا أو حساب منصة). وحين تتعذّر قراءة الملف وكتابته معًا، تسجّل الحزمة تحذيرًا يقول السبب وكيف تصلحه، وتستخدم معرّفًا لذلك التشغيل وحده. (ولا يصلح FPlatformMisc::GetDeviceId معرّفًا: فهو فارغ على Windows وMac وLinux.) لا تمرّر معرّفًا من عندك إلا في حالتين:
  • لعبتك تسجّل دخول اللاعبين أصلًا بمعرّف من عندها (GUID محفوظ في SaveGame أو في ملف، كما كانت تعرض الإصدارات السابقة من هذه الصفحة): فواصل تمرير ذلك المعرّف نفسه. فتركه فارغًا يسجّل دخول كل لاعب موجود إلى حساب جديد فارغ.
  • نسختان من اللعبة تُشغَّلان من مجلد مشروع واحد (Play In Editor بجانب لعبة مستقلة، أو عميلا لعبة على جهاز واحد) تتشاركان Saved/، فتتشاركان المعرّف المحفوظ وتكونان لاعبًا واحدًا. فمرّر معرّفًا آخر في إحداهما.
تحمل دوالّ الإكمال TWeakObjectPtr إلى الحزمة، لا UFlockSubsystem* الخام ولا this أبدًا. فقد يصل الردّ بعد أن تبدأ اللعبة الإغلاق، فيشير المؤشّر الخام حينها إلى لا شيء.

التهيئة

خيار Auto Initialize on Load (في Flock SDK Settings، تحت Initialization) مُفعَّل افتراضيًا، لذا يكون UFlockSubsystem قيد التشغيل قبل BeginPlay. ولتأجيل ذلك إلى ما بعد شاشة البداية أو اتفاقية الترخيص، عطّله واستدعِ InitializeFromSettings() بنفسك (وفي Blueprint، Initialize From Settings على نظام Flock الفرعي):
ولأن التهيئة تقرأ معرّف إصدار مخبوزًا، فهي متزامنة ولا تُجري أي اتصال بالشبكة — فتبدأ لعبتك دون اتصال تمامًا كما تبدأ مع الاتصال.

صادِق لاعبًا

البريد الإلكتروني، ومعرّف الجهاز، وGoogle، وApple، وSteam، وFacebook، وDiscord. تستبدل الحزمة بيان الاعتماد الذي أنتجته حزمة تطوير المنصة لديك بجلسة Flock، وتخزّن الرموز مشفَّرة بين مرات التشغيل، وتستعيد الجلسة تلقائيًا عند الإقلاع، وتجدّد رموز الوصول المنتهية بصمت. كل طريقة عقدة غير متزامنة تحت Flock | Auth ‏(Flock Login With Email وFlock Register With Device وغيرهما)، أو استدعاء على مزوّد المصادقة في C++. وتسجيل الدخول والتسجيل استدعاءان منفصلان: فتسجيل الدخول لا يُنشئ حسابًا أبدًا، والتسجيل الذي يُنشئ حسابًا يسجّل دخول اللاعب أيضًا. وكل طريقة تتبع نمط الجهاز في أول استدعاء لك. ومثال ذلك تسجيل الدخول بالبريد الإلكتروني من شاشة تسجيل الدخول الخاصة بك:
وكل الطرق واستدعاءات التسجيل وعمليات الحساب في صفحة المصادقة.
لن تمرّر معرّف لاعب إطلاقًا. فالقراءات والأوامر تعمل نيابةً عن اللاعب المسجَّل دخوله؛ أما طرف Player Id فمُخبَّأ في القسم المتقدّم لكل عقدة، للحالة النادرة التي تتصرّف فيها بالنيابة عن لاعب آخر.

اعمل مع بيانات لعبتك

نقرة واحدة في القائمة تحوّل قوالب واجهتك الخلفية وإعداداتها ومتاجرها إلى عقد مُحدَّدة الأنواع. Tools → Flock → Sync Schemas — بلا C++، وبلا سلسلة أدوات، وبلا خطوة بناء.
قائمة Tools تعرض Resolve Game Version وSync Schemas وClean Generated

يولّد Tools → Flock → Sync Schemas ملفات مُحدَّدة الأنواع من مخطّطاتك أنت.

وتصبح قراءة إعدادٍ ما عقدة واحدة تحمل معها عملية الجلب والمعرّف:
عقدة Get Gameplay المُولَّدة تُغذّي عقدة Break

تجلب Get Gameplay وتحوّل وتُعيد بنية مُحدَّدة الأنواع — فكّكها للحصول على أطراف حقيقية.

ومع لاعب مسجّل الدخول، يُقرأ إعداد اللعب (gameplay) أو الميزات (feature) كما يحسمه Flock لذلك اللاعب: أحدث رقعة، ثم تجاوزات شرائح اللاعب، ثم تجاوزاته هو. ودون أحد مسجّل الدخول يُقرأ بقيم اللعبة العامة، فالإعداد الذي يُقرأ قبل تسجيل الدخول ينبغي أن يُقرأ من جديد بعد أن يسجّل اللاعب دخوله (من On Authenticated). انظر الإعدادات عن بُعد. وتغيير بيانات لاعب يجري هكذا: Get ← Set members in struct من المحرّك ← Save:
عقدة Get Player Level تُغذّي Set members ثم Save Player Level

تُعيد Get معرّف الصف إلى جانب البنية، لأن Save يحتاج إليه.

أشّر على الأعضاء الذين تريد كتابتهم. أما غير المؤشَّر عليهم فيحتفظون بما جلبته Get.
لوحة Details لعقدة Set members in struct

التأشير على عضو يُظهر طرفه — والأعضاء غير الملموسين يبقون كما كانوا تمامًا.

وتأخذ مشتريات المتجر ومنح العملات قائمة منسدلة مُولَّدة بدل معرّف تكتبه بيدك:
عقدة Flock Purchase في رسم Blueprint

اشترِ باختيار العنصر — فالمعرّف مخبوز ولا يمكن أن تخطئ في كتابته.

تفضّل C++؟

بدّل Codegen Target إلى C++ فتُصدِر المزامنة وحدة مُولَّدة بدلًا من ذلك — USTRUCT لكل قالب وإعداد، وUENUM لكل مجموعة معرّفات، وسطح استدعاء مُحدَّد الأنواع.
إعداد Codegen Target في Project Settings

يحدّد Codegen Target ما تُصدِره المزامنة. وBlueprint هو الافتراضي.

تكتب المزامنة الوحدة في Source/FlockGenerated وتسجّلها في ملف .uproject. ابنِ وأعِد تشغيل المحرّر، ثم أضف الوحدة إلى ملف Build.cs الخاص بوحدة لعبتك وضمّن ترويستها:
والأسماء أدناه من لعبة فيها قالب PlayerLevel وعنصر متجر GemPack وعملة Gold؛ أما أسماؤك فتتبع مخطّطاتك أنت.
ويستخدم المشروع الواحد أحد الهدفين لا كليهما. وبنى C++ المُولَّدة من نوع BlueprintType، فتظل الرسوم ترى أنواعك بعد التبديل.

الأمثلة

تأتي الإضافة بمثالين مصنوعين من Blueprint وحده، بلا شيفرة C++ خاصة بهما (مثال المتجر منذ 1.48.0). فعّل Show Plugin Content في إعدادات Content Browser لتراهما تحت Content/Samples في الإضافة. ويحتاج كلاهما أولًا إلى ملء Project Settings → Plugins → Flock SDK Settings.
  • Shop ‏(Content/Samples/Shop) — افتح المستوى FlockShopSample وشغّله: سجّل دخول جهاز، وافتح المتجر، واشترِ بالمحفظة أو بمال حقيقي (متجر الهاتف، أو الدفع عبر الويب على Windows وMac وLinux)، واستعمل ما يملكه اللاعب، واستعد المشتريات. ويحتاج إلى متجر في لوحة تحكّم Flock، والوسم currency على قالب اللاعب الذي يحمل المحفظة، ومعرّفات منتجات المتجر للعناصر المدفوعة بمال حقيقي. انظر المتاجر والمخزون والشراء داخل التطبيق.
  • Multiplayer ‏(Content/Samples/Multiplayer) — اضبط Game Instance Class على BP_FlockSampleGameInstance تحت Project Settings → Maps & Modes، ثم شغّل المستوى FlockMultiplayerSample في لعبتين مستقلّتين: سجّل الدخول باسم جهاز مختلف في كل منهما (فالاسم الواحد يجعلهما لاعبًا واحدًا)، ثم استضِف وانضمّ برمز، أو ابحث عن مباراة سريعة في طابور موجود للعبتك في لوحة تحكّم Flock. انظر اللعب الجماعي.
ولتبني على أحدهما، انسخ مجلّده إلى Content في مشروعك وعدّل النسخ.

استكشف الميزات

تسجيل الدخول

ربط الحسابات

بيانات اللاعب

المتاجر والمخزون

الشراء داخل التطبيق

الدفع عبر الويب

الإعدادات عن بُعد

لوحات الصدارة

الإشعارات

الأصول

التحليلات والأحداث

اللعب الجماعي

اختبار اللعب مع Protokite

الإعدادات المتقدّمة

يضبط Project Settings أيضًا التحليلات، وإعادات محاولة HTTP، وذاكرة وضع عدم الاتصال، ومسارات توليد الشيفرة. والقيم الافتراضية معقولة — فلا تغيّرها إلا عند الحاجة. وتفعيل Enable Debug Logs يتتبّع كل اتصال بالشبكة ضمن الفئة LogFlock، ويذكر كل سطر مصدر الاستدعاء لتميّز رسم Blueprint من شيفرة C++:

التخزين المؤقّت دون اتصال

تُخزَّن قراءات الإعدادات واللعبة وفهرس المتجر وقوالب اللاعبين مؤقتًا على القرص، ضمن نطاق إصدار لعبتك، وتُقدَّم عند تعذّر الوصول إلى الخادم — إذ يُجرَّب الخادم أولًا دائمًا، ولا توجد مدد صلاحية. وتُحفظ قيم الإعدادات للاعب المسجّل الدخول لكل لاعب على حدة، فتُعطي القراءة دون اتصال آخر قيم ذلك اللاعب، وإلا فقيم اللعبة العامة، ولا تُعطي قيم لاعب آخر أبدًا. أما عمليات الكتابة على بيانات اللاعب فتُصفّ في طابور عند انقطاع الاتصال وتُعاد تلقائيًا عند عودته. أما منح العملات فلا يُصفّ أبدًا: إذ يفشل المنح بدل أن يُصفّ، ولا يُعاد إرساله إطلاقًا بعد إخفاق غامض، فلا يمكن أن يُقيَّد مرتين.

معالجة الأخطاء

يردّ كل استدعاء بقيمة TFlockResult<T> بدل أن يرمي استثناءً — فـUnreal تُبنى مع تعطيل الاستثناءات. تحقّق من bSuccess، ثم اقرأ Value أو Error. وذلك داخل أي دالة إكمال، حيث Result هي قيمة TFlockResult التي استلمتها:
ويذكر Error.ToDisplayText() ما الخطأ وكيف تصلحه: الاستدعاء الذي أخفق، وسبب الخادم نفسه، والمعرّف المُرمَّز، وحالة HTTP، ثم سطر Fix:. ويحمل Output Log النصّ نفسه لكل استدعاء أخفق.
Output Log
ويحمل Error.Message ما الخطأ وحده، وError.Hint الإصلاح وحده؛ ولا يكون أيٌّ منهما فارغًا عند الإخفاق. وفي Blueprint، لكل عقدة غير متزامنة طرف On Failure يحمل Error نفسه. وتحوّله To String (Flock Error) إلى نص العرض، وتعطي Break Flock Error قيمته Error Code، وهي تعداد (enum) تقارنه دون مطابقة نصوص.
تجد المرجع الكامل للواجهة البرمجية، وأدلّة كل ميزة، وتفاصيل توليد الشيفرة في ملف README الخاص بالحزمة.