Вопросы

Surfer_Selectrum
Новичок

здравствуйте, подскажите как сделать так, чтобы команда /makeadmin после назначения игрока на админа, или повышение админа, добавляла в базу данных админку игроку, чтобы в таблице users меняла уровень админки, а в таблице admins добавляла игрока и также изменяла уровень.

Code:

CMD:makeadmin(playerid, params[])
{
    new string[128];
    if(GetAdmin(playerid, adminLogin) == falsereturn SCM(playerid, 0xA3A3A3FF"{C20000}[Ошибка]"C_GREY" Вы не являетесь администратором");
    if(GetAdmin(playerid, adminLevel) < 6return SCM(playerid, 0xA3A3A3FF"{C20000}[Ошибка]"C_GREY" Вы не можете использовать данную команду.");
    if(sscanf(params, "ii", params[0], params[1])) return SCM(playerid, 0xA3A3A3AA"{C20000}[Ошибка]"C_GREY" Введите: /makeadmin [ID] [Level].");
    if(!IsPlayerConnected(params[0])) return SCM(playerid, 0xA3A3A3FF"{C20000}[Ошибка]"C_GREY" Данный игрок не в сети!");
    if(params[1] < 0 || params[1] > 8return SCM(playerid, 0xA3A3A3FF"{C20000}[Ошибка]"C_GREY" Уровень администратора [0-8]");
    InfoPlayer[params[0]][pAdmin] = params[1];
    format(string, sizeof(string), "Администратор %s изменил ваш уровень администратора на: %d", InfoPlayer[playerid][pName], params[1]);
    SCM(params[0], 0xFFFFFFAA, string);
    return true;
}

Screens - click

 

Снимок экрана 2024-07-25 234801.png

Снимок экрана 2024-07-25 234904.png

Снимок экрана 2024-07-25 234923.png

Снимок экрана 2024-07-25 235212.png

Поделиться сообщением


Ссылка на сообщение

11 ответов на этот вопрос

  • 0
Cawfee
Великий Гуру

@Surfer_Selectrum, это называется избыточность: вы в двух таблицах храните и уровень прав администратора, и имя пользователя. В вашем случае правильнее хранить в столбце admin таблицы users идентификатор дескриптора (описателя) прав администратора в таблице admins. Тогда таблица admins не будет содержать столбец name, а таблица users в столбце admin не будет хранить уровень прав администратора текущего пользователя.

 

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

Поделиться сообщением


Ссылка на сообщение
  • 0
moffes
Новичок

Если я правильно понял, то:
 

Создать в таблицу admins:

mysql_format(mysql, query, sizeof query, "INSERT INTO admins (name, password, level) VALUES (%s, %d, '%d')", name, password, level);

    mysql_query(mysql, query, false);


Изменить в Users:

mysql_format(mysql, query, sizeof query, "UPDATE users SET admin=%d", admin);
    mysql_query(mysql, query, false);

только все замени под себя

Если я все же правильно тебя понял, то нужно сделать проверку на то, есть ли уже в admins строка

Отредактировано пользователем moffes

Поделиться сообщением


Ссылка на сообщение
  • 0
Cawfee
Великий Гуру


@moffes, не совсем. Идея в том, чтобы можно было сопоставить данные из таблиц users и admins на основе общего поля (идентификатора аккаунта) через операторы соединения (JOIN).

 

Таблица users должна иметь следующие столбцы:

  1. id (уникальный идентификатор аккаунта).
  2. name.
  3. password.
  4. sex.
  5. skin.
  6. money.
  7. regip.
  8. lastip.

Обратите внимание на отсутствие столбца admin!

 

Таблица admins должна иметь следующие столбцы:

  1. id (уникальный номер записи).
  2. accountid (уникальный идентификатор аккаунта, аналогичный полю id таблицы users.
  3. password.
  4. level.

 

Теперь для выдачи прав администратора игроку нужно создать новую запись в таблице admins. Для изменения текущих прав администратора нужно, соответственно, изменить существующую запись. Удаление записи влечет лишение игрока прав администратора. Для того, чтобы при подключении игрока к серверу одним запросом получить всю информацию как из таблицы users, так и из таблицы admins, нужно соединить обе этих таблицы по столбцу admins. Например, вот так:

"SELECT * FROM users LEFT JOIN admins ON users.id = admins.accountid WHERE users.name = '%s' and users.password = '%s'", PlayerInfo[playerid][pAccountID], PlayerInfo[playerid][pPassword]

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

Поделиться сообщением


Ссылка на сообщение
  • 0
surenescore
Освоившийся

@Surfer_Selectrum Чтобы решить твою проблему правильно: нужно учитывать несколько моментов архитектуры базы данных и обеспечения целостности данных. В твоем же случае наблюдается что ты хранишь уровень администратора и имя пользователя в двух таблицах (`admins` и `users`), что не является оптимальным подходом.

 

Правильнее было бы использовать одну таблицу для хранения информации об уровне администратора и ссылаться на нее из основной таблицы пользователей. Это уменьшит избыточность и упростит управление данными. Например, в таблице `users` у тебя должен быть столбец `admin_id`, который ссылается на идентификатор в таблице `admins`.

 

Твой текущий код не включает операции вставки и обновления в базу данных. Вот как это можно сделать, сохраняя корректность и эффективность работы:

CMD:makeadmin(playerid, params[])
{
    new string[128];
    new pname[MAX_PLAYER_NAME];
    GetPlayerName(playerid, pname, sizeof(pname));

    if(GetAdmin(playerid, adminLogin) == falsereturn SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Вы не являетесь администратором");
    if(GetAdmin(playerid, adminLevel) < 6return SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Вы не можете использовать данную команду");

    if(!IsPlayerConnected(params[1])) return SCM(playerid, 0xA3A3A3AA"[C20000]Ошибка[]C_GREY] Данный игрок не в сети!");
    if(!strlen(params[1]) || !strlen(params[2])) return SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Введите: /makeadmin [ID игрока] [Уровень администратора 0-8]");

    new targetid = strval(params[1]);
    new level = strval(params[2]);

    if(level < 0 || level > 8return SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Уровень администратора [0-8]!");

    format(string, sizeof(string), "SELECT `id` FROM `users` WHERE `name`='%s'", pname);
    new Cache:cache = db_query(mysqlHandle, string);
    if(cache_get_row_count(cache) == 0) {
        db_free_result(cache);
        return SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Пользователь не найден в базе данных");
    }
    db_free_result(cache);

    if(level == 0) {
        format(string, sizeof(string), "DELETE FROM `admins` WHERE `name`='%s'", pname);
        db_query(mysqlHandle, string);
    } else {
        format(string, sizeof(string), "REPLACE INTO `admins` (`name`, `password`, `level`) VALUES ('%s', '%s', %d)", pname, "somepassword", level);
        db_query(mysqlHandle, string);
    }

    format(string, sizeof(string), "UPDATE `users` SET `admin`=%d WHERE `name`='%s'", level, pname);
    db_query(mysqlHandle, string);

    InfoPlayer[targetid][pName] = level;
    format(string, sizeof(string), "Администратор %s изменил ваш уровень администратора на: %d", pname, level);
    SCM(params[0], 0xFFFFFFAA, string);

    return true;
}

 

В этом коде выполняется сначала проверка наличия пользователя в таблице `users`. Если он найден, затем проверяется уровень администратора. Если он равен 0, то запись удаляется из таблицы `admins`. В противном случае используется `REPLACE INTO`, чтобы обновить или вставить новую запись в `admins`. Также обновляется поле `admin` в таблице `users`.

Такой подход минимизирует избыточность данных и поддерживает целостность и консистентность базы данных.

Отредактировано пользователем D2DChat
Причина: Орфографические ошибки.

Поделиться сообщением


Ссылка на сообщение
  • 0
Surfer_Selectrum
Новичок

@D2DChat 

Снимок экрана 2024-07-27 223136.png

@D2DChat ../server/admins/cmd.inc(30) : error 017: undefined symbol "mysqlHandle"
../server/admins/cmd.inc(30) : warning 213: tag mismatch: expected tag "Cache", but found "DBResult"
../server/admins/cmd.inc(31) : warning 213: tag mismatch: expected tag none ("_"), but found "Cache"
../server/admins/cmd.inc(32) : warning 213: tag mismatch: expected tag "DBResult", but found "Cache"
../server/admins/cmd.inc(35) : warning 213: tag mismatch: expected tag "DBResult", but found "Cache"
../server/admins/cmd.inc(39) : error 017: undefined symbol "mysqlHandle"
../server/admins/cmd.inc(42) : error 017: undefined symbol "mysqlHandle"
../server/admins/cmd.inc(46) : error 017: undefined symbol "mysqlHandle"

некоторые ошибки исправил

 

Отредактировано пользователем Surfer_Selectrum

Поделиться сообщением


Ссылка на сообщение
  • 0
surenescore
Освоившийся

@Surfer_Selectrum 

CMD:makeadmin(playerid, params[])
{
    new string[256];
    new pname[MAX_PLAYER_NAME];
    GetPlayerName(playerid, pname, sizeof(pname));

    if(GetAdmin(playerid, adminLogin) == falsereturn SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Вы не являетесь администратором");
    if(GetAdmin(playerid, adminLevel) < 6return SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Вы не можете использовать данную команду");

    if(!IsPlayerConnected(params[1])) return SCM(playerid, 0xA3A3A3AA"[C20000]Ошибка[]C_GREY] Данный игрок не в сети!");
    if(!strlen(params[1]) || !strlen(params[2])) return SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Введите: /makeadmin [ID игрока] [Уровень администратора 0-8]");

    new targetid = strval(params[1]);
    new level = strval(params[2]);

    if(level < 0 || level > 8return SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Уровень администратора [0-8]!");

    format(string, sizeof(string), "SELECT `id` FROM `users` WHERE `name`='%s'", pname);
    mysql_tquery(mysqlHandle, string, "OnAdminCheckQuery""ii", playerid, level);

    return true;
}

forward OnAdminCheckQuery(playerid, level);
public OnAdminCheckQuery(playerid, level)
{
    new string[256];
    new pname[MAX_PLAYER_NAME];
    GetPlayerName(playerid, pname, sizeof(pname));

    if(cache_num_rows() == 0) {
        return SCM(playerid, 0xA3A3A3FF"[C20000]Ошибка[]C_GREY] Пользователь не найден в базе данных");
    }

    if(level == 0) {
        format(string, sizeof(string), "DELETE FROM `admins` WHERE `name`='%s'", pname);
        mysql_tquery(mysqlHandle, string);
    } else {
        format(string, sizeof(string), "REPLACE INTO `admins` (`name`, `password`, `level`) VALUES ('%s', '%s', %d)", pname, "somepassword", level);
        mysql_tquery(mysqlHandle, string);
    }

    format(string, sizeof(string), "UPDATE `users` SET `admin`=%d WHERE `name`='%s'", level, pname);
    mysql_tquery(mysqlHandle, string);

    InfoPlayer[playerid][pName] = level;
    format(string, sizeof(string), "Администратор %s изменил ваш уровень администратора на: %d", pname, level);
    SCM(playerid, 0xFFFFFFAA, string);

    return true;
}

 

Поделиться сообщением


Ссылка на сообщение
  • 0
Cawfee
Великий Гуру

@D2DChat, не нужен столбец admin в таблице users – он вообще не имеет никакого смысла, это избыточность. Достаточно в таблице admins завести столбец для хранения идентификатора аккаунта, который и будет первичным и уникальным ключом для данной таблицы.

Поделиться сообщением


Ссылка на сообщение
Гость
Эта тема закрыта для публикации ответов.
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

  • Похожий контент

    • Доналдо Фарекелка
      От Доналдо Фарекелка


      Скачать файл Christmas Live » RPG | XS
      Приветствую, сливаю мод, который делал самолично. Мод недоработан, возможно где-то имеются баги, без лаунчера.
      Взят под основу от Phantom RolePlay. Отдельная благодарность за мод WW.INC
      Основная информация про мод:
       
      Информация про сервер:
      Записка:
      ПРИМЕР -  скриншот, сделанный для показа чего-либо и скриншот может является устаревшей информацией(Пояснение: Что-то изменилось, а что-то нет).
      Добавил Доналдо Фарекелка Добавлено 14.03.2025 Категория Моды Автор Donaldo_Farekelka  
    • KAIF HOST
      От KAIF HOST
      Если вы ищете надежный, стабильный и бюджетный хостинг для ваших серверов SAMP или CRMP, то KAIF-HOST.RU - лучший выбор для вас. Мы молодая компания среди игровых хостингов, но мы гарантируем стабильность и безопасность вашего сервера.
       
      Мы предлагаем защиту от TCP SYN и UDP флуда, а также от Spoofing атак. Мы также обеспечиваем защиту на уровнях L3, L4 и L7.
       
      Наши преимущества включают автоподнятие серверов после падения, удобную панель управления сервером и автоматическую установку сервера. Мы также гарантируем быструю техническую поддержку для всех наших клиентов.
       
       
       
      Наши серверы доступны всего от 20 рублей в месяц, что делает нас одним из самых доступных хостингов на рынке.
       
       
       
       
       
       Ссылки:
       
      Сайт kaif-host.ru
      Панель управления lk.kaif-host.ru
      Группа ВКонтакте https://vk.com/kaif_host_official
       
      P.s Промокод #pawnorus даст тебе скидку в размере 20%

    • watson
      От watson
      Привет всем!

      Выкладываю рабочий инструмент, который лично писал под задачи для крупных бонусных проектов. От меня недавно произошла доработка - теперь при записи маршрута сохраняются все сообщения, которые вы пишете в чат.
       
      Как это работает Запуск записи:
      Вводите /route с названием скрипта (или биндите на клавишу) — скрипт начинает фиксировать всё ваше передвижение (onfoot/incar/aim пакеты) и любые ваши сообщения в чат. Завершение:
      Ещё раз /route с названием скрипта или /stop — сохраняется маршрут вместе с чатом в файл формата .rt в папке MoonLoader/rakbotRoutes. Воспроизведение:
      Через команду !play <название> в консоли RakSamp LITE — бот воспроизводит маршрут один в один с вашими действиями, повторяет весь ввод, а так-же отправляет в чат все сохранённые сообщения (имитация через Enter). Поддержка цикла:
      Можно включить повтор маршрута (!loop), пока не надоест. Что важно в коде
      Запись всех синк-пакетов (движения, анимации, aim и т.д.):
      Пакеты по движению (onfoot/incar/aim) записываются подробно — никакой халтуры, каждое значение (позиция, кватернион, скорость, анимации, флаги и т.д.) фиксируется для полной копии.  

       
      Запись сообщений чата по индексам
      Каждое сообщение, которое отправляется в чат во время записи маршрута, сохраняется в отдельную таблицу с текущим индексом (counter). То есть при воспроизведении бот знает, на каком этапе какой текст нужно “цитировать” в чат.  

       
      Воспроизведение маршрута и чата
      На каждом этапе воспроизведения проверяется, было ли сообщение в этот момент — если да, оно “отправляется” как будто в оригинале, без задержек и рассинхрона. Пакеты проигрываются по индексу — как только доходит до конца, скрипт сам решает, останавливать ли выполнение или запускать по кругу (если включен loop).  

       
      Формат сохранения
      Файл маршрута содержит не только действия, но и отдельную секцию [chat], что позволяет воспроизвести всё как было, а не только беготню.  

       
       
      Если кому-то реально нужна автоматизация для бонусных серверов и не только как например фейковые игроки и вам важна последовательность действий и чата — этот инструмент сэкономит часы времени. Всё написано максимально просто для внедрения.

      P.S. Если есть определённые проблемы, вопросы или даже идеи для доработки — пишите.
      Desktop.zip