> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qwacks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# حزمة تطوير Unreal

> أضف Flock إلى لعبتك في Unreal Engine عبر الإضافة الرسمية — من C++ أو من Blueprint.

تربط حزمة تطوير Flock لـUnreal لعبتك بالواجهة الخلفية لـFlock: مصادقة اللاعبين، وبيانات الحفظ،
والاقتصاد، والإعدادات عن بُعد، والتحليلات — كل ذلك يُضبط من Project Settings، مع عقد Blueprint
مُحدَّدة الأنواع أو شيفرة C++ تُولَّد من مخطّطاتك أنت.

**كل ميزة تعمل من Blueprint.** فكل استدعاء عقدة غير متزامنة قائمة بذاتها لها طرفا نجاح وفشل، ولا
طرف Target توصّله — إذ تستدلّ العقد على الحزمة من الرسم الذي تقع فيه.

<Card title="نزّل حزمة تطوير Unreal" icon="download" href="https://github.com/QwackStack/FlockUnrealSdk/releases">
  احصل على أحدث إصدار من الإضافة عبر GitHub.
</Card>

<Note>
  **وصول مبكر.** كل ما يلي متاح اليوم. و**الأصول** القابلة للتنزيل هي ميزة Unity الوحيدة التي لم
  تصل بعد إلى حزمة Unreal — وستصل في إصدار لاحق.
</Note>

<h2 id="requirements">
  المتطلّبات
</h2>

* Unreal Engine **5.5**
* مشروع C++. أما المشاريع القائمة على Blueprint فقط فتحتاج إلى تثبيت سلسلة أدوات C++ لبناء الإضافة.

<h2 id="setup">
  الإعداد
</h2>

<Steps>
  <Step title="ثبّت الإضافة">
    نزّل أحدث [إصدار](https://github.com/QwackStack/FlockUnrealSdk/releases) وفكّ ضغطه داخل مجلد
    `Plugins/` في مشروعك، بحيث يصبح لديك `YourProject/Plugins/FlockUnrealSdk/`.

    ثم انقر بالزر الأيمن على ملف `.uproject` واختر **Generate Visual Studio project files**، وأعِد
    البناء. والإضافة مُفعَّلة افتراضيًا — تحقّق من ذلك في **Edit → Plugins → Online Platform →
    Flock SDK**.
  </Step>

  <Step title="اضبط الإعدادات">
    افتح **Project Settings → Plugins → Flock SDK** واملأ الحقول الأربعة من صفحة لعبتك على
    [لوحة التحكم](https://flock-saas.qwacks.com):

    | الحقل            | القيمة                                                                          |
    | ---------------- | ------------------------------------------------------------------------------- |
    | **API URL**      | اترك القيمة الافتراضية (`https://api-flock.qwacks.com`) ما لم يُطلب منك غير ذلك |
    | **API Key**      | يُعرّف لعبتك — تعامَل معه كما تتعامل مع كلمة المرور                             |
    | **Game Name**    | اسم لعبتك كما هو على لوحة التحكم                                                |
    | **Game Version** | اسم إصدار لعبتك، مثل `1.0.0`                                                    |

    وتُحفظ القيم في ملف `DefaultGame.ini` الخاص بمشروعك.
  </Step>

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

<h2 id="your-first-call">
  أول استدعاء لك
</h2>

تهيّئ الحزمة نفسها تلقائيًا مع لعبتك، فليس هناك ما تبدأه. سجّل دخول لاعب، ثم اقرأ شيئًا في المقابل.

<Frame caption="سجّل الدخول عند BeginPlay، ثم اقرأ سجل اللعبة — بلا طرف Target في أيٍّ من العقدتين.">
  <img src="https://mintcdn.com/qwacks/xJEjgQCFVIWLhvHB/images/sdk/unreal/quickstart-graph.png?fit=max&auto=format&n=xJEjgQCFVIWLhvHB&q=85&s=5c493067823b2181580b28285fc42bad" alt="رسم Blueprint يمرّر Flock Login With Device إلى Flock Get Game" width="890" height="437" data-path="images/sdk/unreal/quickstart-graph.png" />
</Frame>

```cpp theme={null}
UFlockSubsystem* Sdk = UFlockSubsystem::Get(this);

Sdk->GetAuthProvider()->LoginWithDevice(DeviceId,
    [Sdk](TFlockResult<FFlockPlayerLoginResponse> Login)
    {
        if (!Login.bSuccess) { return; }

        Sdk->GetGameProvider()->GetGame(
            [](TFlockResult<FFlockGameSchema> Game)
            {
                UE_LOG(LogTemp, Log, TEXT("Playing %s"), *Game.Value.Name);
            });
    });
```

<h2 id="initialization">
  التهيئة
</h2>

خيار **Auto-Initialize On Load** مُفعَّل افتراضيًا، لذا يكون `UFlockSubsystem` قيد التشغيل قبل
`BeginPlay`. ولتأجيل ذلك إلى ما بعد شاشة البداية أو اتفاقية الترخيص، عطّله واستدعِ
`InitializeFromSettings()` بنفسك.

ولأن التهيئة تقرأ معرّف إصدار مخبوزًا، فهي متزامنة ولا تُجري أي اتصال بالشبكة — فتبدأ لعبتك دون
اتصال تمامًا كما تبدأ مع الاتصال.

<h2 id="authenticate-a-player">
  صادِق لاعبًا
</h2>

البريد الإلكتروني، ومعرّف الجهاز، وGoogle، وApple، وSteam، وFacebook، وDiscord. تستبدل الحزمة بيان
الاعتماد الذي أنتجته حزمة تطوير المنصة لديك بجلسة Flock، وتخزّن الرموز مشفَّرة بين مرات التشغيل،
وتستعيد الجلسة تلقائيًا عند الإقلاع، وتجدّد رموز الوصول المنتهية بصمت.

<Frame caption="تسجيل الدخول والتسجيل استدعاءان منفصلان — فالتسجيل لا يسجّل دخول اللاعب.">
  <img src="https://mintcdn.com/qwacks/xJEjgQCFVIWLhvHB/images/sdk/unreal/auth-login.png?fit=max&auto=format&n=xJEjgQCFVIWLhvHB&q=85&s=f322ebe2c890469c6ab62616019424f9" alt="عقدتا Flock Login With Email وFlock Register With Device في رسم Blueprint" width="713" height="261" data-path="images/sdk/unreal/auth-login.png" />
</Frame>

```cpp theme={null}
Sdk->GetAuthProvider()->LoginWithEmail(Email, Password,
    [](TFlockResult<FFlockPlayerLoginResponse> Result)
    {
        if (Result.bSuccess)
        {
            UE_LOG(LogTemp, Log, TEXT("Signed in as %s"), *Result.Value.PlayerId);
        }
    });
```

<Tip>
  لن تمرّر معرّف لاعب إطلاقًا. فالقراءات والأوامر تعمل نيابةً عن اللاعب المسجَّل دخوله؛ أما طرف
  `Player Id` فمُخبَّأ في القسم المتقدّم لكل عقدة، للحالة النادرة التي تتصرّف فيها بالنيابة عن
  لاعب آخر.
</Tip>

<h2 id="work-with-your-game-data">
  اعمل مع بيانات لعبتك
</h2>

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

<Frame caption="يولّد Tools → Flock → Sync Schemas ملفات مُحدَّدة الأنواع من مخطّطاتك أنت.">
  <img src="https://mintcdn.com/qwacks/xJEjgQCFVIWLhvHB/images/sdk/unreal/codegen-menu.png?fit=max&auto=format&n=xJEjgQCFVIWLhvHB&q=85&s=fd967d26f2e71014eeb8e3322bac8e61" alt="قائمة Tools تعرض Resolve Game Version وSync Schemas وClean Generated" width="246" height="927" data-path="images/sdk/unreal/codegen-menu.png" />
</Frame>

وتصبح قراءة إعدادٍ ما **عقدة واحدة** تحمل معها عملية الجلب والمعرّف:

<Frame caption="تجلب Get Gameplay وتحوّل وتُعيد بنية مُحدَّدة الأنواع — فكّكها للحصول على أطراف حقيقية.">
  <img src="https://mintcdn.com/qwacks/xJEjgQCFVIWLhvHB/images/sdk/unreal/codegen-get-config.png?fit=max&auto=format&n=xJEjgQCFVIWLhvHB&q=85&s=1a823c39016fda2108f524d62d8c03b2" alt="عقدة Get Gameplay المُولَّدة تُغذّي عقدة Break" width="634" height="345" data-path="images/sdk/unreal/codegen-get-config.png" />
</Frame>

وتغيير بيانات لاعب يجري هكذا: `Get` ← **Set members in struct** من المحرّك ← `Save`:

<Frame caption="تُعيد Get معرّف الصف إلى جانب البنية، لأن Save يحتاج إليه.">
  <img src="https://mintcdn.com/qwacks/xJEjgQCFVIWLhvHB/images/sdk/unreal/codegen-get-save.png?fit=max&auto=format&n=xJEjgQCFVIWLhvHB&q=85&s=ea937a651f7ff7582c7c5110de5a1322" alt="عقدة Get Player Level تُغذّي Set members ثم Save Player Level" width="752" height="352" data-path="images/sdk/unreal/codegen-get-save.png" />
</Frame>

أشّر على الأعضاء الذين تريد كتابتهم. أما غير المؤشَّر عليهم فيحتفظون بما جلبته `Get`.

<Frame caption="التأشير على عضو يُظهر طرفه — والأعضاء غير الملموسين يبقون كما كانوا تمامًا.">
  <img src="https://mintcdn.com/qwacks/xJEjgQCFVIWLhvHB/images/sdk/unreal/codegen-set-members-details.png?fit=max&auto=format&n=xJEjgQCFVIWLhvHB&q=85&s=a6bb1a356f97b61ede4981cdab07164b" alt="لوحة Details لعقدة Set members in struct" width="1581" height="655" data-path="images/sdk/unreal/codegen-set-members-details.png" />
</Frame>

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

<Frame caption="اشترِ باختيار العنصر — فالمعرّف مخبوز ولا يمكن أن تخطئ في كتابته.">
  <img src="https://mintcdn.com/qwacks/xJEjgQCFVIWLhvHB/images/sdk/unreal/shop-purchase.png?fit=max&auto=format&n=xJEjgQCFVIWLhvHB&q=85&s=7d62008138e464eab95c97c1be0943a7" alt="عقدة Flock Purchase في رسم Blueprint" width="333" height="237" data-path="images/sdk/unreal/shop-purchase.png" />
</Frame>

<h3 id="prefer-c++">
  تفضّل C++؟
</h3>

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

<Frame caption="يحدّد Codegen Target ما تُصدِره المزامنة. وBlueprint هو الافتراضي.">
  <img src="https://mintcdn.com/qwacks/xJEjgQCFVIWLhvHB/images/sdk/unreal/codegen-target-setting.png?fit=max&auto=format&n=xJEjgQCFVIWLhvHB&q=85&s=f53e64af46d79160379f51d266df69db" alt="إعداد Codegen Target في Project Settings" width="1596" height="1104" data-path="images/sdk/unreal/codegen-target-setting.png" />
</Frame>

```cpp theme={null}
FFlockGenerated::GetPlayerLevel(this,
    [this](TFlockResult<FPlayerLevelTemplate> Result, const FString& RowId)
    {
        if (!Result.bSuccess) { return; }

        FPlayerLevelTemplate Progress = Result.Value;
        Progress.Level.Stage = 5;
        FFlockGenerated::SavePlayerLevel(this, RowId, Progress, nullptr);
    });

FFlockGenerated::Purchase(this, EFlockShopItemId::GemPack, OnBought);
FFlockGenerated::AddFunds(this, EFlockCurrencyId::Gold, 100, OnCredited);
```

ويستخدم المشروع الواحد أحد الهدفين لا كليهما. وبنى C++ المُولَّدة من نوع `BlueprintType`، فتظل
الرسوم ترى أنواعك بعد التبديل.

<h2 id="explore-features">
  استكشف الميزات
</h2>

<CardGroup cols={2}>
  <Card title="اللاعبون والمصادقة" icon="user" href="/ar/guides/players-and-auth" />

  <Card title="بيانات اللاعب" icon="database" href="/ar/guides/player-data" />

  <Card title="المتاجر والمخزون" icon="cart-shopping" href="/ar/guides/shops-and-inventory" />

  <Card title="الإعدادات عن بُعد" icon="sliders" href="/ar/guides/remote-config" />

  <Card title="التحليلات والأحداث" icon="chart-line" href="/ar/guides/analytics-and-events" />
</CardGroup>

<h2 id="advanced-settings">
  الإعدادات المتقدّمة
</h2>

يضبط Project Settings أيضًا التحليلات، وإعادات محاولة HTTP، وذاكرة وضع عدم الاتصال، ومسارات توليد
الشيفرة. والقيم الافتراضية معقولة — فلا تغيّرها إلا عند الحاجة.

وتفعيل **Enable Debug Logs** يتتبّع كل اتصال بالشبكة ضمن الفئة `LogFlock`، ويذكر كل سطر مصدر
الاستدعاء لتميّز رسم Blueprint من شيفرة C++:

```
[Flock SDK] -> GET .../v1/player_data?player_id=01KY... [Blueprint 'bpTest']
[Flock SDK] <- 200 GET .../v1/player_data?player_id=01KY... (34 ms, 2060 bytes) [Blueprint 'bpTest']
```

<h2 id="offline-caching">
  التخزين المؤقّت دون اتصال
</h2>

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

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

<h2 id="error-handling">
  معالجة الأخطاء
</h2>

يردّ كل استدعاء بقيمة `TFlockResult<T>` بدل أن يرمي استثناءً — فـUnreal تُبنى مع تعطيل الاستثناءات.
تحقّق من `bSuccess`، ثم اقرأ `Value` أو `Error`.

```cpp theme={null}
if (!Result.bSuccess && Result.Error.Code == EFlockErrorCode::ShopInsufficientFunds)
{
    // The server declined — not enough funds.
}
```

وفي Blueprint، لكل عقدة غير متزامنة طرف **On Failure** يحمل `Error` نفسه، وتحوّله
`UFlockErrorLibrary` إلى نص للعرض أو إلى تحقّق من خطأ مُرمَّز دون مطابقة نصوص.

<Tip>
  تجد المرجع الكامل للواجهة البرمجية، وأدلّة كل ميزة، وتفاصيل توليد الشيفرة في
  [ملف README الخاص بالحزمة](https://github.com/QwackStack/FlockUnrealSdk#readme).
</Tip>
