Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 19/10/16 in all areas

  1. Данный урок предполагает, что вы уже знаете, что такое MySQL, как это работает и зачем это нужно, если же нет - ознакомитесь с данным уроком и вернитесь сюда! Цель данного урока - донести до вас некоторые вещи, которые вы, возможно, не понимаете или даже не задумывались о них. Немного теории MySQL - свободная реляционная система управления базами данных. Для работы с базой используется язык структурированных запросов(он же SQL). Более подробную и интересующую Вас информацию об SQL, Вы сможете найти на просторах интернета. Мы же поговорим о ключевых моментах работы с MySQL. SQL имеет 4 основных оператора для манипуляции с данными. SELECT - выбор данных, удовлетворяющих заданные условия. INSERT - добавление новых данных. UPDATE - изменение существующих данных. DELETE - удаление указанных данных Я не буду рассказывать вам о существующих типах данных MySQL, как создавать или удалять таблицы, я лишь хочу поделиться с вами ключевыми вещами, которые помогут вам оптимизировать работу вашего сервера и уменьшить нагрузку на него. Рассмотрим на основе примера В качестве примера для данного урока будет использоваться таблица с названием players, имеющая следующие столбцы: `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `surname` varchar(255) NOT NULL, `age` tinyint(3) NOT NULL, `adminLevel` tinyint(3) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) Тут я думаю все понятно, никаких проблем быть не должно. Для примера рассмотрим несколько запросов. Получаем всех игроков: SELECT `id`, `name`, `surname`, `age`, `adminLevel` FROM `players` Получаем игрока с конкретным id: SELECT `id`, `name`, `surname`, `age`, `adminLevel` FROM `players` WHERE id=117 Получаем всех игроков, имя которых равно какому-то конкретному значению: SELECT `id`, `name`, `surname`, `age`, `adminLevel` FROM `players` WHERE name="Bobby" Получаем первых 10 игроков, возраст которых равен 19 лет: SELECT `id`, `name`, `surname`, `age`, `adminLevel` FROM `players` WHERE age=19 LIMIT 10 Получаем всех игроков, возраст которых больше или равен 18 годам: SELECT `id`, `name`, `surname`, `age`, `adminLevel` FROM `players` WHERE age >= 18 Ну тут все просто, пришло время рассмотреть все на основе конкретных примеров и указать ключевые особенности. Неправильный выбор функции для формирования запроса Это первая и наиболее часто встречающаяся ошибка, которую я вижу в коде различных разработчиков. Для формирования запроса к MySQL в МТА существует 2 функции, а именно: dbExec и dbQuery. Обе функции выполняют запрос, но их главная особенность заключается в том, что dbQuery возвращает какой-либо результат и тем самым занимает оперативную память сервера, а dbExec нет. Очень часто разработчики забывают использовать dbFree после запроса, для создания, редактирования или удаления какой-то записи. Рассмотрим на основе простого примера создания нового пользователя: local Name = "Bobby" local Surname = "Raily" local Age = 23 dbExec(dbConnection, "INSERT INTO `players` (name, surname, age) VALUES(?, ?, ?)", Name, Surname, Age) Опять же, все просто, сформировали простой запрос, создали новую запись в таблице players с заданными значениями. Можно, конечно, реализовать это с помощью dbQuery, но обязательно не стоит забывать про dbFree! Казалось бы, а что такого? Но все дело в том, что если у вас на сервере зарегистрируется большое количество игроков, то это порядком забьет память ненужной ерундой, проще говоря мусором, который хранить на сервере нет никакой необходимости. local Name = "Bobby" local Surname = "Raily" local Age = 23 local Query = dbQuery(dbConnection, "INSERT INTO `players` (name, surname, age) VALUES(?, ?, ?)", Name, Surname, Age) dbFree(Query) Я надеюсь, что вы четко и ясно уяснили для себя этот пункт, на это стоит обратить особое внимание. Некорректное использование dbQuery для получения результата запроса Очень часто вам необходимо получить какие-то данные из базы данных. В этом нам помогают dbQuery и dbPoll. Если внимательно посмотреть на синтаксис функции dbQuery, то вы увидите, что в качестве первого необязательного аргумента она принимает callback функцию. Что же это такое и зачем это нужно? Я настоятельно рекомендую вам как можно внимательнее и ответственнее подойти к этому вопросу, т.к. многие разработчики до сих пор не до конца уловили суть данного аргумента и не понимают из-за чего происходят "фризы" во время работы того или иного скрипта. Предположим, что у нас зарегистрировано 100 000 уникальных игроков(для крупного проекта - вполне себе реально, но мы рассматриваем все в теории). Нам необходимо получить список всех имеющихся игроков. Вы должны понимать, что это не произойдет моментально, в любом случае на данную операцию будет затрачено какое-то количество времени. Рассмотрим два примера, использование запроса без callback функции и с ней соответственно: local Players = dbPoll(dbQuery(dbConnection, "SELECT * FROM `players`"), -1) for Index, PlayerData in ipairs(Players) do print(PlayerData.name) end function CallbackFunction(qh, tag, score) local Players = dbPoll(qh, 0) for Index, PlayerData in ipairs(Players) do print(PlayerData.name) end end dbQuery(CallbackFunction, dbConnection, "SELECT `id`, `name`, `surname`, `age`, `adminLevel` FROM `players`") Время, занявшее на выполнение данного запроса, составило 489 мс. Так в чем же характерная особенность между первым и вторым способом? Особенность заключается в том, что пока выполняется получение данных из базы первым способом, то работа нашего сервера приостановиться на время, которое необходимо для выполнения данного запроса, что может негативно повлиять на всех игроков, в результате могут возникнуть такие вещи как фризы, рассинхронизация и т.д. Поэтому вы четко должны понимать для себя нужно вам это или нет. Если же вам необходимо, чтобы работа сервера была приостановлена на время выполнения запроса - используйте первый вариант, если же нет - второй. Если же вы до этого имели опыт с другими ЯП, то вероятнее всего понимаете, что такое синхронное и асинхронное выполнение. Первый вариант - это синхронное выполнение, второй - асинхронное. Выполнение лишней работы посредством Lua Так же очень часто наблюдаю картину, когда многие разработчики выполняют лишнюю работу, а именно предпринимают лишние действия, которые можно было сформировать в результате SQL запроса. SQL существует довольно большое количество времени и за это время овладел всеми необходимыми функциями, операторами и прочими вещами для формирование корректного запроса. К примеру мы хотим получить id всех игроков, adminLevel которых выше или равен 2. Как видно из запроса - мы сразу же получаем список игроков, уровень которых равен или больше 2 function CallbackFunction(qh, tag, score) local Players = dbPoll(qh, 0) for Index, PlayerData in ipairs(Players) do print(PlayerData.id) end end dbQuery(CallbackFunction, dbConnection, "SELECT `id`, `name`, `surname`, `age`, `adminLevel` FROM `players` WHERE adminLevel >= 2") Но иногда мне приходится видеть, как некоторые разработчики получают список всех игроков и начинают проверь их adminLevel посредством Lua, что само по себе не имеет никакого смысла, т.к это выполнение лишней работы. function CallbackFunction(qh, tag, score) local Players = dbPoll(qh, 0) for Index, PlayerData in ipairs(Players) do if PlayerData.adminLevel >= 2 then print(PlayerData.id) end end end dbQuery(CallbackFunction, dbConnection, "SELECT `id`, `name`, `surname`, `age`, `adminLevel` FROM `players`") Заключение Надеюсь, что вы не зря потратили свое время и подчеркнули для себя какие-то полезные вещи, которые в последствии помогут вам при разработке собственного игрового режима или мода. Если же у вас остались какие то вопросы или вам что-то непонятно - вы можете оставлять свои вопросы в данной теме.
    2 points
  2. السلام عليكم اخواني اليوم ابي اعلن عن بداية الرسمية لــ مشروع BusinessLifeRP وهو مشروع كبير جدا و فيه ميزات عدة مثل الشركات و المصانع و سوق الاسهم .... و اكثر بأذن الله و راح نصدر السيرفر Beta بعد اشهر من الان عشان نشوف ردة فعل الاعبين و راح نغلق و نفتح السيرفر الرسمي اللي راح يكون اكبر و أحسن منه ان شاء الله و مشروعنا راح يكون من الاول للأخر مبرمج من طرف مبرمجينا و ماراح نستعمل بأذن الله اي سكريبت موجود في اللعبة نتمنى منكم دعم الفكرة ولوا بـ كلمة الموقع الرسمي BusinessLifeRP.com لدينا مبرمجين لاكن نحتاج لاكثر اذا كنتم مهتمين ارسلوا رسالة او ضعوها في الموقع و شكرا
    2 points
  3. You have to use the new way of posting codes. See the '<>' (code) button, it will allow you to paste codes.
    2 points
  4. Верно. Папки backups - бекап сервера (базы и конфигов, по датам) - МТА их делает сама, в mtaserver.conf можно настроить путь для бекапов, а также их периодичность и другие параметры. databases - локальные базы SQLite. logs - логи сервера recource-cache - кэш ресурсов из папки resources, но если в папке resources есть ресурсы в виде .zip архивов, то МТА их распакует автоматически и переместит в папку resource-cache. resources - папка, в которой находятся все ресурсы (мод, админка, мап едитор и т.д) Конфиги acl.xml - Документ Access Control List (список прав доступа), в ней находятся группы Admin, Moderator, ты можешь создать свою группу. Для каждой группы расписаны права доступа. banlist.xml - В этом документе находятся все игроки, которые были забанены на сервере. editor.conf - Конфиг для мап едитора, очень схож с mtaserver.conf, он описывает параметры для мап едитор сервера (В меню МТА есть пункт - Редактор Карт, если ты нажмешь на него, то запустится локальный сервер по данному конфигу) editor_acl.xml - Тоже самое что и acl.xml, но для мап едитор сервера. mtaserver.conf - В данном конфиге находятся все параметры для сервера (макс кол-во слотов, название сервера и т.д) settings.xml - В данном конфиге могут содержаться пользовательские настройки для сервера, они могут быть получены или изменены через функции get/set. set get Все изменения будут записаны в этот конфиг. vehiclecolors.conf - В донном конфиге содержатся цвета для машин. Другое server-id.keys - Уникальный ключ для сервера. Используется для предотвращения чтения личных файлов, сохраненных на клиенте, другими серверами. Бинарники не буду расписывать, на гитхабе проекта MTA можно самому посмотреть: https://github.com/multitheftauto/mtasa-blue. Больше информации по настройке сервера можно найти тут: https://wiki.multitheftauto.com/index.p ... ver_Manual https://wiki.multitheftauto.com/index.p ... erver.conf P.S На вики не все страницы русифицированы, а если и русифицированы, то возможно они старые и давно не обновлялись. Смена языка есть слева (если доступен)
    2 points
  5. Prank online players on your server by showing them a BSOD (blue screen) and let them believe their PC has crashed while they are playing MTA. https://community.multitheftauto.com/index.php?p=resources&s=details&id=13748 use: /bsod PlayerName (exact) After 5 seconds the bluescreen and error sound disappears and everything is back normal. (hud elements and chat etc that are hidden to make the bluescreen look real will also return) 2 sound effects are incuded: buzzing sound loop (like can happen with Windows 7, 8, 10 bluescreens) and Windows XP error beep. Win7+ BSOD sound: bs1.mp3 (demonstration: https://www.youtube.com/watch?v=TDOolCOjE30) WinXP BSOD beep: bs2.mp3 (demonstration: https://www.youtube.com/watch?v=WdOuIJLHBEs) If you want to change the effect from default buzzing sound to the XP beep, change in client.lua the .mp3 filename to bs2.mp3 behind ''playSound''
    1 point
  6. الطريقة الخاصة بك اكثر من رائعة انا جربت طريقة متلها لكن getVehicleID وما نفعت ميشان كذا سويت كل هذا الحين بعدل الكود شكراً لك
    1 point
  7. Why clientside instead of serverside, You don't want the others to see what walking style you have?
    1 point
  8. الزبده انك عرفت المودات وانتهينا !
    1 point
  9. ^ انا مضبط وضعي تقريباً بس باقي اجيب كرت شاشة GTX 1050 TI >< ( طبعاً اذا الشحن ماياخذ كثير )
    1 point
  10. Это конфиг сервера который запускается из клиента МТА (Создать сервер)
    1 point
  11. يب ^ مشكور ع التصليح بس الي انا حاطها حق كلنت شيك ع الويكي و شوف ^ : )
    1 point
  12. اتوقع انه يستفسر عن السرعة بهاذي الطريقة
    1 point
  13. Верно, это для помощи разработчикам МТА последние эксперементальные версии вы можете найти тут: https://nightly.multitheftauto.com/ Компилировать вам их совершенно не обязательно.
    1 point
  14. I don't like that idea so that's up to you, this is an open source project that means everyone can do whatever they want. I don't do requests unless I like them.
    1 point
  15. العفو ، حيآك *
    1 point
  16. I suggest setting postGUI to true to make it look more realistic (hides MTA watermark), anyway good job ^^
    1 point
  17. Made an automated script to pull MTA:SA's wiki once every month, all wiki versions will be available at: https://mta.ggcommunity.net/arkives/ Latest: 10-17-2016
    1 point
  18. local franMark1 = createMarker ( 1762.6,-1813.4,12.6,'cylinder',5,255,0,0,35 ) local franMark2 = createMarker ( 1805,-1748.6,51.5,'cylinder',5,255,0,0,115 ) function teleport ( player ) if player and isElement(player) and getElementType ( player ) == 'player' then if is_group ( player ) or is_admin ( player ) then local aPlayer = isPedInVehicle (player) and getPedOccupiedVehicle (player) or player if ( source == franMark1 ) then setElementPosition ( aPlayer,1791,-1780,53) setElementFrozen ( aPlayer,true ) setTimer ( setElementFrozen,300,1,aPlayer,false ) elseif ( source == franMark2 ) then setElementPosition ( aPlayer,1775.8,-1821.3,14.5 ) setElementFrozen ( aPlayer,true) setTimer ( setElementFrozen,300,1,aPlayer,false ) end end end end addEventHandler ('onMarkerHit',root,teleport)
    1 point
  19. السلام عليكم بالنسبة لطلبك اضافة او انشاء سلاح جديد يستحيل حالياً ان يكون متكامل مثل الاسلحة الثانية والكمال لله لكن تقدر تبدل الاسلحة باشكال ملفات وتعدل على خصائص باستخدام : setWeaponProperty مثلاً تقدر بهذي الوظيفة تدبل مسافة الاطلاق لسلاح معين يعني اذا ماكان يوصل تقدر تعدل وتخلية يوصل بالوظيفة هذي موفق
    1 point
×
×
  • Create New...