🚀 Полный гайд по созданию системы админки для SA-MP (Pawn)

Добро пожаловать!

Зарегистрировавшись у нас, вы сможете обсуждать, делиться и отправлять личные сообщения другим участникам нашего сообщества.

Зарегистрироваться!
  • Если Вы желаете помогать развитию проекта, готовы заполнять раздел(-ы) и подсказывать другим пользователям на портале, есть возможность попасть в команду редакторов. Для этого следует обратиться в техническую поддержку
Пользователь
Регистрация
17 Май 2023
Сообщения
50
# 🚀 Полный гайд по созданию системы админки для SA-MP (Pawn)

[big]Система администрирования для SA-MP сервера[/big]​

## 🔧 1. Настройка окружения

```pawn
#include <a_samp>
#include <zcmd> // Для удобных команд
#include <sscanf2> // Для парсинга параметров
#include <YSI\y_ini> // Для работы с файлами
#include <logger> // Для логирования действий
#include <timestamp> // Для временных меток

#define PATH_ADMIN_DATA "/AdminData/%s.ini" // Путь к файлам данных
```

## 📊 2. Структура данных

```pawn
// Уровни админки
enum E_ADMIN_LEVELS {
ADMIN_NONE = 0, // 0 - Обычный игрок
ADMIN_HELPER, // 1 - Помощник
ADMIN_MODERATOR, // 2 - Модератор
ADMIN_ADMIN, // 3 - Администратор
ADMIN_HEAD_ADMIN, // 4 - Старший админ
ADMIN_OWNER // 5 - Владелец
};

// Данные администратора
enum E_ADMIN_DATA {
adminLevel,
adminName[MAX_PLAYER_NAME],
bool:adminLogged,
adminActions,
adminWarns,
adminKicks,
adminBans,
adminJails,
adminMutes,
adminLastLogin[24]
};

new AdminData[MAX_PLAYERS][E_ADMIN_DATA];
```

## 💾 3. Система сохранения данных

```pawn
SaveAdminData(playerid) {
if(AdminData[playerid][adminLevel] == ADMIN_NONE) return 0;

new filename[128], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(filename, sizeof(filename), PATH_ADMIN_DATA, name);

new INI:file = INI_Open(filename);

INI_SetTag(file, "admin_data");
INI_WriteInt(file, "Level", AdminData[playerid][adminLevel]);
INI_WriteString(file, "Name", AdminData[playerid][adminName]);
INI_WriteInt(file, "Actions", AdminData[playerid][adminActions]);
INI_WriteInt(file, "Warns", AdminData[playerid][adminWarns]);
INI_WriteInt(file, "Kicks", AdminData[playerid][adminKicks]);
INI_WriteInt(file, "Bans", AdminData[playerid][adminBans]);
INI_WriteInt(file, "Jails", AdminData[playerid][adminJails]);
INI_WriteInt(file, "Mutes", AdminData[playerid][adminMutes]);
INI_WriteString(file, "LastLogin", AdminData[playerid][adminLastLogin]);

INI_Close(file);
return 1;
}
```

## 🔄 4. Загрузка данных администратора

```pawn
LoadAdminData(playerid) {
new filename[128], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(filename, sizeof(filename), PATH_ADMIN_DATA, name);

if(!fexist(filename)) return 0;

new INI:file = INI_Open(filename);

INI_SetTag(file, "admin_data");
INI_ReadInt(file, "Level", AdminData[playerid][adminLevel]);
INI_ReadString(file, "Name", AdminData[playerid][adminName], MAX_PLAYER_NAME);
INI_ReadInt(file, "Actions", AdminData[playerid][adminActions]);
INI_ReadInt(file, "Warns", AdminData[playerid][adminWarns]);
INI_ReadInt(file, "Kicks", AdminData[playerid][adminKicks]);
INI_ReadInt(file, "Bans", AdminData[playerid][adminBans]);
INI_ReadInt(file, "Jails", AdminData[playerid][adminJails]);
INI_ReadInt(file, "Mutes", AdminData[playerid][adminMutes]);
INI_ReadString(file, "LastLogin", AdminData[playerid][adminLastLogin], 24);

INI_Close(file);

// Обновляем время последнего входа
getdate(AdminData[playerid][adminLastLogin], 24);
return 1;
}
```

## 🔑 5. Система входа в админку

```pawn
CMD:alogin(playerid, params[]) {
if(AdminData[playerid][adminLevel] == ADMIN_NONE)
return SendClientMessage(playerid, COLOR_RED, "Ошибка: У вас нет доступа к админке!");

if(AdminData[playerid][adminLogged])
return SendClientMessage(playerid, COLOR_RED, "Ошибка: Вы уже вошли в админку!");

new password[32];
if(sscanf(params, "s[32]", password))
return SendClientMessage(playerid, COLOR_WHITE, "Использование: /alogin [пароль]");

// Проверка пароля (в реальной системе используйте хеширование!)
if(!strcmp(password, "admin123", true)) { // Пример пароля
AdminData[playerid][adminLogged] = true;

new msg[128], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(msg, sizeof(msg), "[ADMIN] %s вошел в систему администрирования (уровень: %d)", name, AdminData[playerid][adminLevel]);
SendAdminMessage(COLOR_ADMIN, msg);

SendClientMessage(playerid, COLOR_GREEN, "Вы успешно вошли в админку!");
return 1;
}

SendClientMessage(playerid, COLOR_RED, "Ошибка: Неверный пароль!");
return 1;
}
```

## 👮 6. Основные админ-команды

```pawn
CMD:a(playerid, params[]) {
if(!AdminData[playerid][adminLogged])
return SendClientMessage(playerid, COLOR_RED, "Ошибка: Вы не авторизованы в админке!");

if(isnull(params))
return SendClientMessage(playerid, COLOR_WHITE, "Использование: /a [текст]");

new msg[128], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(msg, sizeof(msg), "[A] %s (%d): %s", name, playerid, params);
SendAdminMessage(COLOR_ADMINCHAT, msg);
return 1;
}

CMD:kick(playerid, params[]) {
if(!AdminData[playerid][adminLogged] || AdminData[playerid][adminLevel] < ADMIN_MODERATOR)
return SendClientMessage(playerid, COLOR_RED, "Ошибка: Недостаточно прав!");

new targetid, reason[64];
if(sscanf(params, "us[64]", targetid, reason))
return SendClientMessage(playerid, COLOR_WHITE, "Использование: /kick [id] [причина]");

if(!IsPlayerConnected(targetid))
return SendClientMessage(playerid, COLOR_RED, "Ошибка: Игрок не найден!");

new msg[128], adminName[MAX_PLAYER_NAME], targetName[MAX_PLAYER_NAME];
GetPlayerName(playerid, adminName, sizeof(adminName));
GetPlayerName(targetid, targetName, sizeof(targetName));

format(msg, sizeof(msg), "[ADMIN] %s кикнул %s. Причина: %s", adminName, targetName, reason);
SendClientMessageToAll(COLOR_ADMIN_ACTION, msg);

AdminData[playerid][adminActions]++;
AdminData[playerid][adminKicks]++;
SaveAdminData(playerid);

SetTimerEx("DelayedKick", 1000, false, "i", targetid);
return 1;
}
```

## 📝 7. Логирование действий

```pawn
LogAdminAction(adminid, const action[]) {
if(!IsPlayerConnected(adminid)) return;

new logEntry[256], adminName[MAX_PLAYER_NAME], date[24];
GetPlayerName(adminid, adminName, sizeof(adminName));
getdate(date, sizeof(date));

format(logEntry, sizeof(logEntry), "[%s] %s (ID: %d | Level: %d): %s",
date, adminName, adminid, AdminData[adminid][adminLevel], action);

new File:file = fopen("admin_actions.log", io_append);
if(file) {
fwrite(file, logEntry);
fwrite(file, "\r\n");
fclose(file);
}
}
```

## 🛡️ 8. Защита от злоупотреблений

```pawn
CheckAdminAbuse(playerid) {
// Проверяем подозрительную активность
if(AdminData[playerid][adminActions] > 50 && GetPlayerTime(playerid)/3600 < 1) {
new msg[128], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));

format(msg, sizeof(msg), "[WARNING] Возможное злоупотребление: %s (ID: %d) совершил %d действий за 1 час",
name, playerid, AdminData[playerid][adminActions]);

SendMessageToHighAdmins(COLOR_RED, msg);
LogAdminAction(playerid, "ПРЕДУПРЕЖДЕНИЕ: Возможное злоупотребление");
}
}

public OnPlayerCommandPerformed(playerid, cmdtext[], success) {
if(AdminData[playerid][adminLogged]) {
AdminData[playerid][adminActions]++;

// Логируем каждую команду админа
if(success) {
LogAdminAction(playerid, cmdtext);
}

// Проверяем на злоупотребления каждые 10 команд
if(AdminData[playerid][adminActions] % 10 == 0) {
CheckAdminAbuse(playerid);
}
}
return 1;
}
```

## 📚 9. Дополнительные полезные функции

```pawn
SendAdminMessage(color, const message[]) {
foreach(new i : Player) {
if(AdminData[adminLogged]) {
SendClientMessage(i, color, message);
}
}
}

GetAdminRankName(level) {
new rank[32];
switch(level) {
case ADMIN_NONE: rank = "Игрок";
case ADMIN_HELPER: rank = "Помощник";
case ADMIN_MODERATOR: rank = "Модератор";
case ADMIN_ADMIN: rank = "Администратор";
case ADMIN_HEAD_ADMIN: rank = "Старший Админ";
case ADMIN_OWNER: rank = "Владелец";
default: rank = "Неизвестно";
}
return rank;
}

IsPlayerAdminLevel(playerid, level) {
if(!IsPlayerConnected(playerid)) return false;
if(!AdminData[playerid][adminLogged]) return false;
return (AdminData[playerid][adminLevel] >= level);
}
```

## 🔄 10. Обработчики основных событий

```pawn
public OnPlayerConnect(playerid) {
// Сброс данных
AdminData[playerid][adminLevel] = ADMIN_NONE;
AdminData[playerid][adminLogged] = false;
AdminData[playerid][adminActions] = 0;
strcpy(AdminData[playerid][adminName], "");

// Загрузка данных, если игрок админ
LoadAdminData(playerid);
return 1;
}

public OnPlayerDisconnect(playerid, reason) {
if(AdminData[playerid][adminLevel] > ADMIN_NONE) {
SaveAdminData(playerid);
}
return 1;
}
 
Последнее редактирование модератором:
Дальше — Больше
Команда форума
Модератор
Регистрация
21 Янв 2023
Сообщения
966
OFFTOP

вырвите мои глаза, что я увидел...

 
even if it’s rare, it doesn’t mean it’s useful
Профессионал
Регистрация
2 Ноя 2024
Сообщения
1,532
OFFTOP

хотя бы под код или спойлер положите пожалуйста🙏

 
Сверху