المساعدون
المساعدون هم مجموعة من وظائف المساعدة في لوا للعمل المريح في المشروع.
هذه الوظائف المساعدة توسع بشكل كبير قدرات لوا القياسية وتبسط التطوير.
String
طرق مقدمة من Luanti:
string:lower()
يحول السلسلة إلى أحرف صغيرة مع دعم السيريليك.
print(('ПРИВЕТ МИР'):lower()) -- 'привет мир'string:upper()
يحول السلسلة إلى أحرف كبيرة مع دعم السيريليك.
print(string.upper('привет мир')) -- 'ПРИВЕТ МИР'string:is_one_of(table)
يتحقق مما إذا كانت السلسلة هي إحدى القيم في المصفوفة الممررة.
(تناظر دلالي لـ table.contains، الذي يتحقق مما إذا كانت السلسلة مضمنة في المصفوفة الممررة.)
local text = 'hello'
local options = { 'hello', 'world', 'lua' }
print(text:is_one_of(options)) -- truestring:first_to_upper()
يحول الحرف الأول إلى حرف كبير.
local text = 'hello world'
print(text:first_to_upper()) -- 'Hello world'string :title()/:to_headline()
يحول الحرف الأول من كل كلمة إلى title case.
اسم بديل: string:to_headline()
local text = 'hello world from lua'
print(text:title()) -- 'Hello World From Lua'
print(text:to_headline()) -- 'Hello World From Lua'string:starts_with(prefix)
يتحقق مما إذا كانت السلسلة تبدأ بالبادئة المحددة.
local filename = 'config.json'
print(filename:starts_with('config')) -- true
print(filename:starts_with('settings')) -- falsestring:ends_with(suffix)
يتحقق مما إذا كانت السلسلة تنتهي باللاحقة المحددة.
local filename = 'config.json'
print(filename:ends_with('.json')) -- true
print(filename:ends_with('.conf')) -- falsestring:contains(sub_string)
يتحقق من وجود سلسلة فرعية.
local text = 'Hello, World !!!'
print(text:contains('World')) -- true
print(text:contains('world')) -- false (حساس لحالة الأحرف)string:replace(pattern, replacement, n?)
يستبدل السلسلة الفرعية (تناظر gsub، لكن يعيد السلسلة فقط بدون عدد الاستبدالات).
انظر الوثائق لـ string.gsub و Patterns
local text = 'Hello, World, World!'
local result = text:replace('World', 'Lua')
print(result) -- 'Hello, Lua, Lua!'
-- استبدل التكرار الأول فقط
local result2 = text:replace('World', 'Lua', 1)
print(result2) -- 'Hello, Lua, World!'string:remove(pattern, n?)
يزيل السلسلة الفرعية.
انظر الوثائق لـ string.gsub و Patterns
local text = 'Hello, World!'
print(text:remove(', ')) -- 'HelloWorld!'
print(text:remove('o', 1)) -- 'Hell, Wrld!' (احذف 'o' الأول فقط)string:reg_escape()
يهرب من الأحرف الخاصة للتعبيرات النمطية.
انظر Patterns
local pattern = 'file.txt'
print(pattern:reg_escape()) -- 'file%.txt'
local pattern2 = '^$()%.[]*+-?)'
print(pattern2:reg_escape()) -- '%^%$()%.%[%]%*%+\-%?)'string:vxr_split(delimiter?, processor?)
يقسم السلسلة حسب delimiter المحدد مع القدرة على معالجة الأجزاء.
Luanti لديه طريقة string.split الخاصة به، لكنها لا تدعم معالجة الأجزاء.
هذه الطريقة تضيف القدرة على معالجة أجزاء السلسلة.
-- بدون معالجة
('hello world'):vxr_split() -- { 'hello', 'world' }
('apple,banana,cherry'):vxr_split(',') -- { 'apple', 'banana', 'cherry' }
-- مع المعالجة
local numbers = '1,2,3,4,5'
local squared = numbers:vxr_split(',', function(x)
return tonumber(x)^2
end)
print(squared[1], squared[2], squared[3], squared[4], squared[5])
-- 1 4 9 16 25string.or_nil(value)
يحول إلى سلسلة أو يعيد nil.
print(string.or_nil('hello')) -- 'hello'
print(string.or_nil(42)) -- '42'
print(string.or_nil(nil)) -- nil
print(tostring(nil)) -- 'nil' (مقارنة)طرق مقدمة من Luanti :
Luanti string.split()
انظر أيضاً: string.vxr_split(delimiter?, processor?)
يقسم السلسلة إلى أجزاء حسب الفاصل المحدد. يعيد مصفوفة من السلاسل. الوسائط:
separator?الفاصل، افتراضي:","include_empty?افتراضي:falsemax_splits?إذا كان سالبًا، تقسيمات غير محدودة، افتراضي:-1sep_is_pattern?إذا كان الفاصل سلسلة عادية أو نمط (regex)، افتراضي:false
local text = 'apple,banana,cherry'
local parts = text.split(',')
print(parts[1], parts[2], parts[3]) -- 'apple', 'banana', 'cherry'
-- قسم حسب المسافات
local words = 'hello world lua'.split(' ')
print(words[1], words[2], words[3]) -- 'hello', 'world', 'lua'Luanti string.trim()
يزيل أحرف المسافة في بداية ونهاية السلسلة.
print(("\n \t\tfoo bar\t "):trim()) -- 'foo bar'Luanti string.pack()
يحزم القيم في سلسلة ثنائية حسب التنسيق.
Backport من Lua 5.4.
-- حزم الأعداد الصحيحة
local packed = string.pack('i4', 42)
print(#packed) -- 4 (الحجم بالبايت)
-- حزم قيم متعددة
local data = string.pack('i4f8', 100, 3.14)
print(#data) -- 12 (4 + 8 بايت)Luanti string.unpack()
يفك حزم السلسلة الثنائية إلى قيم حسب التنسيق.
Backport من Lua 5.4.
local packed = string.pack('i4f8', 100, 3.14)
local num, float, next_pos = string.unpack('i4f8', packed)
print(num, float) -- 100, 3.14
print(next_pos) -- 13 (الموضع بعد فك الحزم)
-- فك حزم من الموضع المحدد
local value = string.unpack('i4', packed, 5)
print(value) -- 3.14 (كـ float)Luanti string.packsize()
يعيد حجم السلسلة التي سيتم إنشاؤها بواسطة string.pack.
Backport من Lua 5.4.
local size = string.packsize('i4f8')
print(size) -- 12 (4 + 8 بايت)
-- للتنسيقات المعقدة
local complex_size = string.packsize('i4c10f8')
print(complex_size) -- 22 (4 + 10 + 8 بايت)Table
طرق، المقدمة من Luanti :
table.copy()table.copy_with_metatables()table.insert_all()
table.indexof()table.keyof()table.key_value_swap()table.shuffle()
table.keys(table)
يعيد مصفوفة من مفاتيح الجدول.
local data = { name = 'Alek', age = 25, city = 'Vladivostok' }
local keys = table.keys(data)
-- `keys` يحتوي `{ 'name', 'age', 'city' }` (الترتيب قد يختلف)table.values(table)
يعيد مصفوفة من قيم الجدول.
local data = { name = 'Alek', age = 25, city = 'Vladivostok' }
local values = table.values(data)
-- `values` يحتوي { 'Alek', 25, 'Vladivostok' }table.has_key(table, key)
يتحقق مما إذا كان المفتاح موجودًا في الجدول.
local data = { name = 'Alek', age = 25 }
print(table.has_key(data, 'name')) -- true
print(table.has_key(data, 'city')) -- falsetable .contains/has_value(table, value)
يتحقق مما إذا كانت القيمة موجودة في الجدول.
local fruits = { 'apple', 'banana', 'cherry' }
print(table.contains(fruits, 'banana')) -- true
print(table.contains(fruits, 'orange')) -- falseيمكنك أيضًا استخدام string:is_one_of():
print('banana':is_one_of(fruits)) -- true
print('orange':is_one_of(fruits)) -- falseاسم بديل: table.has_value
local data = { x = 10, y = 20 }
print(table.has_value(data, 10)) -- true
print(table.has_value(data, 30)) -- falsetable.keys_of(table, value)
يعيد جدولًا بالمفاتيح من الجدول المحدد التي لها القيمة المحددة.
local data = { a = 10, b = 20, c = 10, d = 30 }
local keys = table.keys_of(data, 10)
print(dump(keys)) -- { 'a', 'c' }
local keys2 = table.keys_of(data, 99)
print(keys2) -- nil (لا يوجد مفاتيح كهذه)table.has_any_key(table, find_keys)
يتحقق مما إذا كانت مفاتيح الجدول تحتوي على قيمة واحدة على الأقل من المصفوفة المحددة.
local data = { name = 'test', age = 25, active = true }
local find_keys = { 'name', 'email', 'phone' }
print(table.has_any_key(data, find_keys)) -- true (المفتاح 'name' في find_keys)
local find_keys2 = { 'email', 'phone', 'address' }
print(table.has_any_key(data, find_keys2)) -- falsetable.equals(table1, table2)
يقارن بشكل متكرر جدولين من أجل المساواة الكاملة.
local table1 = { a = 1, b = { c = 2, d = 3 } }
local table2 = { a = 1, b = { c = 2, d = 3 } }
local table3 = { a = 1, b = { c = 2, d = 4 } }
print(table.equals(table1, table2)) -- true
print(table.equals(table1, table3)) -- falsetable.is_empty(table)
يتحقق مما إذا كان الجدول فارغًا.
print(table.is_empty({})) -- true
print(table.is_empty({ a = 1 })) -- falsetable.is_position(table)
يتحقق مما إذا كان الجدول يمثل إحداثيات.
print(table.is_position({ x = 10, y = 20, z = 30 })) -- true
print(table.is_position({ x = 10, y = 20 })) -- false
print(table.is_position({ a = 1, b = 2, c = 3 })) -- falsetable.each_value_is(table, value)
يتحقق من أن جميع عناصر الجدول تساوي القيمة المحددة. افتراضيًا يتحقق لـ true.
local data1 = { true, true, true }
print(table.each_value_is(data1)) -- true
local data2 = { 5, 5, 5, 5 }
print(table.each_value_is(data2, 5)) -- true
local data3 = { 1, 2, 3 }
print(table.each_value_is(data3, 1)) -- falsetable.count(table)
يعد عدد العناصر في الجدول.
NOTE
للجداول ذات المفاتيح الصحيحة، استخدم #table.
بما أن عامل التشغيل # لا يعمل على الجداول ذات المفاتيح غير الصحيحة، استخدم table.count لها.
local data = { a = 1, b = 2, c = 3 }
print(table.count(data)) -- 3
print(#data) -- 0، لأن عامل التشغيل `#` لا يعمل مع المفاتيح غير الصحيحة.
local array = { 1, 2, 3, 4, 5 }
print(#array) -- 5table.generate_sequence(max, start_from?, step?)
ينشئ تسلسل أرقام.
local seq1 = table.generate_sequence(5)
print(dump(seq1)) -- { 1, 2, 3, 4, 5 }
local seq2 = table.generate_sequence(10, 2, 2)
print(dump(seq2)) -- { 2, 4, 6, 8, 10 }
local seq3 = table.generate_sequence(1, 5, -1)
print(dump(seq3)) -- { 5, 4, 3, 2, 1 }table.only(table, only)
يعيد جدولًا جديدًا يحتوي على بيانات فقط بالمفاتيح المحددة.
local data = { name = 'Alek', age = 25, city = 'Vladivostok', country = 'Russia' }
local filtered = table.only(data, { 'name', 'age' })
-- `filtered` يحتوي `{ name = 'Alek', age = 25 }`
print(filtered.name, filtered.age) -- 'Alek', 25
print(filtered.city) -- niltable.except(table, keys)
يعيد جدولًا جديدًا يحتوي على بيانات بدون المفاتيح المحددة.
(ينسخ الجدول، مستثنيًا المفاتيح المحددة)
local data = { name = 'Alek', age = 25, city = 'Vladivostok', country = 'Russia' }
local filtered = table.except(data, { 'age', 'country' })
-- `filtered` يحتوي `{ name = 'Alek', city = 'Vladivostok' }`
print(filtered.name, filtered.city) -- 'Alek', 'Vladivostok'
print(filtered.age, filtered.country) -- nil, niltable.merge(table1, table2, overwrite?)
يدمج الجداول بشكل متكرر.
افتراضيًا، الجدول الأول لا يتم الكتابة عليه، يتم إنشاء جدول جديد.
local defaults = { theme = 'dark', font = { size = 12, family = 'Arial' } }
local user_config = { font = { size = 16 }, language = 'en' }
local merged = table.merge(defaults, user_config)
print(dump(merged))
-- {
-- theme = "dark",
-- font = {
-- size = 16,
-- family = "Arial",
-- },
-- language = "en",
-- }اكتب على الجدول الأول:
table.merge(defaults, user_config, true)TIP
- من الأفضل استخدام
table.overwrite()لسهولة القراءة.
table.join(table1, table2, recursively?)
يضيف المفاتيح المفقودة من table2 إلى table1.
القيم التي هي جداول يتم نسخها باستخدام table.copy().
local base = { a = 1, b = 2 }
local addition = { b = 10, c = 3 }
table.join(base, addition)
print(dump(base)) -- { a = 1, b = 2, c = 3 }إذا كان recursively هو true، فستُطبق الدالة بشكل متكرر فقط على القيم التي هي جداول في كل من table1 و table2.
local base = { a = 1, b = { c = 2 } }
local addition = { b = { c = 10, d = 20 } }
table.join(base, addition, true)
print(dump(base))
-- {
-- a = 1,
-- b = {
-- c = 2,
-- d = 20,
-- },
-- }table.overwrite(table1, table2)
يكتب بالكامل على table1 بالقيم من table2.
متغير دلالي لـ table.merge(table1, table2, true).
table.merge_values(table1, table2)
يدمج قيم جدولين في واحد، يزيل التكرارات.
الترتيب محفوظ - أولاً قيم من table1، ثم من table2 التي لم تكن في table1.
local table1 = { 'apple', 'banana', 'cherry' }
local table2 = { 'banana', 'date', 'apple', 'elderberry' }
local merged = table.merge_values(table1, table2)
print(dump(merged)) -- { 'apple', 'banana', 'cherry', 'date', 'elderberry' }table.map(table, callback, overwrite?)
يطبق الدالة على كل عنصر في الجدول.callback: fun(value: any, key: any): any - يقبل القيمة والمفتاح، يعيد قيمة جديدة.
افتراضيًا يعيد جدولًا جديدًا.
local numbers = { 1, 2, 3, 4, 5 }
local squared = table.map(numbers, function(x) return x * x end)
print(dump(squared))
-- { 1, 4, 9, 16, 25 }
local data = { a = 10, b = 20 }
local doubled = table.map(data, function(value, key)
print(key, value)
return value * 2
end)
-- a 10
-- b 20
print(dump(doubled))
-- { a = 20, b = 40 }إذا كان overwrite هو true، فالدالة تعدل الجدول الأصلي.
local data = { a = 10, b = 20 }
table.map(data, function(value, key) return value * 2 end, true)
print(dump(data)) -- { a = 20, b = 40 }table .walk/.each(table, callback)
يتكرر على الجدول مطبقًا الدالة (لا يعدل الجدول).callback: fun(value: any, key: any): void - يقبل القيمة والمفتاح؛ لا يعيد أي شيء.
local data = { a = 10, b = 20, c = 30 }
table.walk(data, function(value, key)
print(key, value)
end)
-- a 10
-- c 30
-- b 20اسم بديل: table.each()
local data = { a = 10, b = 20, c = 30 }
table.each(data, function(value, key)
data[key] = value * 2
-- لا شيء يمنع الوصول إلى upvalue `data`. الآن `data` تم الكتابة عليه.
end)
print(dump(data)) -- { a = 20, b = 40, c = 60 }table.multiply_each_value(table, multiplier_table)
يضرب كل قيمة في الجدول بالقيمة المقابلة من multiplier_table حسب المفتاح.
local data = { a = 10, b = 20, c = 30 }
local multipliers = { a = 2, b = 0.5, c = 3 }
local result = table.multiply_each_value(data, multipliers)
print(dump(result)) -- { a = 20, b = 10, c = 90 }
-- المفاتيح بدون مضاعب تبقى كما هيtable.add_values(table1, table2, empty_value?, overwrite?)
يضيف قيم بنفس المفتاح من جدولين.
local table1 = { a = 10, b = 20 }
local table2 = { b = 5, c = 15 }
local result = table.add_values(table1, table2)
print(dump(result)) -- { a = 10, b = 25, c = 15 }
-- مع قيمة فارغة للمفاتيح المفقودة
local result2 = table.add_values(table1, table2, 0)
print(dump(result2)) -- { a = 10, b = 25, c = 15 }table.sub_values(table1, table2, empty_value?, overwrite?)
يطرح قيم table2 من table1 لنفس المفاتيح.
local table1 = { a = 10, b = 20, c = 30 }
local table2 = { b = 5, c = 10, d = 5 }
local result = table.sub_values(table1, table2)
print(dump(result)) -- { a = 10, b = 15, c = 20, d = -5 }table.mul_values(table1, table2, empty_value?, overwrite?)
يضرب القيم بنفس المفتاح من جدولين.
local table1 = { a = 2, b = 3 }
local table2 = { b = 4, c = 5 }
local result = table.mul_values(table1, table2)
print(dump(result)) -- { a = 2, b = 12, c = 5 }table.div_values(table1, table2, empty_value?, overwrite?)
يقسم قيم table1 على قيم table2 لنفس المفاتيح.
local table1 = { a = 10, b = 20, c = 30 }
local table2 = { b = 5, c = 10, d = 2 }
local result = table.div_values(table1, table2)
print(dump(result)) -- { a = 10, b = 4, c = 3, d = 0.5 }Math
math .limit/.clamp(value, min, max)
يحدد القيمة إلى النطاق المحدد.
اسم بديل: math.clamp().
local health = 150
local max_health = 100
local clamped_health = math.limit(health, 0, max_health)
print(clamped_health) -- 100math.is_within(value, min, max)
يتحقق من أن القيمة داخل النطاق بشكل صارم (min < value < max).
print(math.is_within(5, 1, 10)) -- true
print(math.is_within(1, 1, 10)) -- false (الحدود غير مشمولة)
print(math.is_within(10, 1, 10)) -- falsemath.is_among(value, min, max)
يتحقق من أن القيمة داخل النطاق، بما في ذلك الحدود (min <= value <= max).
print(math.is_among(5, 1, 10)) -- true
print(math.is_among(1, 1, 10)) -- true
print(math.is_among(10, 1, 10)) -- truemath.is_in_range(value, min, max)
يتحقق من أن القيمة داخل النطاق شبه المفتوح (min, max] (min < value <= max).
print(math.is_in_range(5, 1, 10)) -- true
print(math.is_in_range(1, 1, 10)) -- false (يساوي الحد الأدنى)
print(math.is_in_range(10, 1, 10)) -- true (يساوي الحد الأقصى)math.is_near(value, near, gap?)
يتحقق من أن القيمة قريبة من المحدد (|value - near| <= gap).
print(math.is_near(10, 12)) -- false (gap = 1 افتراضي)
print(math.is_near(11, 12)) -- true
print(math.is_near(10, 12, 3)) -- true (gap = 3)math.quadratic_equation_roots(a, b, c)
يحل معادلة تربيعية من الشكل y = a*x^2 + b*x + c.
local root1, root2 = math.quadratic_equation_roots(1, -5, 6)
print(root1, root2) -- 3, 2
-- لا توجد جذور حقيقية
local r1, r2 = math.quadratic_equation_roots(1, 0, 1)
print(r1, r2) -- nil, nilmath.point_on_circle(radius, angle)
يحسب نقطة على دائرة.
local x, z = math.point_on_circle(5, math.pi/4)
print(x, z) -- إحداثيات نقطة على دائرة نصف قطرها 5 عند زاوية 45°Debug
__FILE__(depth?, full?)
يعيد اسم الملف الحالي أو ملف الدالة المستدعية حسب عمق المكدسة.
depth?- عمق مكدسة الاستدعاء (افتراضي0)full?- أظهر المسار الكامل (افتراضيfalse)
-- احصل على المسار النسبي للملف
print(__FILE__()) -- 'mods/Voxrame/helpers/src/lua_ext/debug.lua'
-- احصل على المسار الكامل للملف
print(__FILE__(0, true)) -- '/home/alek13/projects/my-game/mods/Voxrame/helpers/src/lua_ext/debug.lua'
-- احصل على الملف 2 مستوى أعلى في مكدسة الاستدعاء
print(__FILE__(2)) -- ملف الدالة التي استدعت الدالة المستدعية__LINE__(depth?)
يعيد رقم السطر الحالي أو رقم سطر الدالة المستدعية حسب عمق المكدسة.
print(__LINE__()) -- 57
-- احصل على رقم سطر الدالة المستدعية
print(__LINE__(1)) -- رقم السطر في ملف الاستدعاء__FILE_LINE__(depth?, full?)
يعيد الملف والسطر بتنسيق "مسار/نسبي/إلى/ملف:سطر".
print(__FILE_LINE__()) -- 'mods/Voxrame/helpers/src/lua_ext/debug.lua:65'
-- مع المسار الكامل
print(__FILE_LINE__(0, true)) -- '/home/alek13/projects/my-game/mods/Voxrame/helpers/src/lua_ext/debug.lua:65'__DIR__(depth?)
يعيد الدليل من الملف الحالي أو ملف الدالة المستدعية حسب عمق المكدسة.
print(__DIR__()) -- 'mods/Voxrame/helpers/src/lua_ext/'__FUNC__(depth?)
يعيد اسم الدالة الحالية.
function my_function()
print(__FUNC__()) -- 'my_function'
endprint_dump(depth, with_trace, ...)
يطبع محتوى جميع المعلمات الممررة ....
قبل الإخراج، يضيف اسم الملف والسطر @ <file>:<line>.
إذا كان with_trace هو true، يطبع أيضًا مكدسة الاستدعاء.
NOTE
- إذا كان الطرف الخاص بك يدعم الروابط، كل
@ <file>:<lineسيتم ربطه بفتح IDE، انظرreadme.mdللتكوين.
TIP
- استخدم
pd()وpdt()لصياغة أكثر إيجازًا. انظر الأمثلة أدناه.
pd(...)
اختصار لـ print_dump. يستدعي print_dump مع with_trace == false.
local player_name = 'test_player'
local position = { x = 10, y = 20, z = 30 }
pd(player_name, position)output:
[93m@ [0m[33mmods/lord/Core/map/src/map/Corridor.lua[0m[97m:[0m[32m14[0m
[36mplayer_name:[0m "test_player"
[36m position:[0m {
x = 10,
y = 20,
z = 30,
}pdt(...)
اختصار لـ print_dump traced. يستدعي print_dump مع with_trace == true.
local player_name = 'test_player'
local position = { x = 10, y = 20, z = 30 }
pdt(player_name, position)output:
[93m@ [0m[33mmods/lord/Core/map/src/map/Corridor.lua[0m[97m:[0m[32m14[0m
[3m[2m 1 [0m[93m@[0m [C][36m: in dofile[0m
[3m[2m 2 [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod/require.lua[0m[97m:[0m[32m29[0m[36m: in require[0m
[3m[2m 3 [0m[93m@ [0m[33mmods/lord/Core/map/src/map.lua[0m[97m:[0m[32m9[0m[36m: in main[0m
[3m[2m 4 [0m[93m@ [0m [C][36m: in dofile[0m
[3m[2m 5 [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod/require.lua[0m[97m:[0m[32m29[0m[36m: in require[0m
[3m[2m 6 [0m[93m@ [0m[33mmods/lord/Core/map/init.lua[0m[97m:[0m[32m4[0m[36m: in mod_init_function[0m
[3m[2m 7 [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod.lua[0m[97m:[0m[32m80[0m[36m: in mod[0m
[3m[2m 8 [0m[93m@ [0m[33mmods/lord/Core/map/init.lua[0m[97m:[0m[32m3[0m[36m: in main[0m
[36mplayer_name:[0m "test_player"
[36m position:[0m {
x = 10,
y = 20,
z = 30,
}debug.measure(name, callback, print_result?)
يقيس وقت تنفيذ الدالة.
local function heavy_calculation()
local sum = 0
for i = 1, 2000000 do
sum = sum + math.random(1, 100) + math.sin(i)
end
end
-- قس مع إخراج النتيجة
debug.measure('calculation', heavy_calculation, true)
debug.measure('calculation', heavy_calculation, true)
debug.measure('calculation', heavy_calculation, true)
debug.measure('calculation', heavy_calculation, true)
debug.measure('calculation', heavy_calculation, true)
-- output:
-- Measure of [calculation]: Time: 42 ms ; Average: 42 ms
-- Measure of [calculation]: Time: 58 ms ; Average: 50 ms
-- Measure of [calculation]: Time: 58 ms ; Average: 53 ms
-- Measure of [calculation]: Time: 35 ms ; Average: 48 ms
-- Measure of [calculation]: Time: 33 ms ; Average: 45 ms
-- قس بدون إخراج
local time, avg, count = debug.measure('calculation', heavy_calculation)
print(time, avg, count)
local time, avg, count = debug.measure('calculation', heavy_calculation)
print(time, avg, count)
-- output:
-- 33.075 43.170833333333 6
-- 33.135 41.737142857143 7debug.mesure_print(name)
يطبع إحصاءات القياسات السابقة name التي تم الحصول عليها من استدعاءات debug.measure(name, ....).
debug.mesure_print('calculation')
-- output:
-- Measure of [calculation]: Average time: 42 ms ; Last time: 33 ms ; Count of mesures: 7Global
errorf(message, ...)
مشابه لـ error() في Lua، لكن message يمكن أن يكون قالب سلسلة معوسائط محددة، مشابه لـ string.format().
local player_name = nil
errorf('اللاعب '%s' غير موجود', player_name)
-- خطأ: اللاعب 'nil' غير موجودoutput (عندما يكون debug مفعلاً):
[93m@ [0m[33mmods/lord/Core/map/src/map/Corridor.lua[0m[97m:[0m[32m9[0m
[32m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[0m
[1m[91mERROR:[0m
[91m اللاعب `nil` غير موجود[0m
[1m[91mStack trace:[0m
[3m[2m 1 [0m[93m@[0m [C][36m: in error[0m
[3m[2m 2 [0m[93m@ [0m[33mmods/lord/Core/helpers/src/lua_ext/global.lua[0m[97m:[0m[32m9[0m[36m: in errorf[0m
[3m[2m 3 [0m[93m@ [0m[33mmods/lord/Core/map/src/map/Corridor.lua[0m[97m:[0m[32m12[0m[36m: in main[0m
[3m[2m 4 [0m[93m@ [0m [C][36m: in dofile[0m
[3m[2m 5 [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod/require.lua[0m[97m:[0m[32m29[0m[36m: in require[0m
[3m[2m 6 [0m[93m@ [0m[33mmods/lord/Core/map/src/map.lua[0m[97m:[0m[32m9[0m[36m: in main[0m
[3m[2m 7 [0m[93m@ [0m [C][36m: in dofile[0m
[3m[2m 8 [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod/require.lua[0m[97m:[0m[32m29[0m[36m: in require[0m
[3m[2m 9 [0m[93m@ [0m[33mmods/lord/Core/map/init.lua[0m[97m:[0m[32m4[0m[36m: in mod_init_function[0m
[3m[2m 10 [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod.lua[0m[97m:[0m[32m80[0m[36m: in mod[0m
[3m[2m 11 [0m[93m@ [0m[33mmods/lord/Core/map/init.lua[0m[97m:[0m[32m3[0m[36m: in main[0m
[32m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[0mمعالجة الأخطاء في Luanti
WARNING
- ستحتوي مكدسة الاستدعاء على خطوط إضافية، لأن Luanti لا يمرر
levelالمحدد إلىcore.error_handler().
errorlf(message, level, ...)
مثل في errorf() يمكنك تمرير سلسلة تنسيق ووسائط، وأيضًا تحديد مستوى التتبع.
errorlf('خطأ في البيانات', 3, 'قيمة: %d', 42)
-- خطأ مع تتبع 3 مستويات أعلىassertf(condition, message, ...)
مشابه لـ assert() في Lua، لكن كـ message يمكنك تحديد سلسلة تنسيق مع وسائط، مشابه لـ string.format().
يستدعي
errorf()إذا لم يتم تحقيق شرطcondition.
-- استمر التنفيذ إذا كان player موجودًا، وإلا خطأ
local player = nil
assertf(player, 'اللاعب `%s` غير موجود', player)IO
io.file_exists(name)
يتحقق مما إذا كان الملف موجودًا.
if io.file_exists('config.txt') then
print('ملف التكوين موجود')
else
print('ملف التكوين مفقود')
endio.dirname(path)
يعيد الدليل من المسار.
print(io.dirname('/home/user/project/file.txt')) -- '/home/user/project'
print(io.dirname('relative/path/file.txt')) -- 'relative/path'
print(io.dirname('file.txt')) -- '.'io.write_to_file(filepath, content, mode?)
يكتب المحتوى إلى ملف.
local success, error_code, error_message = io.write_to_file('data.txt', 'Hello, World!')
if success then
print('تم كتابة البيانات بنجاح')
else
print('خطأ في الكتابة:', error_code, error_message)
end
-- أضف إلى نهاية الملف
io.write_to_file('log.txt', 'إدخال جديد\n', 'a')io.read_from_file(filepath, mode?)
يقرأ كل المحتوى من ملف.
يعيد سلسلة مع محتوى الملف في حالة النجاح أو false, error_code, error_message في حالة الخطأ.
local content = io.read_from_file('config.json')
if content then
print('محتوى الملف:', content)
else
print('خطأ في قراءة الملف')
endمعالجة الأخطاء
local success, error_code, error_message = io.read_from_file('nonexistent.txt')
if not success then
print('خطأ:', error_code, error_message)
end
-- خطأ: 2 nonexistent.txt: No such file or directoryأو:
local success = io.read_from_file('nonexistent.txt')
if not success then
local error_code, error_message = io.get_file_error()
print('خطأ:', error_code, error_message)
end
-- خطأ: 2 nonexistent.txt: No such file or directoryالقراءة في الوضع الثنائي
local binary_content = io.read_from_file('image.png', 'rb')
if binary_content then
print('حجم الملف:', #binary_content, 'بايت')
endio.get_file_error()
يعيد رمز ورسالة الخطأ الأخير من وظائف io.read_from_file() أو io.write_to_file().
local success = io.read_from_file('nonexistent.txt')
if not success then
local error_code, error_message = io.get_file_error()
print('خطأ:', error_code, error_message)
end
-- Output: خطأ: 2 nonexistent.txt: No such file or directorylocal success = io.write_to_file('/readonly/file.txt', 'data')
if not success then
local error_code, error_message = io.get_file_error()
print('خطأ في الكتابة:', error_code, error_message)
end
-- Output: خطأ في الكتابة: 13 /readonly/file.txt: Permission deniedOS
os.DIRECTORY_SEPARATOR
فاصل الدليل لنظام التشغيل الحالي.
local DS = os.DIRECTORY_SEPARATOR
print(DS) -- '/' في Linux/Mac، '\' في Windows
print('folder' .. DS .. 'file.txt')
-- في Linux/Mac: 'folder/file.txt'
-- في Windows: 'folder\file.txt'