Доброго времени суток.
Данный материал прежде всего предназначен для RP/RPG-серверов, однако если будет использоваться где-то еще - спорить не буду.
Итак, небольшое вступление.
На некоторых серверах существуют правила для ника игрока. Самый яркий пример - РП-сервера, где ник обычно требуют в формате %name%_%surname%. Более того, кое-где существует запрет на регистрацию с ником, имя в котором указано в уменьшительно-ласкательной или иной, отличной от официальной, формы (Sasha вместо Alexander и так далее). При достаточно большом количестве игроков уследить за подобными случаями становится все сложнее.
Но, как говорится, "кто ищет - тот всегда найдет!"
Перед скриптом ставились следующие задачи:
- Хранить где-то базу некорректных ников. Это показалось проще, чем вести базу корректных.
- Иметь удобные инструменты для добавления, удаления и проверки наличия записи.
- Не допускать игрока к серверу в случае совпадения имени с базой и отключать от сервера в случае добавления новой записи в базу.
Первую задачу решено было решить, используя SQLite. Создавать что-то на файлах показалось мне не слишком удобным в реализации, а на MySQL такую ерунду делать не хотелось. Хотя можно и ее использовать, но зачем, если, по сути, нам нужна только одна колонка в БД?
Вторая решилась еще тривиальнее - три команды-три запроса к базе. Еще один запрос - в момент подключения.
Но - обо всем по порядку.
Итак, для начала необходимо подключить нужные библиотеки. В нашем случае - a_samp и a_sampdb.
Для удобства забьем имя файла с базой как директиву препроцессора.
Далее - создаем переменную типа DB для хранения указателя на открытую базу и переменную типа DBResult для хранения возвращаемых из базы результатов.
Начнем с загрузки самой базы. Я использовал код в отдельном ФС, однако ничто не мешает зашить его в гейммод.
Первоначально с помощью команды db_open открываем файл, имя которого забито в db_name. Или создаем, если он не был создан:
Далее - делаем запрос в базу. Необходимо, если таблицы Nicks не существует - создать ее с одной колонкой NICK типа varchar - символьной строки. Делается это простым запросом:
Проверять отдельно, есть ли таблица в файле и есть ли файл вообще, нет необходимости, как нет необходимости и в дальнейших действиях при загрузке ГМ или ФС.
Конечный код в случае ФС будет выглядеть так:
После выгрузки ГМ или ФС базу нужно корректно закрыть. Тут все еще проще - db_close().
Далее я решил начать с реализации проверки на наличие ника в базе и, соответственно, запрещению доступа к серверу, если ник в базе есть.
Алгоритм действий таков:
- Получаем ник игрока. Это достаточно просто, есть стандартная функция GetPlayerName(), описывать ее я смысла не вижу.
- Выделение из ника имени и фамилии.
Обычно разделителем выступает нижняя черта - ее проверять и будем. Берем с SA:MP Wiki функцию split:Создаем двумерный массив для хранения имени и фамилии и записываем в его элементы отдельно имя и отдельно фамилию, полученные после работы split(). - Запрос в базу на наличие ника.
Проверка организована просто - в базу посылается запрос, в ответе проверяем, сколько строк вернула база. Если не ноль - значит, записи есть и ник запрещен, а значит - игрока нужно кикнуть. Если ноль - записи нет, ник разрешен, ничего с игроком делать не нужно.
Берем OnPlayerConnect и производим все необходимые действия по алгоритму:
Хочу обратить внимание на сам запрос в БД:
Оператор LIKE здесь используется как оператор нестрогого сравнения - то есть регистр символов может не совпадать. Однако с русскими символами в строке такой запрос не пройдет, что в MySQL, что в SQLite придется городить костыли. У меня не используются ники с русскими символами, поэтому меня такой запрос вполне устраивает в текущем виде.
Ну и осталось, собственно, только организовать удобство работы с такой базой.
Поскольку бросать идею не хотелось, а использовать для такого порыва покодить какие-то сторонние тулзы вроде командных процессоров было откровенно лень - все построено на стандартной функции OnPlayerCommandText и ненавистной многими strtok:
Однако, конечно, если захотите использовать другой командный процессор - пожалуйста, перетаскивайте.
Начнем с команды добавления записи в базу и одновременной проверки игроков на свежедобавленное имя. Алгоритм прост - из строки cmdtext получаем необходимый параметр и делаем запрос к базе, после чего циклом проверяем все имена игроков, полученные split().
Далее код с комментариями, который, конечно, нужно пихнуть в OnPlayerCommandText, в котором уже объявлены нужные переменные для strtok:
Похожая ситуация - с удалением записи. Даже если похожей записи нет - запрос ничего лишнего не удалит, поэтому на проверку наличия в базе можно не заморачиваться.
В конкретном случае вместо строгого сравнения в запросе опять используется оператор LIKE.
Ну, и функция проверки на наличие записи. Тут все аналогично проверке в OnPlayerConnect - если запрос вернет более нуля строк как результат, значит, запись есть. В противном случае - нет.
На этом все! Система работоспособна и готова к наполнению невалидными никами.
Исходник также доступен на пастбине.
Данное решение, возможно, не является суперсовершенным и суперфункциональным, но то, чего я хотел - я добился. Все работает, и работает как надо.
Вопросы и пожелания принимаются ниже.



Сообщений: 57
Регистрация: