وكل عملية شراء تُنشئ مدخلها الخاص، فشراء العنصر نفسه مرتين يمنحك مدخلين. ويحمل كل مدخل حقلَي
status وused_at يضبطهما الخادم، وكلاهما للقراءة فقط — فلا توجد دالة في أيٍّ من حزمتَي التطوير
تُعلّم المدخل بأنه مستخدَم.عملية الشراء آمنة ماليًا. فهي لا تُعاد أبدًا بعد فشل غامض ولا تُصفّ في طابور عند انقطاع
الاتصال، ومن ثمّ لا يمكن أن تخصم مرتين. ويُجلب المخزون دائمًا محدَّثًا من الخادم؛ أما الكتالوج
فمُخزَّن مؤقتًا ويُقدَّم دون اتصال، لذا عامِل أي سعر معروض على أنه استرشادي حتى تنجح عملية الشراء.
تمنح عمليات الشراء محتوياتها من جهة الخادم. أعطِ عنصر المتجر نوع حزمة عملة أو
عنصر قابل للاستهلاك وأرفق به مكافآت، فيضيف الخادم المكافأة إلى رصيد اللاعب ضمن العملية نفسها
التي تخصم السعر. ولا يمكن أن يقع أحد الشقّين دون الآخر، ولا تقرّر اللعبة ما الذي مُنح — لذا لا
يستطيع تطبيق معدَّل أن يمنح نفسه شيئًا، ولا يترك انقطاع الاتصال اللاعب مخصومًا منه دون مقابل.أما العنصر القياسي فهو السلوك الأقدم ولا يزال الافتراضي: يخصم السعر ويسجّل مدخل مخزون تفسّره
لعبتك كما تشاء.
لوحة التحكم
Unity
Unreal
اضبط المتاجر وعناصرها لإصدار لعبة من لوحة التحكم — حدّد الأسعار والعملات ومدى التوفّر.
اضبط المتاجر والعناصر من لوحة التحكم.
استخدم دوال المتجر في حزمة التطوير لسرد المتاجر والعناصر المتاحة لإصدار لعبتك، ثم نفّذ عملية
شراء لصالح اللاعب المسجَّل دخوله. وتعمل PurchaseAsync افتراضيًا على اللاعب المسجَّل دخوله،
وتُعيد كل ما أنتجته عملية الشراء — ما مُنح، والمحفظة بعد المنح، ومدخل المخزون إن أنشأ العنصر
واحدًا.
PurchaseResult purchase = await FlockClient.Instance.Shop.PurchaseAsync("shop-item-id");foreach (ShopItemReward reward in purchase.Granted) Debug.Log($"+{reward.Amount} {reward.Code}"); // مثلًا +500 GoldPlayerData wallet = purchase.Wallet; // الرصيد بعد المنحPlayerInventory entry = purchase.Inventory; // null في حالة حزمة العملةPaginatedResponse<PlayerInventory> owned = await FlockClient.Instance.Shop.GetPlayerInventoryAsync();
تُضيف حزمة العملة قيمتها إلى المحفظة مباشرة ولا تنشئ مدخل مخزون. أما العنصر القابل للاستهلاك
فيفعل العكس: يستقرّ في المخزون ويمنح مكافأته عند استهلاك اللاعب له.
ولا تكون Granted قيمتها null أبدًا — فالعنصر الذي لا يمنح شيئًا يُعيد قائمة فارغة. ولعرض ما
سيمنحه العنصر قبل أن يشتريه اللاعب، اقرأ ShopItem.Rewards من الفهرس.وترمي عملية الشراء المرفوضة استثناءً — التقط FlockException وتحقّق من ErrorCode بحثًا عن
FlockErrorCode.ShopInsufficientFunds لتمييز «الرصيد غير كافٍ» عن فشل الشبكة. والاستهلاك يحمل
الضمان نفسه الذي يحمله الشراء: يُظهر الفشلَ الملتبس بدل إعادة إرساله، فلا تُمنح المكافأة مرتين.
تصفّح باستخدام عقد Flock | Shop، أو مزوّد المتجر في C++. ويمكن قراءة حقلَي data وstats
الحرَّين لأي عنصر عبر مسار منقوط، فلا حاجة إلى عقدة لتحليل JSON.وتُكمل Purchase بكل ما أنتجته عملية الشراء — ما مُنح، والمحفظة بعد المنح، ومدخل المخزون إن
أنشأ العنصر واحدًا.
اشترِ باختيار عنصر مُولَّد — المعرّف مضمَّن سلفًا ويستحيل أن تخطئ في كتابته.
Sdk->GetShopProvider()->Purchase(ItemId, [](TFlockResult<FFlockPurchaseResult> Bought) { if (!Bought.bSuccess) { if (Bought.Error.ErrorCode == EFlockErrorCode::ShopInsufficientFunds) { // The server declined — show the player, don't retry. } return; } for (const FFlockShopItemReward& Reward : Bought.Value.Granted) { // e.g. +500 GOLD. Compare against the constant, never a typed-out "currency": // the server owns that set and can add kinds. if (Reward.Type == FlockShopItemRewardTypes::Currency) { /* Reward.Code, Reward.Amount */ } } // Both may legitimately be absent, so ask rather than testing the Id yourself. if (Bought.Value.HasWallet()) { /* Bought.Value.Wallet — balances after the grant */ } if (Bought.Value.HasInventoryRow()) { /* Bought.Value.Inventory — the row the player owns */ } });
تُضيف حزمة العملة قيمتها إلى المحفظة مباشرة ولا تنشئ مدخل مخزون — فتعود HasInventoryRow() بالقيمة
false، وهي حالة «لا مدخل» المشروعة لا خطأً. أما العنصر القابل للاستهلاك فيفعل العكس: يستقرّ في
المخزون ويمنح مكافأته عند استهلاك اللاعب له.
وفي Blueprint هاتان العقدتان هما Flock Purchase وFlock Consume Inventory Item. فكّك نتيجة
الشراء للحصول على Inventory وGranted وWallet، واستخدم العقد الصرفة بدل فحص الحقول بنفسك:
Has Inventory Row قبل قراءة المدخل، وIs Currency Reward للتفرّع على نوع المكافأة. ومقارنة
Type بنصّ مكتوب يدويًا هي الخطأ الوحيد الجدير بالاحتراس منه — إذ يُقرأ الخطأ المطبعي على أنه
«ليست مكافأة عملة» فيتخطّى المنح بصمت.ولا تكون Granted قيمتها null أبدًا — فالعنصر الذي لا يمنح شيئًا يُعيد قائمة فارغة. ولعرض ما
سيمنحه العنصر قبل أن يشتريه اللاعب، اقرأ Rewards من عنصر الفهرس.وتُفشِل عملية الشراء المرفوضة النتيجةَ بدل أن ترمي استثناءً — تحقّق من Error.Code بحثًا عن
EFlockErrorCode::ShopInsufficientFunds لتمييز «الرصيد غير كافٍ» عن فشل الشبكة. والاستهلاك يحمل
الضمان نفسه الذي يحمله الشراء: يُظهر الفشلَ الملتبس بدل إعادة إرساله، فلا تُمنح المكافأة مرتين.
راجع العملات والمحافظ للاطّلاع على الأرصدة التي تقوم عليها
عمليات الشراء.