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

    Ошибка: Ваша версия Grand Theft Auto V не поддерживается 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/newswire/
    Статус всех служб для Rockstar Games Launcher и поддерживаемых игр: https://support.rockstargames.com/ru/servicestatus


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

Полная переработка Street RP

meolex

Гуру
BackEnd developer
FrontEnd developer
30 Апр 2025
32
140
53
Всем привет, в свободное время взял брал на дорабтку проект Street RP (есть слитый мод) потому что думал когда то открыть проект, но как я вижу, если кого то искать то это или скам, или делов на 2 недели и потом все, жаль что так.

В общем вот оригинальная тема: https://ragemp.pro/resources/gotovyj-mod-servera-street-role-play-dlja-multipleera-rage-mp.400/

Вот что было сделно, тут не все описано, я чисто взял по своим коммитам посмотрел что сделал, так как мод уже давно лежит просто в папке поздабыл уже, еще там тачки есть с ГТА 5 РП которые сливал Холланд, я отобрад все где нет надписей ГТА 5 РП, в ручную чистил как дурак, ахах.

Список переделок:

Инфраструктура и сборка

- Миграция с Create React App / Webpack → Vite для обеих частей (клиент и сервер)
- Обновление React 17 → React 18

Управление состоянием

- Полный переход с Redux → Zustand (убраны все Redux-зависимости)

UI-библиотека и компоненты

- Замена rc-slider на кастомный Slider
- Замена react-toastify на sonner для уведомлений
- Замена animated-number-react на кастомный AnimatedNumber
- Замена moment.js на date-fns
- Введены компоненты из Radix UI (AlertDialog, Card, Tooltip и др.)
- Добавлен tailwindcss-motion для анимаций
- Рефакторинг кнопок: унификация через новый Button
- Добавлены компоненты: Accordion, Kbd, Selector, Avatar, ItemsGroup, TabletDetails

Инвентарь

- Полный рефакторинг UI инвентаря
- Переход с одной dnd-библиотеки на @dnd-kit/core (drag-and-drop)
- Добавлены: поповер для предметов, контекст инвентаря, слайдер

Формы и валидация

- Переход на react-hook-form + zod для всех форм
- Рефакторинг: логин, регистрация, подтверждение, восстановление пароля

HUD

- Большой рефакторинг HUD-компонентов
- Перемещение Mic, улучшение Target, WeaponsAmmo
- Новые хуки: usePayment, useRotation, useCountdown

Чат

- Полная реализация чата с обработкой сообщений и командами
- Добавлена поддержка фракционного чата
- Рефакторинг Vector3Mp → Vector3

Телефон и UI сервисов

- Рефакторинг телефона, контактов — добавлен компонент Avatar
- Рефакторинг: одежда, тату-шоп, паспорт, банк, газ, лицензии, мастерская
- Приведение всего UI к единому стилю (Tailwind, rounded, отступы)

Планшет (Tablet/Admin)

- Рефакторинг Tablet UI на Tailwind
- Рефакторинг управления участниками и рангами
- Новые вкладки: бан, кик, деньги, скин, деморган, спектатор, телепорт
- Проверка admin-прав для транспорта

Бизнесы
- Полный рефакторинг UI инвентаря
- Переход с одной dnd-библиотеки на @dnd-kit/core (drag-and-drop)
- Добавлены: поповер для предметов, контекст инвентаря, слайдер

Формы и валидация

- Переход на react-hook-form + zod для всех форм
- Рефакторинг: логин, регистрация, подтверждение, восстановление пароля

HUD

- Большой рефакторинг HUD-компонентов
- Перемещение Mic, улучшение Target, WeaponsAmmo
- Новые хуки: usePayment, useRotation, useCountdown

Чат

- Полная реализация чата с обработкой сообщений и командами
- Добавлена поддержка фракционного чата
- Рефакторинг Vector3Mp → Vector3

Телефон и UI сервисов

- Рефакторинг телефона, контактов — добавлен компонент Avatar
- Рефакторинг: одежда, тату-шоп, паспорт, банк, газ, лицензии, мастерская
- Приведение всего UI к единому стилю (Tailwind, rounded, отступы)

Планшет (Tablet/Admin)

- Рефакторинг Tablet UI на Tailwind
- Рефакторинг управления участниками и рангами
- Новые вкладки: бан, кик, деньги, скин, деморган, спектатор, телепорт
- Проверка admin-прав для транспорта

Бизнесы

- Реализована система выбора бизнеса в UI
- Добавлены: статистика, склад (авто-списание), динамические цены, закрытие бизнеса
- UI для управления бизнесом, кнопка сохранения позиции

Работы (Jobs)

- Полная реализация работы Trucker с доставкой заказов и UI
- Система зарплат — вынесена в централизованный конфиг
- Авто-удаление транспорта при дисконнекте

Смерть игрока

- Новый UI меню смерти с причинами
- Таймер смерти, рефакторинг логики возрождения

Транспорт

- Управление транспортом для админа (ремонт, телепорт)
- Временные ТС по умолчанию true
- Рефакторинг VehicleState (убраны debug-логи)

Добавлена библиотека Rage RPC

Пример рефакторинга: Телефон (Contacts + Store):

БЫЛО — Redux (3 файла, ~70 строк)

store/phone/types.ts
export const SET_CALL = 'SET_CALL';
export const ACCEPT_CALL = 'ACCEPT_CALL';
export const SET_WALLPAPER = 'SET_WALLPAPER';

