lib
JRS Lib مكتبة برمجة مقسّمة لـ RedM تسهّل تطوير اللعبة بمكوّنات قابلة لإعادة الاستخدام مبنية على النسخ مع تنظيف تلقائي. مصممة خصيصاً لفريمورك JRS Core، وتساعد المطورين يكتبون سكربتات أنظف وأكفأ وتمنع مشاكل شائعة مثل تسريب الذاكرة وتلويث المتغيرات العامة
هذا التوثيق للمطورين اللي يسوون سكربتات لـ redm، وانتبه إن هذا شغل مستمر وأي شي ممكن يتغير في أي وقت لين الإصدار النهائي.
ما تقدر تستورد ملفات مشفّرة مثل escrow وغيرها، بس الملفات الغير مشفّرة تنستورد.
استخدام المكتبة
عشان تستورد موديولات لسكربتك لازم تضيف التالي لملف fxmanifest.lua حق السكربت
shared_script "@jrs_core/lib/import.lua"استيراد الموديولات
بس ملفات Lua تنستورد
قائمة الموديولات
الموديولات (كلاينت)#
entities (موديول)#
هذا الموديول فيه دوال تخليك تنشئ كيانات مثل الشخصيات والمركبات والأغراض وغيرها
blips (موديول)#
هذا الموديول فيه دوال تخليك تنشئ أنواع مختلفة من علامات الخريطة وأشياء تخص الخريطة
inputs (موديول)#
هذا الموديول فيه دوال تخليك تنشئ أزرار تحكم
raycast (موديول)#
هذا الموديول فيه دوال تخليك تسوي raycast من الكاميرا أو من كيان
prompts (موديول)#
هذا الموديول فيه دوال تخليك تنشئ prompts
commands (موديول) (كلاينت)#
هذا الموديول فيه دوال تخليك تسجّل أوامر
points (موديول)#
هذا الموديول فيه دوال تخليك تنشئ نقاط دخول/خروج مع خيارات تصحيح
polyzones (موديول)#
هذا الموديول فيه دوال تخليك تنشئ مناطق كشف مضلعة أو دائرية أو مربعة مع callbacks وأدوات تصحيح
events (موديول)#
هذا الموديول فيه دوال تخليك تسجّل أحداث اللعبة
dataview (موديول)#
هذا الموديول فيه دوال تخليك تستخدم dataview في lua
streaming (موديول)#
هذا الموديول فيه دوال تخليك تحمّل ملفات اللعبة مثل قواميس الأنيميشن والموديلات وغيرها
استيراد الموديولات
Import#
modulestringrequiredيخليك تستورد أي موديول من المكتبة، وتلقى قائمة الموديولات المتاحة هنا
local module = Import "modulename" -- no symbols
local prompts = Import("prompts").Prompts -- every module has a table with the module name as the key for readability
local Lib = Import "prompts"
local Prompts = Lib.Prompts -- [[@as PROMPTS]] -- for intellisenseImport#
modulestringrequiredيخليك تستورد أي ملف من السكربت اللي أنت فيه، ولازم يبدأ دائماً بـ . أو / عشان توصل لمسار الملف
local module = Import "/filename"
local module = Import "/folder/filename"Import#
modulestringrequiredيخليك تستورد ملفات من سكربتات ثانية، ولازم يبدأ دائماً بـ @ وبعدها الرموز الخاصة / أو . عشان توصل لمسار الملف
local module = Import "@script_name/filename"
local module = Import "@script_name/folder/filename"طريقة الاستيراد
Single#
modulestringrequiredاسم الموديول المراد استيراده
local module = Import "module"Multiple#
modulearrayrequiredاسم الموديول المراد استيراده
local module = Import ({"module", "module2", "module3"})
local prompts = module.PromptsMixed#
modulearrayrequiredأسماء الموديولات المراد استيرادها
local module = Import ({"module", "/internal/filename", "@script_name/external/filename"})
local prompts = module.Prompts
local commands = module.Commandsاستخدام الموديولات
الموديولات التالية متاحة في المكتبة، تقدر تستوردها بدالة Import، وتوثيق كل موديول موجود تحت
الكيانات
هذا الموديول ينستخدم لإنشاء كيانات مثل الشخصيات والمركبات والأغراض وغيرها، وفيه كلاس أساسي لكل الكيانات وكلاسات فرعية لكل نوع كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف الكيانات عشان يسهل التطوير
فيه متتبّع كيانات إذا تبي تتبع الكيانات من سكربتات ثانية (شوف ملف collector) للـ exports
Ped#
- هذا الكلاس الفرعي ينستخدم لإنشاء شخصيات (يرث من الكلاس الأساسي
Entity)، وهي كائنات مستقلة وكل إنشاء له نسخته الخاصة - تحت الدوال المتاحة لكلاس ped
Create#
إنشاء ped
Modelintegerrequiredموديل الـ ped
Posvector3requiredموقع الـ ped
IsNetworkedbooleanإذا الـ ped شبكي
ScriptHostPedbooleanإذا الـ ped تابع لمستضيف السكربت
P7booleanغير معروف
P8booleanغير معروف
Optionstableهذي معاملات اختيارية
PlaceOnGround = boolean, OutfitPreset = integer
OnCreatefunctionالدالة اللي تتشغّل لما ينسوى الـ ped
OnDeletefunctionالدالة اللي تتشغّل لما ينحذف الـ ped
-- Example
-- Import the entities module
local Entity = Import 'entities' --[[@as ENTITY]]
local ped = Entity.Ped:Create({
Model = 'A_C_COW',
Pos = vector4(0, 0, 0, 0),
IsNetworked = true,
Options = {
PlaceOnGround = true,
OutfitPreset = 0,
},
print('Ped created use your own logic here, handle: ', self:GetHandle())
end,
netid)
print('Ped deleted use your own logic here, handle: ', handle, 'netid: ', netid)
end
})
-- methods you can use
local handle = ped:GetHandle()
ped:Delete()Vehicle#
- هذا الكلاس الفرعي ينستخدم لإنشاء مركبات (يرث من الكلاس الأساسي
Entity)، وهي كائنات مستقلة وكل إنشاء له نسخته الخاصة - تحت الدوال المتاحة لكلاس المركبة
Create#
Modelstringrequiredموديل المركبة
Posvectorrequiredموقع المركبة
IsNetworkedbooleanإذا المركبة شبكية
ScriptHostVehbooleanإذا المركبة تابعة لمستضيف السكربت
DontAutoCreateDraftAnimalsbooleanينشئ حيوانات الجر إذا true
P8booleanغير معروف
OptionstablePlaceOnGround, Seat = { Ped = ped, Index = -1}
OnCreatefunctionالدالة اللي تتشغّل لما تنسوى المركبة
OnDeletefunctionالدالة اللي تتشغّل لما تنحذف المركبة
-- Example
-- Import the entities module
local Entity = Import 'entities' --[[@as ENTITY]]
local vehicle = Entity.Vehicle:Create({
Model = 'wagon01x',
Pos = vector4(0, 0, 0, 0),
IsNetworked = true,
Options = {
PlaceOnGround = true,
Seat = { -- optional
Ped = ped, -- entity
Index = -1, -- -1 for driver, 0 for passenger, 1 for passenger, 2 for passenger, etc
}
},
print('Vehicle created use your own logic here, handle: ', self:GetHandle())
end,
print('Vehicle deleted use your own logic here, handle: ', self:GetHandle())
end
})
local handle = vehicle:GetHandle()
vehicle:Delete()Object#
- هذا الكلاس الفرعي ينستخدم لإنشاء أغراض (يرث من الكلاس الأساسي
Entity)، وهي كائنات مستقلة وكل إنشاء له نسخته الخاصة - تحت الدوال المتاحة لكلاس الغرض
Create#
Modelintegerrequiredموديل الغرض
Posvector3requiredموقع الغرض
IsNetworkedbooleanإذا الغرض شبكي
ScriptHostObjbooleanإذا الغرض تابع لمستضيف السكربت
Dynamicbooleanإذا الغرض ديناميكي
OptionstablePlaceOnGround = boolean, Rot = vector3,Rot.Order = integer, Rot.P5 = boolean
OnCreatefunctionالدالة اللي تتشغّل لما ينسوى الغرض
OnDeletefunctionالدالة اللي تتشغّل لما ينحذف الغرض
-- Example
-- Import the entities module
local Entity = Import 'entities' --[[@as ENTITY]]
local object = Entity.Object:Create({
Model = 'prop_paper_bag_01',
Pos = vector4(0, 0, 0, 0),
IsNetworked = true,
Options = { -- optional
PlaceOnGround = true,
Rot = {
Pos = vector3(0, 0, 0),
Order = 2,
P5 = true,
}
},
print('Object created use your own logic here, handle: ', self:GetHandle())
end,
print('Object deleted use your own logic here, handle: ', self:GetHandle())
end
})
local handle = object:GetHandle()
object:Delete()الخريطة
موديول الخريطة ينستخدم حالياً لإنشاء علامات الخريطة، وراح يتوسع ويشمل ميزات خريطة أكثر لما تعيد تشغيل الريسورس تنحذف علامات الخريطة عشان يسهل التطوير
Blip#
هذا الكلاس الأساسي لعلامات الخريطة، تقدر تستخدم الدوال تحت أو الـ natives مباشرة
GetHandle#
returnintegerجلب handle لعلامة الخريطة
GetBlipColor#
colorstring|tablerequiredجلب color value's لألوان العلامة، ممكن يكون single color string أو table of color strings
returnintegerيرجع color value's المقابل لـ color name's
-- single string or multiple colors can be requested just for ease of use
local blue, red, yellow = Map.Blips:GetBlipColor({ 'blue', 'red', 'yellow' })
blip:AddModifierColor(blue) -- or string "blue"Remove#
returnnilإزالة/حذف علامة الخريطة
SetName#
namestringrequiredتعيين اسم علامة الخريطة
SetCoords#
posvector3requiredتعيين إحداثيات علامة الخريطة (pos.x, pos.y, pos.z)
SetStyle#
styleinteger|stringrequiredتعيين ستايل علامة الخريطة، شوف blip style
SetSprite#
spriteinteger|stringrequiredتعيين أيقونة علامة الخريطة. شوف blip sprite
AddModifier#
modifierinteger|stringrequiredإضافة modifier لعلامة الخريطة، شوف blip modifier
RemoveModifier#
modifierinteger|stringrequiredإزالة modifier من علامة الخريطة، شوف blip modifier
AddModifierColor#
colorstring|integerrequiredإضافة modifier لون لعلامة الخريطة، استخدم دالة GetBlipColor عشان تجيب قيم الألوان إذا احتجت
Create#
إنشاء علامة خريطة
BlipTypestringrequiredنوع العلامة: entity، coords، area، radius وكل نوع له معاملات خاصة
Blipinteger|stringrequiredأيقونة/hash العلامة، شوف blip sprite hash
Entityintegerمطلوب لنوع 'entity' - الكيان اللي تنربط فيه العلامة
Posvector3مطلوب لأنواع 'coords' و 'area' و 'radius' - موقع العلامة
Scalevector3مطلوب لنوع 'area' - أبعاد الحجم (x, y, z)
Radiusnumberمطلوب لنوع 'radius' - حجم النطاق (الافتراضي 0.5)
P7integerمعامل اختياري لنوع 'area' (الافتراضي 0)
Optionstableمعاملات اختيارية لشكل العلامة:
sprite = integer|string, name = string, style = integer|string, modifier = integer|string, color = string
OnCreatefunctionالدالة اللي تتشغّل لما تنسوى العلامة
-- Example
-- Import the blips module
local Map = Import 'blips' --[[@as BLIPS]]
local blip = Map.Blips:Create('radius', { -- type can be entity, coords, area, radius
Entity = ped, -- if type is entity, you need to provide a handle
Pos = vector3(2865.88, 475.38, 66.09), -- position
Radius = 50.0, -- if type is radius or area
P7 = 0, -- optional default is 0
Blip = 1673015813, -- blip hash the style of the blip
Scale = vector3(1.0, 1.0, 1.0), -- for type area only
Options = { -- optional
sprite = 1, --string or integer if type is entity or coords
name = 'Test',
modifier = 'BLIP_MODIFIER_MP_COLOR_1', -- int or string
color = 'blue', -- internal color name
},
print('Created', self:GetHandle())
local blue, red, yellow = self:GetBlipColor({ 'blue', 'red', 'yellow' })
self:AddModifier(red)
end
})
local handle = blip:GetHandle()
blip:Remove()المدخلات (Inputs)
هذا الموديول ينستخدم لإنشاء أزرار تحكم لريسورسك، وحدة أو أكثر، بدون ما تحتاج تسوي حلقات وكود كثير كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف المدخلات عشان يسهل التطوير
Input#
استخدم الدوال تحت لإدارة أزرار التحكم
Destroy#
returnnilحذف نسخة المدخل وإيقاف كل المعالجة
RemoveKey#
keystringrequiredإزالة زر معيّن من مدخلات متعددة، أو إذا مدخل واحد يحذفه
Pause#
returnnilإيقاف معالجة المدخل مؤقتاً بدون حذف النسخة
Resume#
returnnilاستئناف معالجة المدخل بعد إيقافه
Update#
datatablerequiredتحديث المعاملات المخصصة للمدخل إذا احتجت
keystring|integerrequiredمطلوب إذا تستخدم مدخلات متعددة - يحدد أي مدخل يتحدث
Start#
returnnilبدء معالجة المدخل إذا ما كان شغّال، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته
Register#
تسجيل مدخل أو أكثر
inputTypestringrequiredنوع المدخل: Press، Hold، Release
keystring|integerrequiredالزر اللي ينراقب (مثلاً E، W) هذي أزرار معرّفة مسبقاً، وتقدر تستخدم أي hash أو نص controls
callbackfunctionrequiredدالة تتشغّل لما ينضغط المدخل - تستقبل (instance, customParams)
statebooleanإذا true، المدخل يبدأ تلقائياً بعد التسجيل، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته
-- Example
-- Import the inputs module
local controls = Import 'inputs' --[[@as INPUTS]]
-- Multiple input support
local inputs = {
{ inputType = "Press", key = "E" },
{ inputType = "Hold", key = "W" },
{ inputType = "Release", key = "S" },
}
local input = controls.Inputs:Register(inputs,function(input, customParams)
if input.key == "E" then
print("E was pressed")
elseif input.key == "W" then
print("W is being held")
elseif input.key == "S" then
print("S was released")
end
end, true) -- auto start on register
input:Destroy()Raycast#
هذا الموديول ينستخدم لفحص خط الرؤية من كاميرا اللعب أو من كيان
يقبل قيم vector3 أو جداول { x, y, z } للإحداثيات ويرجع جدول نتيجة منظم فيه بيانات الإصابة
إذا الـ flag ناقص أو غلط، الموديول يرجع لـ World
Import#
local Raycast = Import('raycast').Raycast --[[@as RAYCAST]]Flags#
أسماء الـ flags المتاحة:
WorldVehiclesPedsRagdollsObjectsPickupsGlassRiversFoliageAll
FromCamera#
إطلاق شعاع من كاميرا اللعب للأمام
distancenumberمسافة الـ raycast، الافتراضي 10.0
flagsstringاسم الـ flag لفحص الشكل، القيم الغلط أو الناقصة ترجع لـ World
ignoreEntityintegerالكيان اللي يتجاهله، الافتراضي PlayerPedId()
options.offsetvector3 | tableإزاحة اختيارية تنضاف لإحداثيات الكاميرا
options.traceTypeintegerنوع تتبّع فحص الشكل، الافتراضي 7
options.timeoutintegerأقصى وقت انتظار للنتيجة بالملي ثانية، الافتراضي 1000
options.waitintegerالتأخير بين محاولات الفحص، الافتراضي 0
returnRAYCAST_RESULTترجع جدول نتيجة فيه hit وcoords وnormal وentity وmaterial وstate وdidHit وhandle
local Raycast = Import('raycast').Raycast --[[@as RAYCAST]]
local result = Raycast:FromCamera(15.0, 'World')
if result.hit then
print('Hit coords:', result.coords)
print('Hit entity:', result.entity)
endFromEntity#
إطلاق شعاع من كيان للأمام باستخدام اتجاهه الحالي
entityintegerrequiredالكيان اللي ينطلق منه الشعاع، ولازم يكون موجود
distancenumberمسافة الـ raycast، الافتراضي 10.0
flagsstringاسم الـ flag لفحص الشكل، القيم الغلط أو الناقصة ترجع لـ World
ignoreEntityintegerالكيان اللي يتجاهله، الافتراضي نفس الكيان المعطى
options.offsetvector3 | tableإزاحة اختيارية تنضاف لإحداثيات الكيان قبل الإطلاق
options.traceTypeintegerنوع تتبّع فحص الشكل، الافتراضي 7
options.timeoutintegerأقصى وقت انتظار للنتيجة بالملي ثانية، الافتراضي 1000
options.waitintegerالتأخير بين محاولات الفحص، الافتراضي 0
returnRAYCAST_RESULTترجع جدول نتيجة فيه hit وcoords وnormal وentity وmaterial وstate وdidHit وhandle
local Raycast = Import('raycast').Raycast --[[@as RAYCAST]]
local horse = GetMount(PlayerPedId())
if horse ~= 0 then
local result = Raycast:FromEntity(horse, 8.0, 'Peds', horse)
if result.hit then
print('Entity raycast hit:', result.entity)
end
endRAYCAST_RESULT#
حقول النتيجة اللي ترجعها FromCamera و FromEntity
hitbooleanTrue لما الفحص يصيب شي
stateintegerحالة فحص الشكل الأصلية
handleintegerرقم فحص الشكل اللي يرجعه الـ native
didHitintegerنتيجة الإصابة الخام من الـ native
coordsvector3إحداثيات الإصابة
normalvector3اتجاه السطح (normal)
entityintegerالكيان المصاب، أو 0 إذا ما انصاب كيان
materialintegerhash المادة اللي يرجعه GetShapeTestResultIncludingMaterial
الـ Prompts
هذا الموديول ينستخدم لإنشاء prompts تتفعّل حسب الإحداثيات، وتقدر تجمع أكثر من prompt وتديرها كوحدة وحدة كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف الـ prompts عشان يسهل التطوير
Prompt#
استخدم الدوال تحت لإدارة الـ prompts
GetHandle#
keystring|integerrequiredمعرّف الـ prompt المحدد، وهو نفس اللي حطيته عند التسجيل
returnintegerجلب handle prompt معيّن بالمفتاح
GetPromptGroup#
keystring|integerrequiredمعرّف الـ prompt المحدد، وهو نفس اللي حطيته عند التسجيل
returnintegerجلب رقم المجموعة لـ prompt معيّن
GetGroupLabel#
keystring|integerrequiredمعرّف الـ prompt المحدد، وهو نفس اللي حطيته عند التسجيل
returnstringجلب اسم المجموعة لـ prompt معيّن
IsRunning#
returnbooleanفحص إذا الـ prompt اللي سجّلته شغّال حالياً
SetLabel#
labelstringrequiredنص جديد للـ prompt
keystring|integerrequiredمعرّف الـ prompt المراد تحديثه، وهو نفس اللي حطيته عند التسجيل
SetEnabled#
enabledbooleanrequiredهل الـ prompt مفعّل أو معطّل
keystring|integerrequiredمعرّف الـ prompt المراد تحديثه، وهو نفس اللي حطيته عند التسجيل
SetVisible#
visiblebooleanrequiredهل الـ prompt ظاهر أو مخفي
keystring|integerrequiredمعرّف الـ prompt المراد تحديثه، وهو نفس اللي حطيته عند التسجيل
SetMashMode#
mashCountintegerrequiredعدد مرات الضغط المتكرر المطلوبة
keystring|integerrequiredمعرّف الـ prompt المراد تحديثه، وهو نفس اللي حطيته عند التسجيل
SetMashIndefinitelyMode#
keystring|integerrequiredمعرّف الـ prompt اللي تحطه على وضع ضغط متكرر بلا حد، وهو نفس اللي حطيته عند التسجيل
Start#
returnnilبدء نظام الـ prompts إذا ما كان شغّال، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته
Pause#
returnnilإيقاف نظام الـ prompts مؤقتاً بدون حذفه
Resume#
returnnilاستئناف نظام الـ prompts بعد إيقافه
Remove#
keystringrequiredمعرّف الـ prompt المراد إزالته إذا متعدد، وإذا واحد ينحذف
Destroy#
returnnilحذف نظام الـ prompts بالكامل
Register#
تسجيل prompts
coordsvector3requiredإحداثيات المركز اللي تكون فيها الـ prompts نشطة
distancenumberنطاق التفعيل من الإحداثيات (الافتراضي 2.0)
labelstringrequiredاسم المجموعة اللي يظهر فوق مجموعة الـ prompts
sleepintegerوقت الانتظار لما تكون برا النطاق (الافتراضي 700ms)
markertableإعدادات marker اختيارية: type، color = {r,g,b,a}، distance، scale = {x,y,z} وتنفع للتصحيح كمان
promptsarrayrequiredمصفوفة prompts فيها: type، key، label، mode، ومعاملات خاصة بكل وضع
الأنواع: Press، Hold، Release، Standard، Pressed، Released، Mash
الأوضاع: Hold (holdTime)، Timed (timedMode)، Mash (mashCount)، Standard (releaseMode)، Standardized (eventHash)
callbackfunctionrequiredدالة تتشغّل لما ينضغط أي prompt - تستقبل (prompt, index, instance, value).
value هو العنصر الحالي من جدول locations، عشان ما تحتاج تدوّر عليه مرة ثانية يدوياً.
statebooleanإذا true، الـ prompts تبدأ تلقائياً بعد التسجيل (الافتراضي false)، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته
-- Example
-- Import the prompts module
local Game = Import 'prompts' --[[@as PROMPTS]]
local data = {
locations = {
{ -- index 1
coords = vector3(2868.43, 480.19, 65.02), -- distance based prompts
label = 'group label', -- group label
distance = 2.0, -- distance from coords
marker = { -- optional marker
type = 0x94FDAE17,
color = { r = 0, g = 255, b = 0, a = 96 },
distance = 4.0,
scale = { x = 2.0, y = 2.0, z = 0.5 },
}
}
},
sleep = 700, -- sleep time when not in range
prompts = { -- group prompts or single prompt
{ type = 'Press', key = 'G', label = 'press', mode = 'Standard' },
{ type = 'Hold', key = 'E', label = 'hold', mode = 'Hold', holdTime = 3000 }
}
}
local prompt = Game.Prompts:Register(data, function(prompt, index, self, location)
-- location is the current entry from data.locations[index]
if index == 1 and location.label == 'group label' then
if prompt.key == 'G' then
print('G pressed')
elseif prompt.key == 'E' then
print('E held for 3 seconds')
end
end
end, true) -- auto start on register
prompt:Destroy() -- the lib it self will destroy any prompt on script restartالأوامر
هذا الموديول ينستخدم لتسجيل أوامر للكلاينت/السيرفر مع صلاحيات واقتراحات وفحص للمعاملات كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف الأوامر عشان يسهل التطوير، وإذا الأمر نشط والاقتراح ما انحدد يضاف عند التسجيل، راح ينضاف تلقائياً لما تنختار الشخصية
Command#
استخدم الدوال تحت لإدارة الأوامر
Remove#
returnnilيحذف الأمر واقتراحه من الشات
AddSuggestion#
returnnilيضيف اقتراح الأمر للشات
RemoveSuggestion#
returnnilيحذف اقتراح الأمر من الشات
Pause#
returnnilإيقاف الأمر مؤقتاً بدون حذفه (يعطّل الأمر مؤقتاً)
Resume#
returnnilاستئناف الأمر بعد إيقافه
Destroy#
returnnilحذف نسخة الأمر بالكامل وتنظيفها
Start#
addSuggestionbooleanهل يضاف اقتراح الشات عند تسجيل الأمر، استخدمه وقت التشغيل بس، لأن الاقتراح افتراضياً ينضاف تلقائياً لما اللاعب يختار شخصيته
returnnilبدء/تفعيل الأمر
OnExecute#
callbackfunctionrequiredتتشغّل لما يتنفذ الأمر
OnError#
callbackfunctionتتشغّل لما يكون في الأمر أخطاء
Register#
تسجيل أمر
namestringrequiredاسم الأمر (بدون /)
Suggestiontableإعدادات اقتراح الشات مع Description ومصفوفة Arguments
Permissionstableإعدادات الصلاحيات مع مجموعات Ace
OnExecutefunctionrequiredدالة تتشغّل لما يتنفذ الأمر - تستقبل (args, rawCommand, instance)
OnErrorfunctionدالة تتشغّل عند أخطاء الأمر - تستقبل نوع الخطأ كنص
statebooleanإذا true، الأمر يبدأ تلقائياً بعد التسجيل، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته
-- Example
-- Import the commands module
local Commands = Import 'commands' --[[@as COMMANDS]]
local command = Commands.Command:Register("mycommand", {
Suggestion = { -- optional
Description = "My custom command description",
Arguments = {
-- if type is number or integer, it will be converted to a number
-- if type is message, it will give it as a message
{ name = "playerId", help = "Target player ID", type = "integer", required = true },
{ name = "amount", help = "Amount value", type = "number", required = true },
{ name = "message", help = "Optional message", type = "message"}
}
},
Permissions = { -- optional
Ace = "group.admin" -- Restrict to admin group, or remove for public command
},
rawCommand, instance)
print("Command executed with args:", json.encode(args))
print("Player ID:", args[1]) -- integer type
print("Amount:", args[2]) -- number type
print("Message:", args[3]) -- message type (remaining args combined)
end,
if errorType == 'missing_arguments' then
print('Usage: /mycommand <playerId> <amount> [message]')
elseif errorType == 'missing_permission' then
print('You do not have permission to use this command')
elseif errorType == 'command_active' then
print('Command is currently paused')
end
end
}, true) -- Auto-start
-- Control methods
command:Start(true) -- Start and add suggestion if not have been added yet
command:Destroy() -- Clean up completely
-- Argument types:
-- "integer" - converts to number (whole numbers)
-- "number" - converts to number (decimals allowed)
-- "message" - combines remaining arguments into string
-- (no type) - keeps as string
-- Error types:
-- "missing_arguments" - Required argument not provided
-- "missing_permission" - User lacks required permissions
-- "command_active" - Command is paused
-- "missing_target" - Target not found (if applicable)Command#
استخدم الدوال تحت لإدارة أوامر السيرفر
Remove#
returnnilحذف الأمر واقتراحه من كل اللاعبين وصلاحيات ACE
AddSuggestion#
targetintegerrequiredرقم اللاعب اللي ينرسل له الاقتراح
returnnilإضافة اقتراح الأمر لشات لاعب معيّن
RemoveSuggestion#
targetintegerrequiredرقم اللاعب اللي ينحذف منه الاقتراح
returnnilحذف اقتراح الأمر من شات لاعب معيّن
Pause#
returnnilإيقاف الأمر مؤقتاً بدون حذفه (تعطيل مؤقت)
Resume#
returnnilاستئناف الأمر بعد إيقافه
Destroy#
returnnilحذف نسخة الأمر بالكامل وتنظيفها
Start#
returnnilبدء/تفعيل الأمر وتسجيل صلاحيات ACE إذا محددة
OnExecute#
callbackfunctionrequiredتعيين أو تحديث دالة الـ callback اللي تتشغّل لما يتنفذ الأمر
OnError#
callbackfunctionrequiredتعيين أو تحديث دالة الـ callback اللي تتشغّل لما يكون في الأمر أخطاء
Register#
تسجيل أمر للسيرفر
namestringrequiredاسم الأمر (بدون /)
Suggestiontableإعدادات اقتراح الشات مع Description ومصفوفة Arguments
- Description: وصف الأمر
- Arguments: معاملات الأمر
- name: اسم المعامل
- help: شرح المعامل
- type: نوع المعامل، إذا number أو integer يتحوّل لرقم، وإذا message ينعطى كرسالة
- required: هل المعامل مطلوب
Suggestion = { -- optional
Description = "Admin command with complex permissions",
Arguments = {
{ name = "playerId", help = "Target player ID", type = "integer", required = true },
{ name = "amount", help = "Amount value", type = "number", required = true },
{ name = "message", help = "Optional message", type = "message" }
}
}Permissionstableإعدادات صلاحيات متقدمة مع Ace والوظايف والمجموعات و CharIds
- Ace: صلاحية ACE (تتغلب على الباقي)، خلها false إذا ما تبي تستخدم صلاحيات ace
- Groups: صلاحيات المجموعات مع قسم users (جدول المستخدمين) وقسم characters (جدول الشخصيات)
- Jobs: صلاحيات حسب الوظيفة مع تقييد اختياري بالرتبة
- CharIds: صلاحيات حسب أرقام شخصيات معيّنة
Permissions = { -- optional
Ace = "group.admin", -- ACE permission (overrides others) leave false if you dont want to use ace permissions
Groups = { -- optional
users = {
admin = true,
moderator = true
},
characters = {
gang_leader = true
}
},
Jobs = { -- optional
Police = { -- jobname
[0] = false,
[1] = true
},
Sheriff = true -- All ranks allowed
},
CharIds = { -- optional
[123] = true, -- Specific character ID
[456] = true
},
}OnExecutefunctionrequiredدالة تتشغّل لما يتنفذ الأمر - تستقبل (source, args, rawCommand, instance)
OnErrorfunctionدالة تتشغّل عند أخطاء الأمر - تستقبل نوع الخطأ كنص
statebooleanإذا true، الأمر يبدأ تلقائياً بعد التسجيل (الافتراضي false)
-- Example
-- Import the server commands module
local LIB = Import 'commands' --[[@as COMMANDS]]
local command = LIB.Command:Register("commandName", {
Suggestion = { -- optional
Description = "Admin command with complex permissions",
Arguments = {
{ name = "playerId", help = "Target player ID", type = "integer", required = true },
{ name = "amount", help = "Amount value", type = "number", required = true },
{ name = "message", help = "Optional message", type = "message" }
}
},
Permissions = { -- optional
Ace = "group.admin", -- ACE permission (overrides others) leave false if you dont want to use ace permissions
Jobs = { -- optional
Police = { -- jobname
[0] = false, -- Rank 0 not allowed
[1] = true, -- Rank 1+ allowed
},
Sheriff = true -- All ranks allowed
},
Groups = { -- optional
users = {
admin = true,
moderator = true
},
characters = {
gang_leader = true
}
},
CharIds = { -- optional
[123] = true, -- Specific character ID
[456] = true
}
},
args, rawCommand, instance)
print("Command executed by source:", source)
print("Player ID:", args[1]) -- player type (validated)
print("Amount:", args[2]) -- number type
print("Message:", args[3]) -- message type
end,
if errorType == 'missing_arguments' then
print('Usage: /admincommand <playerId> <amount> [message]')
elseif errorType == 'missing_permission' then
print('You do not have permission to use this command')
elseif errorType == 'missing_job' then
print('You do not have the required job')
elseif errorType == 'missing_grade' then
print('You do not have the required job rank')
elseif errorType == 'missing_group' then
print('You do not have the required group')
elseif errorType == 'missing_character' then
print('Your character is not authorized')
elseif errorType == 'missing_user' then
print('User not found or console command not supported')
elseif errorType == 'command_active' then
print('Command is currently paused')
end
end
}, true) -- Auto-start
-- Control methods
command:Destroy() -- Clean up completely
-- Server-specific features:
-- - Automatic ACE permission management
-- - Complex job/grade validation
-- - Character and user group permissions
-- - Per-player suggestion management
-- - Console command restriction (source = 0)
-- Error types (additional server-side):
-- "missing_user" - User not found or console command
-- "missing_job" - Player doesn't have required job
-- "missing_grade" - Player doesn't have required job rank
-- "missing_group" - Player doesn't have required group
-- "missing_character" - Character not authorized
-- "missing_state" - State validation failed
-- Permission priority:
-- 1. ACE permissions (highest) all others will be ignored
-- 2. Job permissions
-- 3. Group permissions
-- 4. Character ID permissionsالنقاط
هذا الموديول ينستخدم لإنشاء مناطق دخول/خروج حسب الإحداثيات مع كشف النطاق، وتقدر تسجّل أكثر من نقطة وتديرها كل وحدة لحالها كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف النقاط عشان يسهل التطوير
Point#
استخدم الدوال تحت لإدارة النقاط
IsPointActive#
idstring|integerrequiredالمعرّف الفريد للنقطة المراد فحصها
returnbooleanترجع true إذا النقطة نشطة ومو معطّلة
IsPointInside#
idstring|integerrequiredالمعرّف الفريد للنقطة المراد فحصها
returnbooleanترجع true إذا اللاعب حالياً داخل نطاق النقطة
IsPointOutside#
idstring|integerrequiredالمعرّف الفريد للنقطة المراد فحصها
returnbooleanترجع true إذا اللاعب حالياً برا نطاق النقطة
UpdatePoint#
idstring|integerrequiredالمعرّف الفريد للنقطة المراد تحديثها
datatablerequiredبيانات نقطة جديدة تستبدل إعدادات النقطة الحالية
RemovePoint#
idstring|integerrequiredالمعرّف الفريد للنقطة المراد إزالتها
returnnilيزيل النقطة المحددة من النسخة
PausePoint#
idstring|integerrequiredالمعرّف الفريد للنقطة المراد إيقافها مؤقتاً
returnnilيعطّل النقطة المحددة بدون ما يزيلها
ResumePoint#
idstring|integerrequiredالمعرّف الفريد للنقطة المراد استئنافها
returnnilيعيد تفعيل نقطة كانت موقفة
Start#
returnnilبدء نظام النقاط إذا ما كان شغّال، ويبدأ يراقب موقع اللاعب
Pause#
returnnilإيقاف نظام النقاط كامل مؤقتاً بدون حذفه
Resume#
returnnilاستئناف نظام النقاط بعد إيقافه
Destroy#
returnnilحذف نسخة النقاط بالكامل وتنظيف كل النقاط
DebugPoints#
returnnilتفعيل علامات التصحيح المرئية للنقاط اللي مفعّل فيها debug
Register#
تسجيل نقاط حسب الإحداثيات لكشف الدخول/الخروج
Argumentsarrayrequiredمصفوفة إعدادات النقاط، كل نقطة لازم يكون لها id فريد وإحداثيات مركز ونطاق
- id: معرّف فريد للنقطة (نص/رقم)
- center: إحداثيات مركز النقطة (vector3)
- radius: نطاق الكشف حول المركز (رقم)
- wait: فترة الفحص بالملي ثانية (اختياري، الافتراضي 500)
- debug: تفعيل علامة تصحيح مرئية (اختياري، boolean)
- deActivate: إذا true، النقطة تبدأ معطّلة ولازم تفعّلها يدوياً (اختياري، boolean)
-- supports multiple points
Arguments = {
{
id = 'bank_entrance',
center = vector3(2843.49, 474.49, 64.03),
radius = 15.0,
wait = 500,
debug = true,
deActivate = false,
}
}OnEnterfunctionrequiredدالة تتشغّل لما يدخل اللاعب أي نقطة - تستقبل (point, distance)
OnExitfunctionrequiredدالة تتشغّل لما يطلع اللاعب من أي نقطة - تستقبل (point, distance)
statebooleanإذا true، نظام النقاط يبدأ تلقائياً بعد التسجيل، وإلا استخدم دالة Start عشان تشغّله
-- Example
-- Import the points module
local GamePoints = Import 'points' --[[@as POINTS]]
local points = GamePoints.Points:Register({
Arguments = {
{
id = 'bank_entrance', -- unique identifier
center = vector3(2843.49, 474.49, 64.03), -- center coordinates
radius = 15.0, -- detection radius
wait = 500, -- check interval (ms)
debug = true, -- show debug marker
deActivate = true, -- start active? remove to start active
},
{
id = 'shop_door',
center = vector3(2884.03, 484.19, 66.73),
radius = 10.0,
wait = 300,
debug = true,
},
},
distance)
print("Entered point:", point.id, "Distance:", distance)
if point.id == 'bank_entrance' then
print("Welcome to the bank!")
elseif point.id == 'shop_door' then
print("Welcome to the shop!")
end
end,
distance)
print("Exited point:", point.id, "Distance:", distance)
if point.id == 'bank_entrance' then
print("Left the bank area")
elseif point.id == 'shop_door' then
print("Left the shop area")
end
end
}, true) -- Auto-start
-- Control methods
points:PausePoint('shop_door') -- Pause specific point
points:ResumePoint('shop_door') -- Resume specific point
points:RemovePoint('bank_entrance') -- Remove specific point
-- Check point status
local isActive = points:IsPointActive('shop_door')
local isInside = points:IsPointInside('shop_door')
local isOutside = points:IsPointOutside('shop_door')
-- System control
points:Pause() -- Pause entire system
points:Resume() -- Resume entire system
points:Destroy() -- Clean up completelyPolyZones#
هذا الموديول ينستخدم لإنشاء مناطق كشف بشكل مضلع أو دائرة أو مربع مع فلترة بالارتفاع، رسم للتصحيح، و callbacks للدخول/الوجود داخلها/الخروج كل شي تنشئه كائن مستقل: كل نسخة منطقة خاصة بالسكربت اللي استوردها وتنحذف تلقائياً لما يعيد الريسورس التشغيل
PolyZone#
استخدم الدوال تحت لتسجيل وإدارة أشكال المناطق المتقدمة
GetId#
returnstring|integerترجع المعرّف الفريد للمنطقة (يتولّد تلقائياً إذا ما انعطى)
GetType#
returnstringترجع نوع المنطقة poly أو circle أو box
IsRunning#
returnbooleanترجع true لما تكون حلقة فحص المنطقة شغّالة حالياً
IsInside#
returnbooleanترجع true إذا اللاعب المحلي حالياً داخل المنطقة
SetCallbacks#
cbEnterfunctionتستبدل الـ callback onEnter (تستقبل نسخة المنطقة وإحداثيات اللاعب)
cbExitfunctionتستبدل الـ callback onExit (تستقبل نسخة المنطقة وإحداثيات اللاعب)
cbInsidefunctionتستبدل الـ callback onInside اللي يتشغّل كل tick وأنت داخل المنطقة
UpdatePolygon#
pointsarrayتحدّث نقاط المضلع (قائمة vector3) وتعيد حساب الحدود، للمناطق المضلعة فقط
UpdateCircle#
centervector3تحدّث موقع مركز الدائرة
radiusnumberتحدّث نصف قطر الدائرة، للمناطق الدائرية فقط
UpdateBox#
centervector3تحدّث موقع مركز المربع
lengthnumberتحدّث طول المربع، للمناطق المربعة فقط
widthnumberتحدّث عرض المربع، للمناطق المربعة فقط
headingnumberاتجاه جديد اختياري بالدرجات للمنطقة المربعة
SetHeight#
minZnumberتحدد أقل ارتفاع Z مسموح قبل ما تعتبر المنطقة اللاعب برّاها
maxZnumberتحدد أعلى ارتفاع Z مسموح قبل ما تعتبر المنطقة اللاعب برّاها
SetDebug#
enabledbooleanتفعّل أو تعطّل رسم التصحيح (تبدأ حلقة التصحيح تلقائياً لما تكون المنطقة شغّالة)
SetTickRates#
outsideMsnumberتحدد فترة الفحص بالملي ثانية وقت ما اللاعب برا المنطقة (الافتراضي 200)
insideMsnumberتحدد فترة الفحص بالملي ثانية وقت ما اللاعب داخلها (الافتراضي 1)
Start#
returnnilتبدأ الخيط الخلفي اللي يفحص المنطقة، وتشغّل رسم التصحيح تلقائياً إذا مفعّل
Pause#
returnnilتوقف المنطقة مؤقتاً بدون مسح الـ callbacks أو بيانات الشكل
Resume#
returnnilتعيد تشغيل منطقة موقفة وترجع للكشف
Destroy#
returnnilتعطّل المنطقة وتمسح إعداداتها (المفروض تتخلص من النسخة بعدها)
Register#
تسجيل مناطق مضلعة أو دائرية أو مربعة مع callbacks وتشغيل تلقائي اختياري
datatablerequiredجدول إعدادات المنطقة:
- id: معرّف فريد اختياري نص أو رقم (
polyzone_<timestamp>إذا ما انحط) - type: نوع المنطقة
polyأوcircleأوbox(الافتراضيpoly، ما يفرق بين الأحرف الكبيرة والصغيرة) - sleep: الفترة بالملي ثانية وقت ما تكون برا المنطقة (الافتراضي 200)
- sleepInside: الفترة بالملي ثانية وقت ما تكون داخل المنطقة (الافتراضي 1)
- padding: أمتار إضافية تنضاف لنصف قطر الحدود للرفض المبكر (الافتراضي 1.5)
- debug: تفعيل رسم التصحيح للمنطقة (boolean)
- minZ / maxZ: حدود ارتفاع اختيارية تقيّد الكشف
- onEnter(zone, coords): callback يتشغّل لما يدخل اللاعب المنطقة
- onInside(zone, coords): callback اختياري يتشغّل كل tick وقت ما اللاعب داخلها
- onExit(zone, coords): callback يتشغّل لما يطلع اللاعب من المنطقة
- المضلع: أعطِ
pointsفيه 3 قيم vector3 على الأقل وcenterاختياري - الدائرة: أعطِ
centervector3 وradiusرقم (أو جدولsizeبنفس القيم) - المربع: أعطِ
centervector3، وlengthوwidthأرقام، وheadingاختياري (درجات) أو جدولsize{ x, y }
statebooleanإذا true المنطقة تبدأ مباشرة بعد التسجيل (الافتراضي false، وإلا استدعِ Start() يدوياً)
returnPolyZoneترجع نسخة المنطقة عشان تتحكم فيها بالدوال اللي فوق
local PolyZones = Import('polyzones').PolyZones
local stables = PolyZones:Register({
id = 'valentine_stables',
type = 'poly',
points = {
vector3(-546.83, -600.65, 42.23),
vector3(-548.62, -607.16, 42.32),
vector3(-554.35, -605.86, 42.31),
vector3(-552.20, -599.25, 42.27),
vector3(-554.13, -594.14, 42.19),
},
minZ = 41.8,
maxZ = 45.0,
debug = true,
coords)
print(('Entered %s at %.2f %.2f'):format(zone:GetId(), coords.x, coords.y))
end,
print('Left zone', zone:GetId())
end,
}, true) local PolyZones = Import('polyzones').PolyZones
local campfire = PolyZones:Register({
id = 'campfire_radius',
type = 'circle',
center = vector3(-567.97, -594.54, 42.51),
radius = 2.5,
debug = true,
sleepInside = 250,
coords)
print(('Warming up at %.2f %.2f'):format(coords.x, coords.y))
end,
print('Leaving the fire')
end,
}, true) local PolyZones = Import('polyzones').PolyZones
local jailCell = PolyZones:Register({
id = 'jail_cell_a',
type = 'box',
center = vector3(-565.68, -605.77, 42.31),
length = 4.0,
width = 3.0,
heading = 90.0,
minZ = 41.5,
maxZ = 44.0,
}, true)
jailCell:SetDebug(true)
jailCell:SetTickRates(100, 10)Destroy#
instancePolyZoneنسخة المنطقة اللي ترجعها Register
returnnilتوقف المنطقة وتشيلها من المدير وتنظّفها
local PolyZones = Import('polyzones').PolyZones
local zone = PolyZones:Register({
id = 'temp_zone',
type = 'circle',
center = vector3(-100.0, 120.0, 40.0),
radius = 3.0,
}, true)
PolyZones:Destroy(zone)الأحداث (Events)
هذا الموديول ينستخدم لتسجيل مستمعي أحداث اللعبة اللي يلتقطون أحداث اللعبة الأصلية ويعالجونها مع تحليل تلقائي للبيانات كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف مستمعات الأحداث عشان يسهل التطوير
Event#
استخدم الدوال تحت لإدارة مستمعي الأحداث
Start#
returnnilبدء مستمع الحدث ومراقبة الحدث المسجّل
Pause#
returnnilإيقاف مستمع الحدث مؤقتاً بدون حذف النسخة
Resume#
returnnilاستئناف مستمع الحدث بعد إيقافه
Destroy#
returnnilحذف نسخة مستمع الحدث وتنظيفها
DevMode#
enabledbooleanrequiredتفعيل أو تعطيل وضع المطوّر لتصحيح الأحداث
eventsToIgnorestring|arrayأحداث اختيارية يتجاهلها في وضع المطوّر (اسم الحدث كنص أو hash)
returnnilلما يكون مفعّل يسجّل كل الأحداث في المجموعة. استخدم eventsToIgnore عشان تفلتر الإزعاج.
-- Enable dev mode and ignore specific events
event:DevMode(true, {"EVENT_PED_CREATED", "EVENT_PED_DESTROYED"})
-- Enable dev mode for all events
event:DevMode(true)
-- Disable dev mode
event:DevMode(false)Register#
تسجيل مستمع لحدث في اللعبة
eventNamestring|integerrequiredاسم حدث اللعبة (نص) أو الـ hash (رقم) المراد الاستماع له
groupintegerrequiredمجموعة الأحداث المراقبة: 0 لـ SCRIPT_EVENT_QUEUE_AI أو 1 لـ SCRIPT_EVENT_QUEUE_NETWORK
- SCRIPT_EVENT_QUEUE_AI (0): للأحداث المتعلقة بالذكاء الاصطناعي والـ NPC
- SCRIPT_EVENT_QUEUE_NETWORK (1): للأحداث المتعلقة بالشبكة واللاعبين
callbackfunctionrequiredدالة تتشغّل لما يحصل الحدث - تستقبل بيانات الحدث بعد التحليل أو ولا شي إذا الحدث ما فيه بيانات
statebooleanإذا true، مستمع الحدث يبدأ تلقائياً بعد التسجيل، وإلا استخدم دالة Start
-- Example
-- Import the events module
local Game = Import 'events' --[[@as EVENTS]]
-- Register event with automatic data parsing
local event = Game.Events:Register('EVENT_PED_CREATED', 0, function(data)
print("Ped created with data:", json.encode(data, {indent = true}))
end, true) -- Auto-start
-- Developer mode for debugging, dont fire this events when in dev mode
event:DevMode(true, {"EVENT_PED_CREATED","EVENT_VEHICLE_CREATED"}) -- Enable dev mode, ignore these events
-- dev mode enables all events to be triggered
-- Clean up
event:Destroy()DataView#
هذا الموديول يعطي وظائف DataView مثل JavaScript للتعامل مع البيانات الثنائية في Lua مع دعم أنواع بيانات مختلفة وترتيب البايتات هذا الموديول مبني على تطبيق DataView من gottfriedleibniz ويعطي تعامل فعّال مع البيانات الثنائية
DataView#
استخدم الدوال تحت لإدارة البيانات الثنائية
Buffer#
returnstringجلب الـ buffer الثنائي كنص
ByteLength#
returnintegerجلب طول الـ buffer بالبايت
ByteOffset#
returnintegerجلب موقع الإزاحة الحالي داخل الـ buffer
دوال قراءة أنواع البيانات#
دوال القراءة المتاحة لقراءة أنواع بيانات مختلفة:
GetInt8(offset, endian)- قراءة عدد صحيح 8-بت بإشارةGetUint8(offset, endian)- قراءة عدد صحيح 8-بت بدون إشارةGetInt16(offset, endian)- قراءة عدد صحيح 16-بت بإشارةGetUint16(offset, endian)- قراءة عدد صحيح 16-بت بدون إشارةGetInt32(offset, endian)- قراءة عدد صحيح 32-بت بإشارةGetUint32(offset, endian)- قراءة عدد صحيح 32-بت بدون إشارةGetInt64(offset, endian)- قراءة عدد صحيح 64-بت بإشارةGetUint64(offset, endian)- قراءة عدد صحيح 64-بت بدون إشارةGetFloat32(offset, endian)- قراءة عدد عشري 32-بتGetFloat64(offset, endian)- قراءة عدد double 64-بتGetString(offset, endian)- قراءة نص ينتهي بـ nullGetLuaInt(offset, endian)- قراءة عدد صحيح LuaGetLuaNum(offset, endian)- قراءة رقم Lua
offsetintegerrequiredإزاحة البايت من بداية الـ buffer للقراءة منها
endianbooleanترتيب البايتات: true لـ big-endian، و false/nil لـ little-endian
returnnumber|string|nilالقيمة المقروءة، أو nil إذا الإزاحة برا الحدود
دوال قراءة بحجم ثابت#
GetFixedString(offset, length, endian)- قراءة نص بطول ثابتGetFixedInt(offset, length, endian)- قراءة عدد صحيح بإشارة بحجم ثابتGetFixedUint(offset, length, endian)- قراءة عدد صحيح بدون إشارة بحجم ثابت
offsetintegerrequiredإزاحة البايت من بداية الـ buffer
lengthintegerrequiredعدد البايتات المراد قراءتها
endianbooleanترتيب البايتات: true لـ big-endian، و false/nil لـ little-endian
SubView#
offsetintegerrequiredإزاحة البايت اللي ينسوى منها العرض الفرعي
returnDataViewإنشاء DataView جديد يشارك نفس الـ buffer بس بإزاحة مختلفة
دوال كتابة أنواع البيانات#
دوال الكتابة المتاحة لكتابة أنواع بيانات مختلفة:
SetInt8(offset, value, endian)- كتابة عدد صحيح 8-بت بإشارةSetUint8(offset, value, endian)- كتابة عدد صحيح 8-بت بدون إشارةSetInt16(offset, value, endian)- كتابة عدد صحيح 16-بت بإشارةSetUint16(offset, value, endian)- كتابة عدد صحيح 16-بت بدون إشارةSetInt32(offset, value, endian)- كتابة عدد صحيح 32-بت بإشارةSetUint32(offset, value, endian)- كتابة عدد صحيح 32-بت بدون إشارةSetInt64(offset, value, endian)- كتابة عدد صحيح 64-بت بإشارةSetUint64(offset, value, endian)- كتابة عدد صحيح 64-بت بدون إشارةSetFloat32(offset, value, endian)- كتابة عدد عشري 32-بتSetFloat64(offset, value, endian)- كتابة عدد double 64-بتSetString(offset, value, endian)- كتابة نص ينتهي بـ nullSetLuaInt(offset, value, endian)- كتابة عدد صحيح LuaSetLuaNum(offset, value, endian)- كتابة رقم Lua
offsetintegerrequiredإزاحة البايت من بداية الـ buffer للكتابة فيها
valuenumber|stringrequiredالقيمة المراد كتابتها
endianbooleanترتيب البايتات: true لـ big-endian، و false/nil لـ little-endian
returnDataViewترجع نفسها عشان تقدر تسلسل الدوال
دوال كتابة بحجم ثابت#
SetFixedString(offset, length, value, endian)- كتابة نص بطول ثابتSetFixedInt(offset, length, value, endian)- كتابة عدد صحيح بإشارة بحجم ثابتSetFixedUint(offset, length, value, endian)- كتابة عدد صحيح بدون إشارة بحجم ثابت
offsetintegerrequiredإزاحة البايت من بداية الـ buffer
lengthintegerrequiredعدد البايتات لنوع البيانات
valuenumber|stringrequiredالقيمة المراد كتابتها
endianbooleanترتيب البايتات: true لـ big-endian، و false/nil لـ little-endian
ArrayBuffer#
إنشاء buffer ثنائي جديد
lengthintegerrequiredحجم الـ buffer المراد حجزه بالبايت
returnDataViewترجع نسخة DataView جديدة مع buffer محجوز
-- Import the dataview module
local Data = Import 'dataview' --[[@as DATAVIEW]]
-- Create a 64-byte buffer
local buffer = Data.DataView.ArrayBuffer(64)
-- Write different data types
buffer:SetInt32(0, 42) -- Write integer at offset 0
buffer:SetFloat32(4, 3.14159) -- Write float at offset 4
buffer:SetString(8, "Hello") -- Write string at offset 8
-- Read the data back
local intValue = buffer:GetInt32(0) -- 42
local floatValue = buffer:GetFloat32(4) -- 3.14159
local stringValue = buffer:GetString(8) -- "Hello"
print("Buffer length:", buffer:ByteLength()) -- 64
print("Values:", intValue, floatValue, stringValue)Wrap#
تغليف بيانات ثنائية موجودة
binaryDatastringrequiredنص البيانات الثنائية الموجودة المراد تغليفه
returnDataViewترجع نسخة DataView تغلّف البيانات الموجودة
-- Wrap existing binary data
local existingData = string.pack("i4f", 100, 2.718)
local wrappedView = Data.DataView.Wrap(existingData)
-- Read from wrapped data
local intVal = wrappedView:GetInt32(0) -- 100
local floatVal = wrappedView:GetFloat32(4) -- 2.718DataStream#
إنشاء قارئ بيانات متسلسل
dataViewDataViewrequiredنسخة DataView اللي ينسوى منها الـ stream
returnDataStreamترجع DataStream للقراءة المتسلسلة
دوال DataStream المتاحة (تقدّم الإزاحة تلقائياً):
Int8(endian, align),Uint8(endian, align)Int16(endian, align),Uint16(endian, align)Int32(endian, align),Uint32(endian, align)Int64(endian, align),Uint64(endian, align)Float32(endian, align),Float64(endian, align)String(endian, align),LuaInt(endian, align),LuaNum(endian, align)
-- Create buffer with mixed data
local buffer = Data.DataView.ArrayBuffer(32)
buffer:SetInt32(0, 123)
buffer:SetFloat32(4, 4.56)
buffer:SetInt16(8, 789)
-- Create stream for sequential reading
local stream = Data.DataView.DataStream.New(buffer)
-- Read sequentially (offset advances automatically)
local int1 = stream:Int32() -- 123, offset now at 4
local float1 = stream:Float32() -- 4.56, offset now at 8
local int2 = stream:Int16() -- 789, offset now at 10
print("Sequential read:", int1, float1, int2)التحميل (Streaming)
هذا الموديول يعطي دوال مساعدة لتحميل ملفات اللعبة مثل الموديلات والأنيميشنات والتكستشر وغيرها مع تنظيف تلقائي ومعالجة المهلة كل الدوال تتعامل مع عملية التحميل مع فحص صحيح ومعالجة أخطاء، وتمنع المشاكل الشائعة في تحميل الملفات
تحميل الملفات#
استخدم الدوال تحت لتحميل ملفات اللعبة مع تنظيف تلقائي
LoadModel#
modelstring|integerrequiredاسم الموديل (نص) أو الـ hash (رقم) المراد تحميله
timeoutintegerمهلة اختيارية بالملي ثانية عشان يفك تحميل الموديل تلقائياً ويحرر الذاكرة
returnnilيحمّل الموديل ويفحصه، ويرمي خطأ إذا كان غلط أو فشل التحميل خلال 5 ثواني
LoadTextureDict#
dictstringrequiredاسم قاموس التكستشر المراد تحميله
timeoutintegerمهلة اختيارية بالملي ثانية عشان يفك تحميل قاموس التكستشر تلقائياً
returnnilيحمّل قاموس التكستشر مع فحص ومعالجة أخطاء
LoadParticleFx#
dictstringrequiredاسم قاموس المؤثرات (particles) المراد تحميله
timeoutintegerمهلة اختيارية بالملي ثانية عشان يشيل ملف المؤثرات تلقائياً
returnnilيحمّل قاموس المؤثرات عشان تستخدمه مع أنظمة الـ particles
LoadAnimDict#
dictstringrequiredاسم قاموس الأنيميشن المراد تحميله
timeoutintegerمهلة اختيارية بالملي ثانية عشان يشيل قاموس الأنيميشن تلقائياً
returnnilيحمّل قاموس الأنيميشن مع فحص وجوده
LoadWeaponAsset#
weaponstring|integerrequiredاسم السلاح (نص) أو الـ hash (رقم) المراد تحميله
p1integerrequiredمعامل غير معروف (غالباً 31)
p2booleanrequiredمعامل غير معروف (غالباً false)
timeoutintegerمهلة اختيارية بالملي ثانية عشان يشيل ملف السلاح تلقائياً
returnnilيحمّل ملف السلاح مع فحص
LoadMoveNetworkDef#
netDefstringrequiredاسم تعريف move network المراد تحميله
timeoutintegerمهلة اختيارية بالملي ثانية عشان يشيل تعريف الـ network تلقائياً
returnnilيحمّل تعريف move network لأنظمة الحركة المتقدمة
LoadClipSet#
clipSetstringrequiredاسم مجموعة الـ clips المراد تحميلها
timeoutintegerمهلة اختيارية بالملي ثانية عشان يشيل مجموعة الـ clips تلقائياً
returnnilيحمّل مجموعة clips للأنيميشن لطرق مشي الشخصيات
RequestCollisionAtCoord#
coordsvector3requiredالإحداثيات اللي ينحمّل فيها التصادم
returnnilيحمّل بيانات تصادم الأرض عند الإحداثيات المحددة
RequestCollisionForModel#
modelstring|integerrequiredاسم الموديل أو الـ hash اللي ينحمّل له التصادم
returnnilيحمّل بيانات التصادم لموديل معيّن
RequestIpl#
iplstring|integerrequiredاسم IPL (Interior Proxy List) أو الـ hash المراد تحميله
returnnilيحمّل IPL للداخليات أو أجزاء الخريطة، ويحذّر إذا كان محمّل من قبل
LoadScene#
posvector3requiredالموقع اللي ينحمّل المشهد حوله
offsetvector3requiredالإزاحة من الموقع
radiusnumberrequiredالنطاق اللي ينحمّل داخله المشهد
p7integerrequiredمعامل غير معروف (غالباً 0)
returnnilيحمّل منطقة العالم حول الكيان - استخدمه بحذر لأنه ممكن يسبب كراش مع كثرة الـ MLOs
Import#
استيراد موديول streaming
-- Import the streaming module
local Assets = Import 'streaming' --[[@as STREAMING]]
-- Use any function
Assets.Streaming.LoadModel('A_C_BEAR_01')
Assets.Streaming.LoadAnimDict('amb@world_human_drinking@coffee@male@idle_a')
الكلاس
هذا الموديول يعطي نظام برمجة كائنية كامل لـ Lua مع كلاسات ووراثة وأعضاء خاصة ودوال قراءة/تعديل تلقائية يدعم أنماط OOP التقليدية في Lua والطرق المنظمة الحديثة مع إدارة تلقائية للخصائص مستوحى من كلاسات JavaScript
نظام OOP#
استخدم الدوال تحت لإنشاء كلاسات بدعم OOP كامل
Create#
basetable|classالكلاس الأساسي اللي يورث منه، أو جدول بالدوال/الخصائص الأولية
classNamestringاسم اختياري للكلاس (ينستخدم في رسائل الخطأ)
returnclassيرجع كلاس جديد يقدر ينشئ نسخ بـ :New()
-- Import the class module
local Lib = Import 'class' --[[@as CLASS]]
-- Create a basic class
local MyClass = Lib.Class:Create({
constructor = function(self, name)
self.name = name
end,
getName = function(self)
return self.name
end
}, "MyClass")
-- Create instance
local instance = MyClass:New("Test")
print(instance:getName()) -- "Test"- مثال بأسلوب Lua التقليدي
local MyClass = Lib.Class:Create({},"MyClass")
function MyClass:constructor(name)
self.name = name
end
function MyClass:getName()
return self.name
end
local instance = MyClass:New("Test")
print(instance:getName()) -- "Test"New#
...anyالمعاملات اللي تنرسل للـ constructor
returninstanceيرجع نسخة جديدة من الكلاس
ينشئ نسخ جديدة من الكلاس. يدعم constructors بالجدول أو بالمعاملات.
-- Table-based constructor
local instance1 = MyClass:New({
name = "John",
age = 30
})
-- Argument-based constructor
local instance2 = MyClass:New("John", 30)وراثة الكلاسات#
الكلاسات تقدر ترث من كلاسات ثانية وتحصل على كل دوال وخصائص الكلاس الأب.
-- Base class
local Entity = Lib.Class:Create({
constructor = function(self, id)
self.id = id
self.created = os.time()
end,
getId = function(self)
return self.id
end,
getInfo = function(self)
return "Entity " .. self.id
end
}, "Entity")
-- Inherited class
local Ped = Lib.Class:Create(Entity, "Ped")
function Ped:constructor(id, model)
self:super(id) -- Call parent constructor
self.model = model
end
function Ped:getInfo()
return "Ped " .. self.id .. " (" .. self.model .. ")"
end
-- Usage
local ped = Ped:New(123, "A_M_M_FARMER_01")
print(ped:getInfo()) -- "Ped 123 (A_M_M_FARMER_01)"
print(ped:getId()) -- 123 (inherited method)super#
...anyالمعاملات اللي تنرسل لـ constructor الأب
returnnilيستدعي constructor الكلاس الأب
ينستخدم داخل الـ constructor عشان يستدعي constructor الكلاس الأب.
local Ped = Lib.Class:Create(Entity, "Ped")
function Ped:constructor(id, model)
self:super(id) -- Call parent constructor
self.model = model
endخصائص تلقائية#
عرّف دوال قراءة وتعديل تلقائية للخصائص باستخدام جداول get و set.
local Person = Lib.Class:Create({
constructor = function(self, name, age)
self.name = name
self.age = age
end,
-- can be used to organize your code as well just like JS classes
get = {
name = function(self)
return self.name:upper() -- Always return uppercase
end,
age = function(self)
return self.age
end,
isAdult = function(self)
return self.age >= 18
end
},
-- can be used to organize your code as well just like JS classes
set = {
name = function(self, value)
if type(value) ~= "string" then
error("Name must be a string")
end
self.name = value
end,
age = function(self, value)
if type(value) ~= "number" or value < 0 then
error("Age must be a positive number")
end
self.age = value
end
}
})
local person = Person:New("john", 25)
-- Using getters
print(person.name) -- "JOHN" (automatic uppercase)
print(person.isAdult) -- true
-- Using setters
person.name = "jane" -- Validates and stores
person.age = 30 -- Validates and storesالخصائص والدوال الخاصة#
الأعضاء اللي تبدأ بشرطة سفلية _ خاصة وما تنوصل إلا من داخل نفس الكلاس.
local BankAccount = Lib.Class:Create({
constructor = function(self, accountNumber, initialBalance)
self._accountNumber = accountNumber -- Private
self._balance = initialBalance -- Private
self.accountType = "Checking" -- Public
end,
-- Public method that accesses private members
getBalance = function(self)
self:_validateAccess() -- Private method call
return self._balance
end,
deposit = function(self, amount)
if amount > 0 then
self._balance = self._balance + amount
return true
end
return false
end,
-- Private method
_validateAccess = function(self)
print("Validating access to account " .. self._accountNumber)
end,
-- Private method
_calculateInterest = function(self)
return self._balance * 0.01
end
}, "BankAccount")
local account = BankAccount:New("12345", 1000)
-- ✅ Public access
print(account:getBalance()) -- 1000
account:deposit(500)
-- ❌ Private access will error
-- print(account._balance) -- ERROR
-- account:_validateAccess() -- ERRORالوراثة والخصوصية#
الأعضاء الخاصة خاصة بالكلاس وما تقدر الكلاسات الفرعية توصل لها.
local Vehicle = Lib.Class:Create({
constructor = function(self, model)
self._engine = "V8" -- Private to Vehicle
self.model = model -- Public
end,
getEngineInfo = function(self)
return "Engine: " .. self._engine -- ✅ Same class access
end,
_startEngine = function(self)
print("Starting " .. self._engine .. " engine")
end
})
local Car = Lib.Class:Create(Vehicle, "Car")
function Car:constructor(model, doors)
self:super(model)
self.doors = doors
-- self._engine = "Modified" -- ❌ Would error - can't access parent private
end
function Car:tryAccessPrivate()
-- ❌ Cannot access parent's private members
-- local engine = self._engine -- ERROR
-- self:_startEngine() -- ERROR
print("Cannot access parent private members")
end
local car = Car:New("Mustang", 2)
print(car:getEngineInfo()) -- ✅ "Engine: V8" (via public method)
car:tryAccessPrivate() -- Shows privacy enforcementمثال كامل#
مثال شامل لنظام الكلاسات
-- Import the class module
local Lib = Import 'class' --[[@as CLASS]]
-- Base Entity class
local Entity = Lib.Class:Create({
constructor = function(self, data)
self._id = data.id or 0 -- Private ID
self._position = data.pos or vector3(0,0,0) -- Private position
self.name = data.name or "Entity" -- Public name
self._created = os.time() -- Private creation time
end,
-- Public methods
getId = function(self)
return self._id
end,
getPosition = function(self)
return self._position
end,
setPosition = function(self, pos)
self._position = pos
self:_onPositionChanged() -- Private method call
end,
getAge = function(self)
return os.time() - self._created
end,
-- Private methods
_onPositionChanged = function(self)
print("Entity " .. self._id .. " moved to " .. tostring(self._position))
end,
-- Automatic getters/setters
get = {
displayName = function(self)
return self.name .. " (#" .. self._id .. ")"
end
},
set = {
name = function(self, value)
if type(value) ~= "string" or #value == 0 then
error("Name must be a non-empty string")
end
self.name = value
end
}
}, "Entity")
-- Ped class inheriting from Entity
local Ped = Lib.Class:Create(Entity, "Ped")
function Ped:constructor(data)
self:super(data) -- Call parent constructor
self._model = data.model or "A_M_M_FARMER_01" -- Private model
self._health = data.health or 100 -- Private health
self.faction = data.faction or "Civilian" -- Public faction
end
function Ped:spawn()
local pos = self:getPosition()
local handle = CreatePed(joaat(self._model), pos.x, pos.y, pos.z, 0.0, true, false, false, false)
self._handle = handle
print("Spawned " .. self.displayName .. " at " .. tostring(pos))
return handle
end
function Ped:damage(amount)
self._health = math.max(0, self._health - amount)
if self._health <= 0 then
self:_onDeath()
end
end
-- Private method
function Ped:_onDeath()
print(self.displayName .. " has died")
if self._handle then
DeletePed(self._handle)
end
end
-- Getters for private properties
Ped.get.health = function(self)
return self._health
end
Ped.get.model = function(self)
return self._model
end
-- Usage
local ped = Ped:New({
id = 123,
name = "John Marston",
pos = vector3(100, 200, 300),
model = "CS_JOHNMARSTON",
health = 150,
faction = "Van der Linde Gang"
})
-- Public interface
print(ped.displayName) -- "John Marston (#123)"
print("Health:", ped.health) -- 150 (via getter)
print("Age:", ped:getAge(), "seconds old")
ped:setPosition(vector3(150, 250, 350))
ped:spawn()
ped:damage(50)
print("Health after damage:", ped.health) -- 100
-- Validation works
ped.name = "Arthur Morgan" -- ✅ Valid
-- ped.name = "" -- ❌ Would error
-- Privacy enforced
-- print(ped._health) -- ❌ Would error
-- ped:_onDeath() -- ❌ Would error
أسلوب Lua التقليدي#
باستخدام صيغة دوال lua التقليدية
local Lib = Import 'class' --[[@as CLASS]]
-- Create class with traditional Lua methods
local Timer = Lib.Class:Create({},"Timer")
function Timer:constructor(name, duration)
self.name = name or "Timer"
self._startTime = nil
self._duration = duration or 5000
self._isRunning = false
end
function Timer:start()
self._startTime = GetGameTimer()
self._isRunning = true
print(self.name .. " started for " .. self._duration .. "ms")
end
function Timer:stop()
self._isRunning = false
print(self.name .. " stopped")
end
function Timer:isExpired()
if not self._isRunning or not self._startTime then
return false
end
return (GetGameTimer() - self._startTime) >= self._duration
end
function Timer:getTimeLeft()
if not self._isRunning or not self._startTime then
return 0
end
local elapsed = GetGameTimer() - self._startTime
return math.max(0, self._duration - elapsed)
end
-- Usage
local timer = Timer:New("Countdown", 10000)
timer:start()
-- Check in a loop or thread
CreateThread(function()
while not timer:isExpired() do
print("Time left:", timer:getTimeLeft() .. "ms")
Wait(1000)
end
print("Timer expired!")
timer:stop()
end)
الدوال
كلاسات مساعدة للتحكم بسير الكود والتوقيت والتنفيذ المشروط يعطي أنماط Switch-case وفترات متكررة ومهلات لمرة وحدة مع تحكم كامل بحالة التنفيذ مشترك بين بيئة السيرفر والكلاينت
Switch#
استخدم هذي الأدوات للتحكم المتقدم بسير الكود والتوقيت
valueanyالقيمة اللي تتقارن مع الحالات
ينشئ هيكل switch-case يخليك تسلسل الحالات مع حالة افتراضية، مستوحى من JS
-- Import the functions module
local Lib = Import 'functions' --[[@as FUNCTIONS]]
-- Basic switch usage
local result = Lib.Switch(playerLevel)
:case(1, function(value)
return "Beginner"
end)
:case(2, function(value)
return "Intermediate"
end)
:case(3, function(value)
return "Advanced"
end)
:default(function(value)
return "Unknown Level: " .. value
end)
:execute()
print(result)SetInterval#
callbackfunctionrequiredالدالة اللي تتنفذ بشكل متكرر
delayintegerrequiredالتأخير بين كل تنفيذ بالملي ثانية
customArgstableالمعاملات اللي تنرسل لدالة الـ callback
startbooleanهل تبدأ الفترة مباشرة
returnIntervalrequiredيرجع نسخة Interval عشان تتحكم فيها
ينشئ فترة متكررة تنفّذ دالة كل مدة محددة
-- Import the functions module
local Lib = Import 'functions' --[[@as FUNCTIONS]]
-- Create an interval that runs every 5 seconds
local healthCheck = Lib.SetInterval(function(self, playerId)
local player = GetPlayerPed(playerId)
if player and DoesEntityExist(player) then
local health = GetEntityHealth(player)
print("Player " .. playerId .. " health: " .. health)
self:Destroy() -- destroy the interval
end
end, 5000,{GetPlayerServerId(PlayerId())}, true)GetState#
returnbooleanيرجع true إذا الفترة شغّالة، و false إذا موقفة
يرجع الحالة الحالية للفترة
local isRunning = healthCheck:GetState()
print("Interval running: " .. tostring(isRunning))SetTimeout#
callbackfunctionrequiredالدالة اللي تتنفذ بعد التأخير
delayintegerrequiredالتأخير قبل التنفيذ بالملي ثانية
customArgstableالمعاملات اللي تنرسل لدالة الـ callback
returnTimeoutrequiredيرجع نسخة Timeout عشان تتحكم فيها
ينشئ تنفيذ متأخر لمرة وحدة تقدر تتحكم فيه
-- Import the functions module
local Lib = Import 'functions' --[[@as FUNCTIONS]]
-- Create a timeout that executes after 10 seconds
local delayedAction = Lib.SetTimeout(function(message, playerId)
print("Delayed message: " .. message)
end, 10000, {"Welcome to the server!", PlayerId()})GetState#
returnbooleanيرجع true إذا المهلة نشطة، و false إذا موقفة أو تنفذت
Pause#
returnnilيوقف المهلة مؤقتاً ويمنع التنفيذ
Resume#
...anyمعاملات جديدة تنرسل للـ callback، ويقبل تحديث المعاملات مثل دالة update
Update#
...anyمعاملات جديدة تنرسل للـ callback
يحدّث معاملات الـ callback
delayedAction:Update("Modified message", differentPlayerId)Destroy#
returnnilيلغي المهلة وينظّفها بالكامل
المسجّل (Logger)
هذا الموديول المشترك ينستخدم لطباعة سجلات منسّقة فيها الوقت ومستوى السجل وبادئة اختيارية وسياق منظم
الكونسول الأساسي يعرض اسم الريسورس أصلاً، فالمسجّل يضيف بس الوقت والمستوى ورسالتك
سجلات DEBUG معطّلة افتراضياً لين تفعّلها بـ SetDebugEnabled(true) أو تجبرها بخيار debug
Import#
local Logger = Import('logger').Logger --[[@as LOGGER]]شكل المخرجات#
[12:34:56] [INFO] message
[12:34:56] [WARN] [BANK] message | charId=1 money=250
[12:34:56] [ERROR] something failedLog#
الدالة الأساسية اللي تستخدمها كل دوال السجل الثانية
levelstringrequiredالقيم المدعومة INFO و WARN و ERROR و DEBUG
...anyأجزاء الرسالة، والقيم تنضم مع بعض بالترتيب
contexttableجدول سياق اختياري ينضاف كأزواج key=value
options.prefixstringبادئة اختيارية تظهر قبل نص الرسالة
options.debugbooleanيجبر سجل DEBUG حتى لو وضع التصحيح معطّل
options.colorizebooleanحطه false عشان تعطّل ألوان الكونسول
local Logger = Import('logger').Logger --[[@as LOGGER]]
Logger:Log('INFO', 'player connected', {
charId = 12,
source = 4
}, {
prefix = 'CHARACTER'
})Info / Warn / Error / Debug#
دوال مختصرة لمستويات السجل المدعومة
local Logger = Import('logger').Logger --[[@as LOGGER]]
Logger:Info('inventory loaded')
Logger:Warn('low ammo', { weapon = 'WEAPON_REPEATER_CARBINE' })
Logger:Error('failed to save character', { charId = 5 })
Logger:SetDebugEnabled(true)
Logger:Debug('debug output enabled')SetDebugEnabled#
يفعّل أو يعطّل مخرجات التصحيح بشكل عام لنسخة المسجّل هذي
enabledbooleanrequiredحطه true عشان تسمح بسجلات DEBUG، و false عشان تعطّلها
GetDebugEnabled#
يرجع حالة التصحيح الحالية
returnbooleantrue إذا سجلات التصحيح مفعّلة، وإلا false
مثال للكلاينت#
local Logger = Import('logger').Logger --[[@as LOGGER]]
Logger:Info('client logger info output', {
side = 'client',
ped = PlayerPedId()
}, {
prefix = 'TEST'
})مثال للسيرفر#
local Logger = Import('logger').Logger --[[@as LOGGER]]
Logger:SetDebugEnabled(true)
Logger:Debug('server logger debug output', {
side = 'server',
source = source
}, {
prefix = 'TEST'
})الـ Exports
المحدِّد (Selector)
هذا المحدِّد يخليك تختار لاعبين بواجهة NUI ويرجع رقم اللاعب اللي انختار
Select#
allow_selfbooleanالسماح باختيار نفسك
amount_of_playersintegerعدد اللاعبين المراد اختيارهم
distancenumberمسافة اختيار اللاعبين
allow_in_vehiclebooleanالسماح باختيار لاعبين داخل المركبات
allow_on_horsebooleanالسماح باختيار لاعبين على الخيل
playeridintegerرقم اللاعب اللي انختار
local result <const> = exports.jrs_core:Select({
allow_self = true,
amount_of_players = 4,
distance = 8.0,
allow_in_vehicle = true,
allow_on_horse = true
})ProgressBar#
يخليك تنشئ شريط تقدم يظهر على الشاشة لمدة محددة
Start#
textstringrequiredالنص اللي يظهر في شريط التقدم
colorstablerequiredجدول ألوان شريط التقدم: startColor و endColor ألوان النص، و backgroundColor و fillColor ألوان الخلفية والتعبئة في صورة شريط التقدم
durationintegerrequiredالمدة بـ milliseconds لشريط التقدم
typestringrequiredنوع شريط التقدم، المتاح حالياً linear بس
positiontablerequiredجدول موقع شريط التقدم على الشاشة: top و left هي الموقع بـ %
imagestringصورة شريط التقدم، المتاح حالياً png بس
callbackfunctionدالة callback إذا تبي تستخدمه بشكل غير متزامن
returnbooleanنتيجة شريط التقدم true أو false، وإذا false يعني شريط التقدم انلغى
local data = {
text = 'Some text here',
colors = {
-- for text
startColor = 'white', -- starting color of the text
endColor = 'black', -- ending color of the text
-- these colors are filters they dont really represent the color that well but its an option if you want to change it
-- for background
-- https://colorpicker.dev/#21d70d use this website choose hwb and its the first number just add deg to it like this 330deg
-- backgroundColor = '0deg', -- Changes grey bar to blue-ish
--fillColor = '120deg', -- Changes white bar to green-ish
},
duration = 5000,
type = 'linear', -- only linear is avaliable for now
position = { top = 90, left = 50 }, -- in % for position on the screen
image = 'score_timer_extralong', -- only png this is optional you can add your own image , images must be in this script images folder
}
-- SYNC
local result = exports.jrs_core:progressStart(data)
if not result then
print('cancelled')
else
print('completed')
end
--OR ASYNC
exports.jrs_core:progressStart(data, function(result)
if result then
print('Progress bar completed')
else
print('Progress bar cancelled')
end
end)Cancel#
إلغاء شريط التقدم
exports.jrs_core:progressCancel()نسخ
يخليك ترسل طلب نسخ للحافظة من واجهة jrs_core NUI.
copyToClipBoard#
textstringrequiredالنص المراد نسخه للحافظة
exports.jrs_core:copyToClipBoard("Hello from jrs_core")الكثافة
يخليك تشوف أو تغيّر مضاعفات كثافة السكان اللي يتحكم فيها jrs_core وقت التشغيل.
الموديول يحتفظ بقيمة افتراضية ويقدر يطبّق قيمة مؤقتة. إذا فيه قيمة مؤقتة تنستخدم أولاً، وإذا ما فيه تنستخدم القيمة الافتراضية.
أسماء الكثافة الصحيحة هي:
"AnimalDensity"
"HumanDensity"
"PedDensity"
"VehicleDensity"
"ScenarioAnimalDensity"
"ScenarioHumanDensity"
"ScenarioPedDensity"
"ParkedVehicleDensity"
"RandomVehicleDensity"GetDensityMultipliers#
namestringاسم الكثافة. إذا ما انحط يرجع الـ export جدول المضاعفات كامل.
returntableيرجع عنصر كثافة واحد أو جدول الكثافة كامل. العنصر الواحد فيه value المضبوط، وممكن يكون فيه temp_value إذا فيه قيمة مؤقتة نشطة.
local allMultipliers = exports.jrs_core:GetDensityMultipliers()
local vehicleDensity = exports.jrs_core:GetDensityMultipliers("VehicleDensity")
print(vehicleDensity.value, vehicleDensity.temp_value)SetDefaultDensityMultipliers#
sourceintegerrequiredرقم اللاعب المستهدف أو -1 للكل.
namestringrequiredواحد من أسماء الكثافة الصحيحة المذكورة فوق.
valuenumberrequiredقيمة مضاعف الكثافة. استخدم قيم بين 0.0 و 1.0.
local target <const> = source
exports.jrs_core:SetDefaultDensityMultipliers(target, "VehicleDensity", 0.2)SetTemporaryDensityMultipliers#
sourceintegerrequiredرقم اللاعب المستهدف أو -1 للكل.
namestringrequiredواحد من أسماء الكثافة الصحيحة المذكورة فوق.
valuenumberrequiredقيمة مضاعف الكثافة، استخدم قيم بين 0.0 و 1.0.
timerintegerوقت اختياري بالثواني قبل ما تنشال قيمة الكثافة المؤقتة تلقائياً.
local target <const> = source
exports.jrs_core:SetTemporaryDensityMultipliers(target, "VehicleDensity", 0.2)RemoveTemporayDensityMultipliers#
sourceintegerrequiredرقم اللاعب المستهدف أو -1 للكل.
namestringrequiredواحد من أسماء الكثافة الصحيحة المذكورة فوق.
local target <const> = source
exports.jrs_core:RemoveTemporayDensityMultipliers(target, "ScenarioHumanDensity")المجمّع (Collector)
ما انطبق للحين
الذاكرة المؤقتة (Cache)
نظام ذاكرة مؤقتة يقلل عدد استدعاءات الـ natives الأكثر استخداماً مثل PlayerPedId
CACHE#
CACHE جدول عام في الكلاينت فيه بيانات مخزّنة لـ Ped،Player،ServerID،Vehicle،Mount،Weapon
هذي تتحدث كل 5 ملي ثانية، و Vehicle و Mount ترجع 0 لما اللاعب مو داخل مركبة أو على مطية
LastVehicle و LastMount و LastWeapon تحتفظ بالقيمة السابقة لما تتغير، وما ترجع 0
returnanyالبيانات المخزّنة
local ped = CACHE.Ped -- current player ped id
local player = CACHE.Player -- current player id
local serverId = CACHE.ServerID -- current player server id
local vehicle = CACHE.Vehicle -- current vehicle or 0 if not in a vehicle
local mount = CACHE.Mount -- current mounted entity or 0 if not mounted
local weapon = CACHE.Weapon -- current held weapon
local isDead = CACHE.IsDead -- current player is dead or not
local lastVehicle = CACHE.LastVehicle -- last vehicle the player was in
local lastMount = CACHE.LastMount -- last mount the player was on
local lastWeapon = CACHE.LastWeapon -- last weapon the player heldCACHE#
هذي تعطيك تحكم أكثر بنظام الذاكرة المؤقتة، وكلها false افتراضياً ولازم تعطّل اللي ما تحتاجه
-- at the top of your client file.
CACHE.SkipWeapon = true -- no need for weapon cache
CACHE.SkipVehicle = true -- no need for vehicle cache
CACHE.SkipMount = true -- no need for mount cache
CACHE.Wait = 500 -- by default is 500 , you can adjust to your needsOnPedChange#
تسجيل callback يتشغّل لما يتغير ped اللاعب، ورقم الـ ped الجديد ينرسل للـ callback
callbackfunctionrequiredالدالة اللي تتشغّل برقم الـ ped الجديد لما يتغير ped اللاعب
CACHE.OnPedChange(function(pedId)
print('ped changed', pedId)
end)OnPlayerDeath#
تسجيل callback يتشغّل لما يموت اللاعب، ويعتمد على فحص IsDead فلازم CACHE.SkipIsDead يبقى false
callbackfunctionrequiredالدالة اللي تتشغّل لما يموت اللاعب
CACHE.OnPlayerDeath(function()
print('player died')
end)