• Из-за обновления GTA 5 (был добавлен новый патч) может временно не работать вход в RAGE Multiplayer.

    ERROR: Your game version is not supported by RAGE Multiplayer.

    Данная ошибка говорит о том, что GTA V обновилась до новой версии (GTA Online тоже). Вам необходимо обновить саму игру в главном меню вашего приложения (Steam / Epic Games / Rockstar Games).
    Если после этого RAGE:MP все равно не работает - вам нужно дождаться выхода патча для самого мультиплеера (обычно это занимает от нескольких часов до нескольких дней).

    Новости и апдейты Rockstar Games - https://www.rockstargames.com/ru/newswire/
    Статус всех служб для Rockstar Games Launcher и поддерживаемых игр: https://support.rockstargames.com/ru/servicestatus


    Grand Theft Auto 5 (+ GTA Online) последний раз были обновлены:

FAQ Middleware в RageMP (для самых маленьких)

anayks

Участник портала
Автор темы
20 Сен 2021
2
12
13
Начнем!

Предыстория

Привет!

Я хочу рассказать об одной маленькой разработке, о которой пока что мало кто знает.
Эта разработка позволит сократить Вам количество говно кода в несколько раз, если Вы просто будете соблюдать базовые принципы.

Скажу сразу, что у меня уже более 3 лет разработки в играх (MTA, SA-MP, RageMP) и уже есть коммерческий опыт в крупнейшей IT компании в РФ (который перекрывает абсолютно весь опыт в играх).

На практике

Я думаю, многие сталкивались с такой проблемой, что в каждом ивенте нужно расставлять условие, авторизован ли игрок, является ли игрок администратором или ещё того хуже - медиком.

Шутки шутками, но мы держали довольно крупный проект, в котором онлайн доходил почти до 3 тысяч человек, но мы ручками в каждом событии расставляли условия по цепочке:
1. Авторизован ли игрок
2. Выбрал ли он персонажа
3. Заспавнен ли он
4. Не находится ли игрок в авто
5. Является ли он администратором
6. Относится ли он к нужной фракции (вдруг, это маркер только для медиков)
7. Доступно ли это ему по рангу
8. Выдан ли ему доступ к этой системе помимо ранга.

Представьте себе эту огромную цепочку!
А зачем представлять, я могу быстренько накидать:

JavaScript:
function onPlayerEnterMedicAdminMarker(player) {
    if(!player.logged) {
        player.send("Ты не авторизован!");
        return;
    }
  
    if(!player.choosedPerson) {
        player.send("Ты не выбрал персонажа!");
        return;
    }
  
    if(!player.spawned) {
        player.send("Ты не заспавнен!");
        return;
    }
  
    if(player.vehicle) {
        player.send("Ты в автомобиле, так нельзя!");
        return;
    }
  
    if(!player.admin) {
        player.send("Ты не админ, так нельзя!");
        return;
    }
  
    if(player.faction != FACTIONS.MEDIC) {
        player.send("Тебе нельзя, ты не МЕДИК!");
        return;
    }
  
    if(player.rank < FACTION_MARKER_RANK_AVAILABLE) {
        player.send("У тебя слишком маленький ранг, тебе нужно подрасти!");
        return;
    }
  
    if(!player.available_medic_marker) {
        player.send("У тебя ещё и доступа нет, ужас!");
        return;
    }
  
    player.send("Ты встал на маркер и прошел все проверки. Ути, молодец!");
}

Смотрим на это и понимаем, что если таких маркеров будет 2-3-5-10-20,
то количество кода вырастет в 20 раз и нужно будет весь этот пиз*** ужас копировать 20 раз!

Да, такое было у нас на продакшене и да, такое было везде.
Вы представьте, что на каждый обработчик событий ставилась как минимум 1 проверка!
(А чаще всего, больше, потому что 1 была гарантированно - это анти-флуд ивентами).

На помощь нам приходит полу-роутинг (не углубляемся) и Middlewares.

Что такое Middleware?
Это промежуточный блок кода, который вызывается перед выполнением основного блока кода.
Чаще всего, Middleware - это функция с условием или с обработкой (например, логированием) перед выполнением основного кода.

