-
Posts
12 -
Joined
-
Last visited
Everything posted by Mohab
-
:جدول المُحتويات مقدمة تحليلية: كيف تُربط MTA:SA مع Discord باستخدام Webhook؟ المفهوم العام (اللوجيك الأساسي) تحليل الكود خطوة بخطوة خلاصة المنطق كاملًا ملاحظات إضافية للمطور مصادر مهمة مقدمة تحليلية: كيف تُربط MTA:SA مع Discord باستخدام Webhook؟ السلام عليكم ورحمة الله وبركاته في هذا المشروع، نريد تمكين اللاعب من إرسال رسالة من داخل اللعبة إلى قناة في Discord. لتحقيق هذا سنستخدم: - أمر داخل اللعبة (command) - كود Lua في سيرفر MTA - خدمة Webhook من Discord - دالة `fetchRemote` في MTA لإرسال البيانات إلى Discord المفهوم العام (اللوجيك الأساسي): 1. اللاعب يكتب أمر داخل اللعبة مثل `/discord مرحباً`. 2. السكربت يقرأ هذا الأمر ويستخرج الرسالة. 3. السكربت يُنشئ رسالة منسّقة (باستخدام JSON). 4. يتم إرسال هذه الرسالة إلى Discord عبر رابط Webhook. 5. Discord يعرض الرسالة داخل القناة المحددة. تحليل الكود خطوة بخطوة: رابط الويب هوك local discordWebhook = "https://discord.com/api/webhooks/...." - هذا هو الرابط الأساسي. - Discord يوفّره لك لكل قناة تريد استقبال الرسائل فيها. - يتم تخزينه في متغير `discordWebhook` لاستخدامه لاحقًا عند الإرسال. دالة تنفيذ الأمر function sendMessageToDiscord(player, command, ...) - هذه الدالة يتم ربطها بالأمر `/discord`. - يتم تنفيذها تلقائيًا عندما يكتب اللاعب الأمر. - البراميتر `player` هو كائن اللاعب الذي نفّذ الأمر. - البراميتر `...` يمثل كل الكلمات التي كتبها اللاعب بعد الأمر. جمع الرسالة local message = table.concat({...}, " ") - يتم دمج الكلمات التي كتبها اللاعب إلى جملة واحدة. - مثلًا: `/discord السلام عليكم يا شباب` → تصبح `"السلام عليكم يا شباب"`. التحقق من وجود رسالة if message == "" then outputChatBox("اكتب رسالة! مثال: /discord مرحبا", player, 255, 0, 0) return end - إذا لم يكتب اللاعب أي شيء، يتم عرض تنبيه داخل اللعبة. - يتم إيقاف تنفيذ الدالة (باستخدام `return`). تجهيز بيانات الرسالة local playerName = getPlayerName(player) - نحصل على اسم اللاعب الذي كتب الرسالة. إعداد شكل الرسالة (باستخدام `embeds`) local webhookData = { username = "MTA:SA Server", -- اسم البوت في Discord embeds = {{ title = "رسالة من اللاعب", description = message, color = 3447003, -- لون الشريط (أزرق) author = {name = playerName}, footer = {text = "MTA:SA Discord Bot"}, timestamp = os.date("!%Y-%m-%dT%H:%M:%SZ") -- وقت الإرسال بصيغة ISO }} } هذا الجزء هو أهم جزء، لأن Discord يستخدم ما يسمى بـ `embeds` لتنسيق الرسائل، ويتضمن: +----------------+----------------------------------------+ | العنصر | وظيفته | +----------------+----------------------------------------+ | username | اسم البوت في الديسكورد | | title | عنوان الرسالة داخل الـ Embed | | description | نص الرسالة الحقيقي | | color | لون الشريط الجانبي (بالـ Hex) | | author.name | اسم مرسل الرسالة (اللاعب) | | footer.text | تذييل صغير | | timestamp | وقت الإرسال بشكل احترافي | +----------------+----------------------------------------+ إرسال البيانات باستخدام fetchRemote fetchRemote(discordWebhook, { method = "POST", headers = {["Content-Type"] = "application/json"}, postData = toJSON(webhookData):sub(2, -2) }, function(responseData, responseInfo) ... end) ما الذي يحدث هنا بالضبط؟ fetchRemote: دالة من MTA لإرسال طلب HTTP إلى عنوان خارجي (هنا Discord). method = "POST": نوع الطلب الذي نستخدمه لإرسال بيانات إلى الخادم (Discord في هذه الحالة). headers: نقوم بإخبار Discord بأن نوع البيانات التي نرسلها هي JSON. postData: نقوم بتحويل البيانات إلى JSON باستخدام دالة toJSON، ثم نحذف الأقواس الزائدة [] باستخدام :sub(2, -2) لتهيئة البيانات بشكل صحيح. function(responseData, responseInfo): هذه دالة "رد الفعل"، التي تُنفذ عندما يرد Discord على الطلب. التعامل مع النتيجة if responseInfo.success then outputChatBox("تم إرسال رسالتك إلى Discord!", player, 0, 255, 0) - إذا تم إرسال الرسالة بنجاح، يُبلغ اللاعب برسالة نجاح. التعامل مع الأخطاء else local statusCode = responseInfo.statusCode or "غير معروف" outputChatBox("فشل الإرسال! (الكود: " .. statusCode .. ")", player, 255, 0, 0) - إذا فشل الإرسال، يتم طباعة الكود الخطأ، مثل: 400: خطأ في البيانات (ربما الرسالة فارغة أو JSON غير صالح). 401 / 404: رابط Webhook غير صحيح أو تم حذفه. 429: تم إرسال عدد كبير جدًا من الرسائل (تم تجاوز الحد المسموح به). ربط الأمر مع الدالة addCommandHandler("discord", sendMessageToDiscord) - هذا السطر هو الذي يربط `/discord` مع الدالة التي كتبناها. - أي شخص يكتب هذا الأمر يتم تنفيذ الكود أعلاه له. خلاصة المنطق كاملًا: ملاحظات إضافية للمطور: - Webhooks يمكن استخدامها لعدة استخدامات مثل: - إرسال تنبيهات عند دخول أو خروج اللاعبين. - إرسال رسائل النظام. - تتبع الأخطاء في السكربتات. - يمكنك تحسين السكربت بإضافة: - صورة اللاعب. - أزرار تفاعلية (عبر Discord Buttons). - أكثر من Embed في نفس الرسالة. مصادر مهمة: - رابط السكريبت كامل على جيت هب مع الشرح - رابط السكربت على موقع المودات بالتوفيق لكم
-
Wish you all the best ! ??
-
Happy new year ?
-
Seems like a good idea, well done.. I will try it later good luck
-
@Burak5312 @The_GTA Thank you guys it really helped me .
-
I forgot one line at client side local ifp = engineLoadIFP( "otur.ifp", "otur" ) so the client side will be :
-
hello , I have a custom animation and I made a simple script by using it. so when you start the resource in the server and type /outr22 in chat the player will do the custom animation client side : addEvent( "otur", true ) addEventHandler( "otur", root, function(enable) if (enable) then setPedAnimation(source, "otur", "WEAPON_crouch", -1, true, false) else setPedAnimation(source) end end ) addEventHandler("onClientResourceStart", resourceRoot, function() triggerServerEvent("onClientSync", resourceRoot) end ) addEventHandler("onClientResourceStop", resourceRoot, function() if ifp then for _,player in ipairs(getElementsByType("player")) do local _, otur = getPedAnimation(player) if (otur == "WEAPON_crouch") then setPedAnimation(player) end end destroyElement(ifp) end end ) server side : local animEnable = {} local syncPlayers = {} addCommandHandler("otur2", function(player) if (not animEnable[player]) then animEnable[player] = true triggerClientEvent(syncPlayers, "otur", player, true) outputChatBox("[!]#FFFFFF animation enabled.", player, 0, 255, 0, true) else animEnable[player] = false triggerClientEvent(syncPlayers, "otur", player, false) outputChatBox("[!]#FFFFFF animation disabled.", player, 255, 0, 0, true) end end) addEvent("onClientSync", true ) addEventHandler("onClientSync", resourceRoot, function() outputChatBox("done") table.insert(syncPlayers, client) for player, enable in ipairs(animEnable) do if (enable) then triggerClientEvent(client, "otur", player, true) end end end ) addEventHandler("onPlayerQuit", root, function() for i, player in ipairs(syncPlayers) do if source == player then table.remove(syncPlayers, i) break end end if (animEnable[source] == true or animEnable[source] == false) then animEnable[source] = nil end end ) Now I have decided to change the command you type in chat to do the animation(outr22) from this addCommandHandler("otur2", function(player) if (not animEnable[player]) then animEnable[player] = true triggerClientEvent(syncPlayers, "otur", player, true) outputChatBox("[!]#FFFFFF animation enabled.", player, 0, 255, 0, true) else animEnable[player] = false triggerClientEvent(syncPlayers, "otur", player, false) outputChatBox("[!]#FFFFFF animation disabled.", player, 255, 0, 0, true) end end) to this addEvent("otur2",true) addEventHandler("otur2",root, function(player) if (not animEnable[player]) then animEnable[player] = true triggerClientEvent(syncPlayers, "otur", player, true) outputChatBox("[!]#FFFFFF animation enabled.", player, 0, 255, 0, true) else animEnable[player] = false triggerClientEvent(syncPlayers, "otur", player, false) outputChatBox("[!]#FFFFFF animation disabled.", player, 255, 0, 0, true) end end) so what I did is I changed the way to do the animation from typing a command --> to press a button to do the custom animation clarification : when I press a button , the client side will trigger the server event which called otur2 to do the custom animation and here's the client side : function mouse2() if isMouseInPosition(1500, 240, 120, 120) and getKeyState("mouse1") then playSound("SFX/click.mp3") triggerServerEvent("otur2", localPlayer) end end addEventHandler ( "onClientClick", root, mouse2) and When I tested the script, a problem appeared to me ERROR: AnimationsPanel\smain.lua:9: table index is nil Knowing that the 9th line in server side is : animEnable[player] = true I didn't make any changes to the script As it is clear above, I just changed the command handler to event handler. I can't figure out what's wrong or fix it, could you help me? I hope my words are clear and I apologize if I took up too much of your time, thank you Other information: The benefit of this script is to make custom animations with server side , not just client side .. it's working when I use the command way, but it's not working with event handler
-
@. - DmaR x سلام عليكم أخوي ، شكراً لانك نبهتني للموضوع .. الحمدلله قدرت اصلح هذه الاخطاء تقدر تجرب السكربت وتقولي رأيك ، شكراً. https://github.com/xMohab/mtasa-Animations-Panel
-
@6rB. أولاً شكراً علي تعليقك الجميل يب صحيح ، انا ذكرت بأسفل الموضوع (Sas-Network/SASnet)بالنسبة للفكرة فـ هي مستوحاه من سيرفر قديم MrDante وقام بإنشائها SparrowMTA وقمت أنا بتطويرها بشكل كبير وإضافة الكثير من المميزات والإستعانة بأنيميشن بواسطة وطبعاً الحقوق محفوظة لكل من له علاقة بتطوير السكربت أو إنشاؤه ولو حابب تشوف السكربت القديم هذا هو : اضغط هنا وتقدر تقارن بين القديم والجديد
-
اعذرني ، سويت السكربت علي حسب معرفتي البسيطة ف البرمجة في اقتراحات للتطوير من طريقة الكتابة ؟ ^-^ @. - DmaR x اعذرني ، سويت السكربت علي حسب معرفتي البسيطة ف البرمجة اللي مخلي السكربت طويل بسبب ان السكربت يحتوي علي الكثير من الحركات المختلفة في اقتراحات للتطوير من طريقة الكتابة ؟ ^-^
-
سكربت لوحة الأنيميشن سكربت يُسهل عليك فعل الحركات كما انه يحتوي علي الكثير من الحركات التي يمكنك القيام بها. معاينة لمعلومات أكثر عن السكربت وحقوق المؤلفين https://bit.ly/AnimationsPanel تحميل السكربت مباشرة Github شكراً لـ @MrDante @SparrowMTA Developer#6617(discord) نسيت أقول شئ مهم : (Sas-Network/SASnet)بالنسبة للفكرة فـ هي مستوحاه من سيرفر قديم MrDante وقام بإنشائها SparrowMTA وقمت أنا بتطويرها بشكل كبير وإضافة الكثير من المميزات والإستعانة بأنيميشن بواسطة وطبعاً الحقوق محفوظة لكل من له علاقة بتطوير السكربت أو إنشاؤه شكرا
-
فكرة جميلة ، بالتوفيق.