تتيح لك بنية بيانات الخريطة المرتبة في مخازن الذاكرة تخزين بيانات متكررة في الذاكرة كأزواج من القيم والمفاتيح مع مفتاح فرز اختياري والحفاظ على ترتيب معين بناءً على مفاتيح الفرز والمفاتيح. على عكس قوائم الانتظار، فإن ترتيب المفاتيح التي تدخل الخريطة لا يحدد ترتيب المعالجة، مما يجعل الخرائط المرتبة مفيدة لتنظيم البيانات بناءً على الفرز لتنفيذ الكيانات داخل اللعبة من أجل الارتباط مثل لوائح المتصدرين والمزادات عبر الخوادم.
الحدود
بالإضافة إلى حدود حجم هيكل البيانات، فإن الخرائط المرتبة لها حد حجم مفتاح يبلغ 128 حرفًا، وحد حجم قيمة يبلغ 32 كيلو بايت، وحد حجم مفتاح فرز يبلغ 128 حرفًا.
إذا كنت بحاجة إلى تخزين بيانات تتجاوز هذا الحد للعبتك، يمكنك اعتماد تقنية التقسيم لتقسيمها وتوزيعها عبر بادئة المفتاح إلى هياكل بيانات متعددة. يمكن أن يساعد تقسيم مخازن الذاكرة أيضًا في تحسين قابليتها للتوسع.
الحصول على خريطة مرتبة
للحصول على خريطة مرتبة، استدعِ MemoryStoreService:GetSortedMap() مع اسم تريد تعريفه للخريطة. الاسم عالمي ضمن اللعبة، لذا يمكنك الوصول إلى نفس الخريطة المرتبة في أي سكربت باستخدام الاسم.
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")بعد الحصول على خريطة مرتبة، يمكنك استدعاء أي من الوظائف التالية:
| الوظيفة | الإجراء |
|---|---|
| MemoryStoreSortedMap:SetAsync() | أضف مفتاحًا جديدًا أو تجاوز القيمة و/أو مفتاح الفرز إذا كان المفتاح موجودًا مسبقًا. |
| MemoryStoreSortedMap:GetAsync() | اقرأ مفتاحًا معينًا. |
| MemoryStoreSortedMap:GetRangeAsync() | اقرأ جميع المفاتيح الموجودة أو نطاق محدد منها. |
| MemoryStoreSortedMap:UpdateAsync() | حدث قيمة مفتاح و/أو مفتاح فرز بعد استرجاعه من خريطة مرتبة. |
| MemoryStoreSortedMap:RemoveAsync() | إزالة مفتاح من الخريطة المرتبة. |
| MemoryStoreSortedMap:GetSizeAsync() | احصل على عدد العناصر في الخريطة المرتبة. |
إضافة أو تجاوز البيانات
لإضافة مفتاح جديد أو تجاوز القيمة أو مفتاح الفرز لمفتاح في الخريطة المرتبة، استدعِ MemoryStoreSortedMap:SetAsync() مع اسم المفتاح، وقيمته، ومدة انتهاء بالثواني ومفتاح فرز اختياري. يتم تنظيف الذاكرة تلقائيًا بمجرد انتهاء مدة المفتاح. أقصى مدة انتهاء هي 3,888,000 ثانية (45 يومًا). يجب أن يكون مفتاح الفرز، إذا تم توفيره، رقمًا صالحًا (صحيح أو نقطة عائمة) أو سلسلة نصية.
في ترتيب الفرز لمفاتيحك، يكون لمفتاح الفرز أسبقية على المفتاح. على سبيل المثال، عند الفرز بترتيب تصاعدي، يتم فرز مفاتيح الفرز الرقمية أولاً، تليها مفاتيح الفرز النصية، تليها العناصر التي ليس لها مفتاح فرز. يتم فرز جميع العناصر ذات مفاتيح الفرز الرقمية حسب مفتاح الفرز، إذا كان مفتاح الفرز لعنصرين متساويًا، فيتم فرزهما حسب المفتاح. بالمثل، يتم فرز جميع العناصر ذات مفاتيح الفرز النصية حسب مفتاح الفرز، إذا كان مفتاح الفرز لعنصرين متساويًا، فيتم فرزهما حسب المفتاح. يتم فرز جميع العناصر التي ليس لها مفتاح فرز حسب المفتاح فقط.
إليك مثال لبعض البيانات مرتبة بترتيب تصاعدي -
{key: "player1", value: someValue1, sortKey: -1}
{key: "player2", value: someValue2, sortKey: 0}
{key: "player4", value: someValue3, sortKey: 1}
{key: "player5", value: someValue4, sortKey: 1}
{key: "player3", value: someValue5, sortKey: 3.14}
{key: "player6", value: someValue6, sortKey: "someString"}
{key: "player0", value: someValue7}
{key: "player7", value: someValue8}لاحظ كيف أن player0 يتم فرزه بعد جميع المفاتيح التي تحمل مفتاح فرز. player6 يتم فرزه بعد جميع المفاتيح التي تحمل مفتاح فرز رقمي. player4 و player5 لهما نفس مفتاح الفرز، لذا يتم فرزهما بترتيب تصاعدي حسب المفتاح.
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local setSuccess, _ = pcall(function()
return sortedMap:SetAsync("User_1234", 1000, 30, 3.14152)
end)
if setSuccess then
print("تمت العملية بنجاح.")
endالحصول على البيانات
يمكنك إما الحصول على قيمة البيانات ومفتاح الفرز المرتبط بمفتاح معين، أو الحصول على قيم متعددة ومفاتيح فرز لمفاتيح ضمن نطاق.
الحصول على البيانات بمفتاح واحد
للحصول على قيمة ومفتاح فرز مرتبط بمفتاح واحد من الخريطة المرتبة، استدعِ MemoryStoreSortedMap:GetAsync() مع اسم المفتاح.
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local setSuccess, _ = pcall(function()
return sortedMap:SetAsync("User_1234", 1000, 30, 3.14152)
end)
if setSuccess then
print("تمت العملية بنجاح.")
end
local item
local getSuccess, getError = pcall(function()
item = sortedMap:GetAsync("User_1234")
end)
if getSuccess then
print(item)
else
warn(getError)
endالحصول على البيانات بمفاتيح متعددة
للحصول على البيانات لعدة مفاتيح من الخريطة المرتبة كعملية واحدة، استدعِ MemoryStoreSortedMap:GetRangeAsync(). تقوم هذه الوظيفة بإدراج جميع المفاتيح الموجودة بشكل افتراضي، ولكن يمكنك تعيين الحدود العليا والسفلى لنطاق المفاتيح. على سبيل المثال، يسترجع نموذج الكود التالي ما يصل إلى 20 عنصرًا بدءًا من بداية الخريطة المرتبة، مع مفاتيح أكبر من أو تساوي 10، ومفاتيح فرز أكبر من أو تساوي 100، ومفاتيح أقل من أو تساوي 50، ومفاتيح فرز أقل من أو تساوي 500.
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local lowerBound = {}
lowerBound["key"] = "10"
lowerBound["sortKey"] = 100
local upperBound = {}
upperBound["key"] = "50"
upperBound["sortKey"] = 500
-- احصل على ما يصل إلى 20 عنصرًا بدءًا من البداية
local getSuccess, items = pcall(function()
return sortedMap:GetRangeAsync(
Enum.SortDirection.Ascending, 20, lowerBound, upperBound)
end)
if getSuccess then
for _, item in items do
print(item.key)
print(item.sortKey)
end
endتحديث البيانات
لاسترجاع القيمة ومفتاح الفرز لمفتاح من الخريطة المرتبة وتحديثه، استدعِ MemoryStoreSortedMap:UpdateAsync() مع اسم المفتاح، ودالة رد النداء لتحديث القيمة ومفتاح الفرز لهذا المفتاح، ومدة انتهاء بالثواني. أقصى مدة انتهاء هي 3,888,000 ثانية (45 يومًا).
بالنسبة لمعظم الألعاب، يمكن لعدة خوادم تحديث نفس المفتاح في وقت واحد وتغيير القيمة. كما أن UpdateAsync() يقوم دائمًا بتعديل أحدث قيمة قبل التحديث، لذا يجب عليك استخدامه لقراءة أحدث قيمة كمدخل لدالة رد النداء الخاصة بك.
على سبيل المثال، نموذج الكود التالي يقوم بتحديث النتيجة في قائمة المتصدرين للاعب. تحسب النتيجة كالتالي الأKills / الأDeaths. تضمن UpdateAsync() أن يتم تحديث الأKills و الأDeaths بالقيم الأكثر حداثة حتى لو كانت عدة خوادم ألعاب تقوم بتحديث نفس العنصر في نفس الوقت. تعتبر الأKills و الأDeaths للقيم تزيد بصفة مستمرة ويمكن بالتالي أن تزيد فقط في القيمة في جلسة واحدة.
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("Leaderboard")
local function updateLeaderboard(itemKey, killsToAdd, deathsToAdd)
local success, newStats, newScore = pcall(function()
return sortedMap:UpdateAsync(itemKey, function(playerStats, playerScore)
playerStats = playerStats or { kills = 0, deaths = 0 }
playerStats.kills += killsToAdd
playerStats.deaths += deathsToAdd
if playerStats then
-- `playerScore` هو مفتاح الفرز المستخدم لفرز العناصر في الخريطة
playerScore = playerStats.kills / math.max(playerStats.deaths, 1)
return playerStats, playerScore
end
return nil
end, 30)
end)
if success then
print(newStats)
print(newScore)
end
endتكون زمن الانتظار لـ UpdateAsync() مشابهًا لـ GetAsync() و SetAsync() ما لم يكن هناك تنافس.
عندما يحدث تنافس، يقوم النظام تلقائيًا بإعادة المحاولة للعملية حتى يحدث أحد هذه الثلاثة: تنجح العملية، أو ترجع دالة رد النداء nil، أو تصل إلى الحد الأقصى من محاولات الإعادة. إذا وصل النظام إلى الحد الأقصى من محاولات الإعادة، فإنه يرجع تعارضًا.
إزالة البيانات
يمكنك استخدام MemoryStoreSortedMap:RemoveAsync() لكل من إزالة مفتاح واحد من الخريطة المرتبة وحذف جميع البيانات في خريطة مرتبة لمخزن الذاكرة.
إزالة مفتاح
لإزالة مفتاح من الخريطة المرتبة، استدعِ MemoryStoreSortedMap:RemoveAsync() مع اسم المفتاح.
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local setSuccess, _ = pcall(function()
return sortedMap:SetAsync("User_1234", 1000, 30, "someStringSortKey")
end)
if setSuccess then
print("تمت العملية بنجاح.")
end
local removeSuccess, removeError = pcall(function()
sortedMap:RemoveAsync("User_1234")
end)
if not removeSuccess then
warn(removeError)
endحذف جميع البيانات
لحذف الذاكرة في الخرائط المرتبة، قم بإدراج جميع مفاتيحك باستخدام MemoryStoreSortedMap:GetRangeAsync()، ثم أزِلها باستخدام MemoryStoreSortedMap:RemoveAsync().
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
-- يبدأ الحد الأدنى الأولي من nil بشكل ينظف من العنصر الأول
local exclusiveLowerBound = nil
while true do
-- احصل على ما يصل إلى مئة عنصر بدءًا من الحدود السفلية الحالية
local getRangeSuccess, items = pcall(function()
return sortedMap:GetRangeAsync(Enum.SortDirection.Ascending, 100, exclusiveLowerBound)
end)
if getRangeSuccess then
local removeSuccess = true
local removeError = nil
for _, item in items do
removeSuccess, removeError = pcall(function()
sortedMap:RemoveAsync(item.key)
end)
end
-- إذا كانت هناك خطأ أثناء إزالة العناصر، حاول مرة أخرى مع نفس الحد الأدنى الحصري
if not removeSuccess then
warn(removeError)
-- إذا كان النطاق أقل من مئة عنصر، يتم الوصول إلى نهاية الخريطة
elseif #items < 100 then
break
else
-- المفتاح الأخير المسترجع هو الحد الأدنى الحصري للدورة التالية
exclusiveLowerBound = {}
exclusiveLowerBound["key"] = items[#items].key
exclusiveLowerBound["sortKey"] = items[#items].sortKey
end
end
endالحصول على الحجم
للحصول على عدد العناصر في الخريطة المرتبة، استدعِ MemoryStoreSortedMap:GetSizeAsync().
local MemoryStoreService = game:GetService("MemoryStoreService")
local sortedMap = MemoryStoreService:GetSortedMap("SortedMap1")
local setSuccess, _ = pcall(function()
return sortedMap:SetAsync("User_1234", 1000, 30, 3.14152)
end)
if setSuccess then
print("تمت العملية بنجاح.")
end
local size
local success, sizError = pcall(function()
size = sortedMap:GetSizeAsync()
end)
if success then
print(size)
else
warn(sizeError)
end