Есть ли примеры?
Конечно, но сначала давайте посмотрим на псевдокоде JS:
JavaScript:
/// мы "где-то посередине кода"
/// Представим, что у нас есть система, и все события этой системы связаны в группу
/// Например, это те же медики

function initMedicSystem(App) {
    const group = App.addGroup("медики");
    group.use(isPlayerLogged, isPlayerCharacterReady, isPlayerSpawned, isPlayerInVehicle, isPlayerAdmin, isPlayerMediс, havePlayerMarkerRank, isPlayerMedicMarkerAvailable)
    group.addEvent("onPlayerEnterMedicAdminMarker", onPlayerEnterMedicAdminMarker);
}

function onPlayerEnterMedicAdminMarker() {
    player.send("Ты встал на маркер и прошел все проверки. Молодец!");
}

function isPlayerLogged(player, args, next) {
    if(!player.logged) {
        player.send("Братик, ты не авторизован!");
        return;
    }
    next();
}

function isPlayerCharacterReady(player, args, next) {
    if(!player.choosedPerson) {
        player.send("Братик, ты не выбрал персонажа!");
        return;
    }
    next();
}

function isPlayerSpawned(player, args, next) {
    if(!player.spawned) {
        player.send("Братик, ты не заспавнен!");
        return;
    }
    next();
}

function isPlayerInVehicle(player, args, next) {
    if(player.vehicle) {
        player.send("Братик, ты в машине, не нужно так!");
        return;
    }
    next();
}

function isPlayerAdmin(player, args, next) {
    if(!player.admin) {
        player.send("Братик, ты не админ!");
        return;
    }
    next();
}

function isPlayerMedic(player, args, next) {
    if(player.faction != FACTIONS.MEDIC) {
        player.send("Братик, ты не медик!");
        return;
    }
    next();
}

function isPlayerMedicMarkerAvailable(player, args, next) {
    if(!player.available_medic_marker) {
        player.send("Братик, ты у тебя нет прав!");
        return;
    }
    next();
}

function havePlayerMarkerRank(player, args, next) {
    if(player.rank < FACTION_MARKER_RANK_AVAILABLE) {
        player.send("Братик, ты у тебя нет прав!");
        return;
    }
    next();
}

/// конец этого "где-то посередине кода"

БУУУУУУУУУМ

Сейчас у Вас может взорваться голова и Вы скажете, что:
Ой, разработчик, у тебя же получилось больше кода, а не меньше!!

Но это до того момента, пока мы не начнем добавлять новые события, которые уже будут проходить эти проверки автоматически:
JavaScript:
// отрывок от отрывка кода
function initMedicSystem(App) {
    const group = App.addGroup("медики");
    group.use(isPlayerLogged, isPlayerCharacterReady, isPlayerSpawned, isPlayerInVehicle, isPlayerAdmin, isPlayerMediс, havePlayerMarkerRank, isPlayerMedicMarkerAvailable)
    group.addEvent("onPlayerEnterMedicAdminMarker", onPlayerEnterMedicAdminMarker);
    group.addEvent("onPlayerEnterAdminSecondMarker", onPlayerEnterAdminSecondMarker);
    group.addEvent("onPlayerEnterAdminThirdMarker", onPlayerEnterAdminThirdMarker);
}

function onPlayerEnterAdminThirdMarker(player) {
    player.send("Ты встал на третий маркер и прошел все проверки. Молодец!");
}

function onPlayerEnterAdminSecondMarker(player) {
    player.send("Ты встал на второй маркер и прошел все проверки. Молодец!");
}

function onPlayerEnterMedicAdminMarker(player) {
    player.send("Ты встал на маркер и прошел все проверки. Молодец!");
}

// отрывок от отрывка кода

Переломный момент

Вот здесь происходит переломный момент.
У этих трех маркеров может быть абсолютно разный функционал, но у всех трех одинаковые проверки.
Если мы просто начнем в тупую копировать код из первого примера, мы заметим, что количество кода будет в 1.5-2 раза больше, чем в примере с группами и middleware функциями.
1649520862668.png
1649520871043.png


(Не удивляйтесь, с форума с вкладки code копируется с лишним пробелами). Если убрать пробелы - соотношение останется.
На около 40% кода просто с 3 обработчиками с middleware просто становится меньше, не нужно копировать и постоянно вставлять один и тот же код.

НО... КАК? ЧТО...? ТАКОГО ЖЕ НЕ...?
Существует :)

Специально для разработчиков я создал платформу с обработкой событий и промежуточными функциями.
Если людям будет интересно, я увижу звездочки на github, то я с удовольствием продолжу развивать это дело.

Такая система сократит количество кода в вашем проекте более чем в 3-4 раза, если Вы будете использовать подход промежуточных функций.

А для чего ещё нужны middleware помимо избавления от тонны говно кода?
В крупных проектах и сервисах в промежуточные функции Вы можете вставлять свои метрики, своё логирование и много-много всего,
чтобы попросту контролировать данные, которые Вам присылаются.

Это не только удобно, но и невероятно полезно.
Будет тяжело забыть проверку на авторизацию, если Вы воткнули её один раз во всём моде и она работает всегда и везде :)


Если будет необходимо, рассмотрю разные Issue и PR'ы.
Как я понимаю, необходимо будет сделать поддержку асинхронности, что не очень трудно, и добавить туда команды.
Если в этом будет необходимость, обязательно это сделаю!

Ссылка (тык):
RageMP-middlewares
 
Последнее редактирование:

kcomba

