Пользователь
- Регистрация
- 17 Май 2023
- Сообщения
- 50
- Автор темы
- #1
#
Полный гайд по созданию системы админки для 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;
}

```pawn
#include <a_samp>
#include <zcmd> // Для удобных команд
#include <sscanf2> // Для парсинга параметров
#include <YSI\y_ini> // Для работы с файлами
#include <logger> // Для логирования действий
#include <timestamp> // Для временных меток
#define PATH_ADMIN_DATA "/AdminData/%s.ini" // Путь к файлам данных
```
##

```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];
```
##

```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;
}
```
##

```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;
}
```
##

```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;
}
```
##

```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;
}
```
##

```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);
}
}
```
##

```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;
}
```
##

```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);
}
```
##

```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;
}
Последнее редактирование модератором: