إتقان الأحداث عن بُعد في برمجة روبلوكس: بناء ميزات متعددة اللاعبين آمنة

إتقان الأحداث عن بُعد في برمجة روبلوكس: بناء ميزات متعددة اللاعبين آمنة

تتيح الأحداث عن بُعد في برمجة روبلوكس للعميل والخادم إرسال الرسائل لبعضهما البعض دون انتظار رد. استخدمها لطلبات مثل "حاول شراء هذا العنصر" أو لتحديثات يوافق عليها الخادم مثل "أظهر هذا التأثير للاعبين القريبين". القاعدة الأساسية في التصميم هي أن الحدث عن بُعد يحمل رسالة، لكنه لا يجعل الطلب موثوقًا. يجب على الخادم تحديد ما إذا كان الإجراء مسموحًا به وتحديث حالة اللعبة المهمة بنفسه.

ما يفعله الحدث عن بُعد

A RemoteEventهو كائن اتصال غير متزامن أحادي الاتجاه. يستدعي المرسل دالةً لإطلاقه، ويقوم الطرف المُستقبِل بتشغيل معالج أحداث متصل. لا يُعيد استدعاء RemoteEvent قيمةً. وهو موثوق ومنظم طالما بقي المُستقبِل متصلاً، ولكنه ليس آلية طلب واستجابة.

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

اتجاهطريقة الإرسالالمُستقبِلالاستخدام النموذجي
من العميل إلى الخادمFireServer(...)OnServerEventاطلب إجراءً أو أرسل ملاحظات اللاعب
خادم لعميل واحدFireClient(player, ...)OnClientEventإرسال إشعار أو تحديث خاص
خادم لكل عميل متصلFireAllClients(...)OnClientEventبث تأثير مشترك أو إعلان

عندما يُطلق أحد العملاء حدثًا عن بُعد، يُمرر Roblox كائن اللاعب Playerكوسيط أول إلى دالة الاستدعاء الخاصة بالخادم OnServerEvent. لا تحاول تمرير هذا الوسيط أو اختياره بنفسك.

أنشئ حدث شراء سلع آمن

يربط هذا المثال المكون من أربعة أجزاء زرًا في واجهة المستخدم الرسومية بمنطق الشراء الخاص بالخادم. في مستكشف الملفات، أنشئ عنصرًا RemoteEventباسم ReplicatedStorage`RemoteEvent` وسمّه `RemoteEvent` PurchaseItem. أضف نصًا برمجيًا محليًا (LocalScript) أسفل زر نصي (TextButton) أو زر صورة (ImageButton). أضف نصًا برمجيًا عاديًا (Script) في ` ServerScriptServiceRemoteEvent`. إذا كنت تستخدم أيضًا مثال التأثير أدناه، فأنشئ حدثًا عن بُعد ثانيًا باسم `RemoteEvent` EffectEventفي ` RemoteEvent` ReplicatedStorage. يفترض هذا المثال أن لعبتك تُنشئ بالفعل leaderstats.Cashقيمة مُدارة من قِبل الخادم ولديها رمزها الخاص بمنح المخزون.

الخطوة 1: إرسال نية اللاعب فقط

يطلب العميل شراء منتج عن طريق إرسال معرّف المنتج في الكتالوج. Activatedيعمل هذا الحدث متعدد المنصات مع إدخال الماوس واللمس ووحدة التحكم على زر واجهة المستخدم الرسومية.

-- LocalScript parented to a TextButton or ImageButton
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local purchaseItem = ReplicatedStorage:WaitForChild("PurchaseItem")
local button = script.Parent

button.Activated:Connect(function()
    purchaseItem:FireServer("SmallHealthPotion")
end)

لا يرسل العميل السعر، أو رصيده النقدي، أو تعليمات بمنح نفسه سلعة. هذه القيم والقرارات تخص الخادم.

الخطوة الثانية: التحقق من صحة الطلب ومعالجته على الخادم

احتفظ بقائمة العناصر وأسعارها في سكربت خاص بالخادم أو وحدة نمطية خاصة بالخادم فقط. يقوم المعالج التالي بفحص نوع الطلب، ويقبل فقط مدخلات الكتالوج المعروفة، ويطبق فترة انتظار لكل لاعب، ويتحقق من رصيد الخادم النقدي قبل خصم أي مبلغ.

-- Script in ServerScriptService
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local purchaseItem = ReplicatedStorage:WaitForChild("PurchaseItem")

local catalog = {
    SmallHealthPotion = { price = 25 },
}

local lastRequestAt = {}
local COOLDOWN_SECONDS = 0.25

purchaseItem.OnServerEvent:Connect(function(player, itemId)
    if typeof(itemId) ~= "string" or #itemId > 40 then
        return
    end

    local item = catalog[itemId]
    if not item then
        return
    end

    local now = os.clock()
    local previous = lastRequestAt[player.UserId] or 0
    if now - previous < COOLDOWN_SECONDS then
        return
    end
    lastRequestAt[player.UserId] = now

    local leaderstats = player:FindFirstChild("leaderstats")
    local cash = leaderstats and leaderstats:FindFirstChild("Cash")
    if not cash or not cash:IsA("IntValue") or cash.Value < item.price then
        return
    end

    cash.Value = cash.Value - item.price
    -- Grant the item through your server-owned inventory system here.
end)

Players.PlayerRemoving:Connect(function(player)
    lastRequestAt[player.UserId] = nil
end)

قم بتكييف عملية التحقق من القيمة مع نظام القيمة أو العملة المستخدم في لعبتك. إذا كانت عملية الشراء تعتمد على موقع المتجر، أو حالة اللاعب (على قيد الحياة)، أو مهمة، أو فتح ميزة، فتحقق من هذا الشرط على الخادم أيضًا. اجعل عملية التحقق وتغيير الحالة متلازمتين، وتجنب التنازل بين التحقق من الرصيد وخصم السعر.

الخطوة 3: دع الخادم يختار النتيجة

بالنسبة للإجراءات الأخرى غير عمليات الشراء، اتبع النمط نفسه: يُبلغ العميل عن المدخلات، ويتحقق الخادم من صحتها قبل تغيير الحالة المشتركة. على سبيل المثال، بعد أن يؤكد نص الخادم أن التعويذة مفتوحة وأن موضع الهدف صالح، يمكنه بث موضع التأثير.

-- Server Script, after validating the action
local effectEvent = ReplicatedStorage:WaitForChild("EffectEvent")
effectEvent:FireAllClients(serverApprovedPosition)

استخدم هذه الطريقة FireClient(player, ...)عندما يحتاج لاعب واحد فقط إلى التحديث. استخدمها FireAllClients(...)عندما يحتاج جميع العملاء المتصلين إلى التحديث. لاستبعاد لاعب معين، أرسل التحديث صراحةً إلى المستلمين المقصودين؛ FireAllClientsExcept()فهي ليست طريقة RemoteEvent.

الخطوة الرابعة: تقديم ملاحظات العميل فقط

يمكن لبرنامج LocalScript الاستماع إلى التحديث المعتمد وعرض انفجار جسيمات أو صوت أو أي عرض مؤقت آخر. احتفظ بالتأثيرات المرئية فقط على جهاز المستخدم عندما لا تؤثر على أسلوب اللعب.

-- LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local effectEvent = ReplicatedStorage:WaitForChild("EffectEvent")

effectEvent.OnClientEvent:Connect(function(position)
    if typeof(position) ~= "Vector3" then
        return
    end

    -- Play a local visual effect at the server-approved position.
end)

يتحقق هذا المثال من نوع البيانات المُستلمة بشكل وقائي. لا ينبغي للعميل أن يقرر ما إذا كانت التعويذة قد أصابت الهدف، أو أنها ستُلحق ضررًا، أو أنها ستُنشئ مكافأة؛ فهذه قرارات خاصة بالخادم.

حدث عن بعد، أو وظيفة عن بعد، أو حدث عن بعد غير موثوق به؟

كائنالتواصلاختره عندما
RemoteEventغير متزامن، أحادي الاتجاه؛ لا يتم إرجاع أي استجابةيجب عليك إرسال طلب إجراء أو إشعار أو تحديث
RemoteFunctionاتصال ثنائي الاتجاه؛ يتوقف المتصل مؤقتًا حتى يتلقى ردًا.يحتاج المتصل فعلاً إلى قيمة مُعادة قبل المتابعة
UnreliableRemoteEventغير متزامن، أحادي الاتجاه، بدون ضمان للتسليم أو الطلبيمكن حذف البيانات المتكررة وغير الحرجة دون الإضرار بحالة اللعبة

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

قائمة التحقق الأمنية لـ RemoteEvent

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

تعتبر إرشادات أمان Roblox المدخلات عن بُعد غير موثوقة. يُعد التحقق من صحة البيانات عبر الخادم أمرًا ضروريًا حتى عندما يتحقق LocalScript الخاص بك بالفعل من نفس القيم. بالنسبة للمشتريات ذات القيمة العالية أو المخزون الدائم، استخدم نفس عمليات التحقق الموثوقة من الخادم في منطق حفظ البيانات والمعاملات.

اختبر وحلّ مشاكل RemoteEvents

  • "لم يتم العثور على الحدث البعيد": تحقق من الاسم والأصل في المستكشف، واستخدمه WaitForChild()عندما يحتاج البرنامج النصي إلى انتظار النسخ المتماثل.
  • لا يتم تشغيل المعالج أبدًا: تأكد من أن رمز التشغيل موجود في LocalScript، وأن رمز الاستقبال موجود في Server Script، وكلاهما يشير إلى نفس مثيل RemoteEvent.
  • يرفض الخادم عملية الشراء: تحقق من مُعرّف العنصر، وقيمة العملة، وصلاحيات الوصول على جانب الخادم. لا تُصحّح عدم التطابق بالاعتماد على السعر المُقدّم من العميل.
  • تظهر التأثيرات للاعب واحد فقط: تحقق مما إذا كنت قد استخدمت FireClient()بدلاً من FireAllClients()، أو ما إذا كان لكل عميل مستمع OnClientEvent.
  • قد تتصرف الرسائل بشكل غير متوقع: قم بتوصيل المستمع قبل إرسالها. يقوم Roblox بتخزين الرسائل مؤقتًا في قائمة الانتظار عندما لا يكون هناك مستمع متصل، ولكن هذه القائمة محدودة. إذا كانت صحة العملية تعتمد على ترتيب استدعاءات RemoteEvent وRemoteFunction، فأضف تسلسلك الخاص؛ لا يضمن Roblox ترتيبها النسبي.

استخدم وضع اختبار الخادم والعملاء في Studio لتشغيل خادم مع عدة لاعبين افتراضيين. تحقق من نافذة الإخراج على كلا الجانبين، ثم اختبر سلوك الانضمام والمغادرة وجرّب إدخالات غير صحيحة. يُعد اختبار العميل والخادم في Studio طريقة أفضل للتحقق من سلوك اللعب الجماعي من الاعتماد فقط على جلسة لعب فردية.

مراجع روبلوكس الرسمية

اترك تعليقاً

دليل الزهور التي تعشق الشمس

دليل الزهور التي تعشق الشمس

شرحٌ لأنواع الزهور التي تحب الشمس، مع خيارات النباتات، وخطوات الزراعة، ونصائح العناية، والأخطاء التي يجب تجنبها، وإجابات الأسئلة الشائعة للحصول على حديقة أكثر صحة.

كيفية إيقاف إشعارات الجوهر الأزرق في لعبة ليج أوف ليجيندز

كيفية إيقاف إشعارات الجوهر الأزرق في لعبة ليج أوف ليجيندز