Начинающий специалист
9 Янв 2022
104
40
50
С тайпскриптом и декораторами было бы симпатичнее.
А в целом, полезно для новичков, хотя большинство новичков хуй положат на этот пост и подобные скорее всего =(
 

Mikhayloff

Модератор
Команда форума
high designer
9 Окт 2020
1,303
866
211
Бля, я даже не программист и даже не рядом, но я охуел от пиздатости статьи
 

welaurs

Начинающий специалист
30 Ноя 2021
19
46
48
Комьюнити заслуживает качественного кода. Требуем ещё
 

fightforfood

Начинающий специалист
20 Сен 2021
68
14
52
Начнем!

Предыстория

Привет!

Я хочу рассказать об одной маленькой разработке, о которой пока что мало кто знает.
Эта разработка позволит сократить Вам количество говно кода в несколько раз, если Вы просто будете соблюдать базовые принципы.

Скажу сразу, что у меня уже более 3 лет разработки в играх (MTA, SA-MP, RageMP) и уже есть коммерческий опыт в крупнейшей IT компании в РФ (который перекрывает абсолютно весь опыт в играх).

На практике

Я думаю, многие сталкивались с такой проблемой, что в каждом ивенте нужно расставлять условие, авторизован ли игрок, является ли игрок администратором или ещё того хуже - медиком.

Шутки шутками, но мы держали довольно крупный проект, в котором онлайн доходил почти до 3 тысяч человек, но мы ручками в каждом событии расставляли условия по цепочке:
1. Авторизован ли игрок
2. Выбрал ли он персонажа
3. Заспавнен ли он
4. Не находится ли игрок в авто
5. Является ли он администратором
6. Относится ли он к нужной фракции (вдруг, это маркер только для медиков)
7. Доступно ли это ему по рангу
8. Выдан ли ему доступ к этой системе помимо ранга.

Представьте себе эту огромную цепочку!
А зачем представлять, я могу быстренько накидать:

JavaScript:
function onPlayerEnterMedicAdminMarker(player) {
    if(!player.logged) {
        player.send("Ты не авторизован!");
        return;
    }
 
    if(!player.choosedPerson) {
        player.send("Ты не выбрал персонажа!");
        return;
    }
 
    if(!player.spawned) {
        player.send("Ты не заспавнен!");
        return;
    }
 
    if(player.vehicle) {
        player.send("Ты в автомобиле, так нельзя!");
        return;
    }
 
    if(!player.admin) {
        player.send("Ты не админ, так нельзя!");
        return;
    }
 
    if(player.faction != FACTIONS.MEDIC) {
        player.send("Тебе нельзя, ты не МЕДИК!");
        return;
    }
 
    if(player.rank < FACTION_MARKER_RANK_AVAILABLE) {
        player.send("У тебя слишком маленький ранг, тебе нужно подрасти!");
        return;
    }
 
    if(!player.available_medic_marker) {
        player.send("У тебя ещё и доступа нет, ужас!");
        return;
    }
 
    player.send("Ты встал на маркер и прошел все проверки. Ути, молодец!");
}

Смотрим на это и понимаем, что если таких маркеров будет 2-3-5-10-20,
то количество кода вырастет в 20 раз и нужно будет весь этот пиз*** ужас копировать 20 раз!

Да, такое было у нас на продакшене и да, такое было везде.
Вы представьте, что на каждый обработчик событий ставилась как минимум 1 проверка!
(А чаще всего, больше, потому что 1 была гарантированно - это анти-флуд ивентами).

На помощь нам приходит полу-роутинг (не углубляемся) и Middlewares.

Что такое Middleware?
Это промежуточный блок кода, который вызывается перед выполнением основного блока кода.
Чаще всего, Middleware - это функция с условием или с обработкой (например, логированием) перед выполнением основного кода.

Есть ли примеры?
Конечно, но сначала давайте посмотрим на псевдокоде JS:
JavaScript:
/// мы "где-то посередине кода"
/// Представим, что у нас есть система, и все события этой системы связаны в группу
/// Например, это те же медики

function initMedicSystem(App) {
    const group = App.addGroup("медики");
    group.use(isPlayerLogged, isPlayerCharacterReady, isPlayerSpawned, isPlayerInVehicle, isPlayerAdmin, isPlayerMediс, havePlayerMarkerRank, isPlayerMedicMarkerAvailable)
    group.addEvent("onPlayerEnterMedicAdminMarker", onPlayerEnterMedicAdminMarker);
}

function onPlayerEnterMedicAdminMarker() {
    player.send("Ты встал на маркер и прошел все проверки. Молодец!");
}

function isPlayerLogged(player, args, next) {
    if(!player.logged) {
        player.send("Братик, ты не авторизован!");
        return;
    }
    next();
}

function isPlayerCharacterReady(player, args, next) {
    if(!player.choosedPerson) {
        player.send("Братик, ты не выбрал персонажа!");
        return;
    }
    next();
}

function isPlayerSpawned(player, args, next) {
    if(!player.spawned) {
        player.send("Братик, ты не заспавнен!");
        return;
    }
    next();
}

function isPlayerInVehicle(player, args, next) {
    if(player.vehicle) {
        player.send("Братик, ты в машине, не нужно так!");
        return;
    }
    next();
}

function isPlayerAdmin(player, args, next) {
    if(!player.admin) {
        player.send("Братик, ты не админ!");
        return;
    }
    next();
}

function isPlayerMedic(player, args, next) {
    if(player.faction != FACTIONS.MEDIC) {
        player.send("Братик, ты не медик!");
        return;
    }
    next();
}

function isPlayerMedicMarkerAvailable(player, args, next) {
    if(!player.available_medic_marker) {
        player.send("Братик, ты у тебя нет прав!");
        return;
    }
    next();
}

function havePlayerMarkerRank(player, args, next) {
    if(player.rank < FACTION_MARKER_RANK_AVAILABLE) {
        player.send("Братик, ты у тебя нет прав!");
        return;
    }
    next();
}

/// конец этого "где-то посередине кода"

БУУУУУУУУУМ

Сейчас у Вас может взорваться голова и Вы скажете, что:
Ой, разработчик, у тебя же получилось больше кода, а не меньше!!

Но это до того момента, пока мы не начнем добавлять новые события, которые уже будут проходить эти проверки автоматически:
JavaScript:
// отрывок от отрывка кода
function initMedicSystem(App) {
    const group = App.addGroup("медики");
    group.use(isPlayerLogged, isPlayerCharacterReady, isPlayerSpawned, isPlayerInVehicle, isPlayerAdmin, isPlayerMediс, havePlayerMarkerRank, isPlayerMedicMarkerAvailable)
    group.addEvent("onPlayerEnterMedicAdminMarker", onPlayerEnterMedicAdminMarker);
    group.addEvent("onPlayerEnterAdminSecondMarker", onPlayerEnterAdminSecondMarker);
    group.addEvent("onPlayerEnterAdminThirdMarker", onPlayerEnterAdminThirdMarker);
}

function onPlayerEnterAdminThirdMarker(player) {
    player.send("Ты встал на третий маркер и прошел все проверки. Молодец!");
}

function onPlayerEnterAdminSecondMarker(player) {
    player.send("Ты встал на второй маркер и прошел все проверки. Молодец!");
}

function onPlayerEnterMedicAdminMarker(player) {
    player.send("Ты встал на маркер и прошел все проверки. Молодец!");
}

// отрывок от отрывка кода

Переломный момент

Вот здесь происходит переломный момент.
У этих трех маркеров может быть абсолютно разный функционал, но у всех трех одинаковые проверки.
Если мы просто начнем в тупую копировать код из первого примера, мы заметим, что количество кода будет в 1.5-2 раза больше, чем в примере с группами и middleware функциями.Посмотреть вложение 4049Посмотреть вложение 4050

(Не удивляйтесь, с форума с вкладки code копируется с лишним пробелами). Если убрать пробелы - соотношение останется.
На около 40% кода просто с 3 обработчиками с middleware просто становится меньше, не нужно копировать и постоянно вставлять один и тот же код.

НО... КАК? ЧТО...? ТАКОГО ЖЕ НЕ...?
Существует :)

Специально для разработчиков я создал платформу с обработкой событий и промежуточными функциями.
Если людям будет интересно, я увижу звездочки на github, то я с удовольствием продолжу развивать это дело.

Такая система сократит количество кода в вашем проекте более чем в 3-4 раза, если Вы будете использовать подход промежуточных функций.

А для чего ещё нужны middleware помимо избавления от тонны говно кода?
В крупных проектах и сервисах в промежуточные функции Вы можете вставлять свои метрики, своё логирование и много-много всего,
чтобы попросту контролировать данные, которые Вам присылаются.

Это не только удобно, но и невероятно полезно.
Будет тяжело забыть проверку на авторизацию, если Вы воткнули её один раз во всём моде и она работает всегда и везде :)


Если будет необходимо, рассмотрю разные Issue и PR'ы.
Как я понимаю, необходимо будет сделать поддержку асинхронности, что не очень трудно, и добавить туда команды.
Если в этом будет необходимость, обязательно это сделаю!

Ссылка (тык):
RageMP-middlewares
Спасибо что просвещаешь незнающих, может мои глаза больше не увидят Main.cs по 8.5к строк... (RedAge)
Но честно говоря, я не думаю что ещё кто-то делает так, как ты показал в самом начале :) (с кучей if'ов)
 

Inoi

/dev/null
VIP
15 Окт 2020
2,322
1,382
208
34
Спасибо что просвещаешь незнающих, может мои глаза больше не увидят Main.cs по 8.5к строк... (RedAge)
Но честно говоря, я не думаю что ещё кто-то делает так, как ты показал в самом начале :) (с кучей if'ов)
здесь бывали молодые люди, которые под каждый вход в каждый домик на сервере писали свой отдельный маркер отдельным креатемаркер с отдельным текстом
 
  • Haha
Реакции: fightforfood

NightWill

Гуру
high coder
15 Сен 2020
111
42
106
Спасибо что просвещаешь незнающих, может мои глаза больше не увидят Main.cs по 8.5к строк... (RedAge)
Но честно говоря, я не думаю что ещё кто-то делает так, как ты показал в самом начале :) (с кучей if'ов)
а причем тут редаговский Main? Он там мусорка из всего подряд
 
  • Like
Реакции: fightforfood

lovesmurf

Участник портала
11 Май 2022
15
0
21
Неплохо, но как мне кажется, это выглядело бы гораздо симпотичнее на функционале а не на ооп