type SetCallAction = { type: typeof SET_CALL; payload?: Call; };
type AcceptCallAction = { type: typeof ACCEPT_CALL; };
type SetWallpaperAction = { type: typeof SET_WALLPAPER; payload: string; };

export type PhoneActionTypes = SetCallAction | AcceptCallAction | SetWallpaperAction;

store/phone/actions.ts
export function setCall(data?: Call): PhoneActionTypes {
return { type: SET_CALL, payload: data };
}
export function acceptCall(): PhoneActionTypes {
return { type: ACCEPT_CALL };
}
export function setWallpaper(name: string): PhoneActionTypes {
return { type: SET_WALLPAPER, payload: name };
}

store/phone/reducer.ts
export default function phoneReducer(state = initialState, action: PhoneActionTypes): PhoneState {
switch (action.type) {
case SET_CALL: return { ...state, call: action.payload };
case ACCEPT_CALL: return { ...state, call: state.call ? { ...state.call, isRecieve: true } : undefined };
case SET_WALLPAPER: return { ...state, wallpaper: action.payload };
default: return state;
}
}

СТАЛО — Zustand (1 файл, 29 строк)

export const usePhoneStore = create<PhoneState & PhoneActions>((set) => ({
call: undefined,
wallpaper: "0",

setCall: (call) => set({ call }),
acceptCall: () => set((state) => ({ call: state.call ? { ...state.call, isRecieve: true } : undefined })),
setWallpaper: (wallpaper) => set({ wallpaper }),
}));

3 файла → 1 файл. Удалены actions, types, reducer. Логика та же.

---
2. Компонент Контактов

БЫЛО — Class Component (~155 строк)

export default class Contacts extends Component<{}, State> {
readonly state: State = {
contacts: [],
blacklist: [],
showEditor: false,
searchValue: ''
};

componentDidMount() {
rpc.callServer('Phone-GetContactsData').then((data) => this.setState(() => data));
}

toggleEditor() {
this.setState((state) => ({ showEditor: !state.showEditor }));
}

async saveContact(data: ContactData) {
const { selectedContact: contact } = this.state;
try {
await rpc.callServer(
contact ? 'Phone-EditContact' : 'Phone-AddContact',
contact ? [contact.phone, data] : data
);
this.setState((state) => ({
contacts: contact
? state.contacts.map((item) => (item.phone === contact.phone ? data : item))
: [...state.contacts, data],
selectedContact: data
}));
this.toggleEditor();
} catch (err: any) {
showNotification('error', 'Контакт с указанным номером уже существует');
}
}

render() {
const { selectedContact, showEditor } = this.state;
return (
<div className="contacts">
{showEditor ? (
<Editor
contact={selectedContact}
save={this.saveContact.bind(this)}
remove={this.deleteContact.bind(this)}
close={this.toggleEditor.bind(this)}
/>
) : selectedContact ? (
<Contact ... />
) : (
<Fragment>
<Navigation action={{ title: IoIosAdd, onClick: this.toggleEditor.bind(this) }} />
...
</Fragment>
)}
</div>
);
}
}


СТАЛО — Functional Component с хуками (~115 строк)

export default function Contacts() {
const [searchValue, setSearchValue] = useState("");
const [showEditor, setShowEditor] = useState(false);
const [contacts, setContacts] = useState<ContactData[]>([]);
const [selectedContact, setSelectedContact] = useState<ContactData | undefined>();

useEffect(() => {
rpc.callServer("Phone-GetContactsData").then((data) => {
setContacts(data.contacts);
setBlacklist(data.blacklist);
});
}, []);

const toggleEditor = () => setShowEditor(!showEditor);

const saveContact = async (data: ContactData) => {
try {
await rpc.callServer(selectedContact ? "Phone-EditContact" : "Phone-AddContact", ...);
setContacts((prev) => selectedContact ? prev.map(...) : [...prev, data]);
toggleEditor();
} catch (err: any) {
showNotification("error", "Контакт с указанным номером уже существует");
}
};

if (showEditor) return <Wrapper><Editor ... /></Wrapper>;
if (selectedContact) return <Wrapper><Contact ... /></Wrapper>;

return (
<Wrapper>
<div className="px-3">
<div className="flex items-center justify-between">
<Title>Контакты</Title>
<Button variant="ghost" size="icon" onClick={toggleEditor}>
<CiCirclePlus className="!size-6" />
</Button>
</div>
<SearchInput ... />
</div>
<List contacts={getFilteredItems()} selectContact={selectContact} />
</Wrapper>
);
}


Все интерфейсы были переписаны, то есть мод по сути другой по части CEF и клиента. Скринов с игры к сожалению нет, но если прям кому то надо я подниму сервак и пофоткаю.

К чему вообще эта тема создана, я просто не знаю продавать ли проект или просто слить его, по поводу слива немного не охота изза потраченого времени на него, я думал сделать аля подписку с постоянными адпейтами, и улучшениями. По этому я хотел это спросить у более опытных как лучше поступить и что сделать, спасибо если прочитали и ответили.

1777909802207.png



Нашел пару примеров:

1777910848620.png
1777910859959.png

1777910869284.png

1777910878750.png

1777910895289.png

1777910910550.png

1777910917321.png

1777910925860.png

1777910954673.png
1777910972057.png
1777911085157.png
 
Последнее редактирование:
Реакции: kasper и youngBeaver