لا يوجد في لعبة League of Legends خيار موثق لتفعيل الإشعارات الخاصة بـ Blue Essence فقط. تعرّف على كيفية كتم إشعارات المحتوى الجديد، وتمييز نوافذ مكافآت المهام، وتعديل لافتات نظام التشغيل Windows.

أفضل مُضاعِف حساسية عمودية في لعبة ببجي: ابدأ من 1.0

أفضل مُضاعِف حساسية عمودية في لعبة ببجي: ابدأ من 1.0

ابدأ بـ 1.0 لحساسية PUBG PC العمودية، ثم تعلم متى يمكن أن تساعد 1.1-1.2 في التحكم في الارتداد وكيفية الحكم على المفاضلة في دقة التصويب.

كيفية تغيير ردود عجلة الدردشة في لعبة دوتا 2

كيفية تغيير ردود عجلة الدردشة في لعبة دوتا 2

تعلم كيفية تخصيص عبارات عجلة الدردشة في لعبة Dota 2، واختيار العجلات الأساسية أو الثانوية، والتحقق من مفاتيح الاختصار، وتجنب الخلط بين الدردشة السريعة وخطوط صوت البطل.

كيفية ربط القفز والوثب بمفاتيح منفصلة في لعبة ببجي

كيفية ربط القفز والوثب بمفاتيح منفصلة في لعبة ببجي

افصل عناصر التحكم في القفز والتسلق في لعبة PUBG على الكمبيوتر لتجنب التسلق العرضي. ابحث عن اختصارات لوحة المفاتيح، وخصص مفاتيح مخصصة، واحل التعارضات، واختبر النتيجة.

أفضل إعدادات اختصارات لوحة المفاتيح لخاصية السحب والتحديد الكلاسيكية في لعبة ستار كرافت: ريماسترد

أفضل إعدادات اختصارات لوحة المفاتيح لخاصية السحب والتحديد الكلاسيكية في لعبة ستار كرافت: ريماسترد

قارن بين تخطيطات المفاتيح المختصرة الافتراضية والمخصصة البسيطة والمضغوطة للعبة StarCraft: Remastered، مع مدخلات التحديد العملية وتوصيات مجموعات التحكم.

أفضل إعدادات النطاق الديناميكي الصوتي لسماعات الرأس في لعبة Dota 2

أفضل إعدادات النطاق الديناميكي الصوتي لسماعات الرأس في لعبة Dota 2

اعثر على أفضل إعداد لنطاق الصوت الديناميكي لسماعات الرأس في لعبة Dota 2، وتعرف على متى يكون الضغط مفيدًا، وقم بضبط الصوت للحصول على إشارات واضحة دون معارك جماعية صاخبة للغاية.

كيفية إصلاح خطأ حرج عند تشغيل لعبة League of Legends

كيفية إصلاح خطأ حرج عند تشغيل لعبة League of Legends

قم بإصلاح الأخطاء الحرجة في لعبة League of Legends عند التشغيل عن طريق فحص الطبقات، وإصلاح ملفات اللعبة، وتحديث برامج التشغيل، واختبار تعارضات التكوين والخدمة.

أفضل حساسية للماوس في لعبة StarCraft: Remastered لنقرات دقيقة

أفضل حساسية للماوس في لعبة StarCraft: Remastered لنقرات دقيقة

ابدأ بخط أساسي عملي لسرعة الماوس في لعبة StarCraft: Remastered، ثم اضبط الحساسية لاختيار الوحدات بدقة، والنقر على الخريطة المصغرة، والتمرير.

كيفية إصلاح مشكلة تجمد لعبة Dota 2 عند ظهور رسالة "جارٍ الاتصال بمنسق اللعبة"

كيفية إصلاح مشكلة تجمد لعبة Dota 2 عند ظهور رسالة "جارٍ الاتصال بمنسق اللعبة"

حل مشكلة توقف لعبة Dota 2 عند الاتصال بمنسق اللعبة. تحقق من وجود مشكلة في الخدمة، وأعد تشغيل Steam، واختبر اتصالك بالشبكة، وتحقق من ملفات اللعبة.