Русское сообщество по скриптингу

(Неактуально) Использование возможностей motd_write

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

(Неактуально) Использование возможностей motd_write

Сообщение DJ_WEST » 27 сен 2009, 23:08

Автор: DJ_WEST

Хочу рассказать Вам о моем способе использования клиентских возможностей для работы с MOTD файлом. Всего существует три команды:
  • motdfile - команда, указывающая какой MOTD файл отображается при соединении к серверу, то есть используется в основном для сервера. По умолчанию: motd.txt.
  • motd_write - команда, используемая для записи текстовой информации в MOTD файл, который указан в motdfile.
  • motd - команда, используемая для отображения содержимого MOTD файла, указанного в motdfile, в консоль клиента.

Для наших целей мы будем использовать только две первые команды, а именно motdfile и motd_write. Существует ряд ограничений при использовании данных команд:
  • Мы можем использовать файлы только в пределах папки мода, в нашем случае cstrike. Использовать вложенные каталоги в cstrike можно, а выйти на уровень выше - нет. Другими словами, мы можем использовать в качестве MOTD файлы из директории cstrike/models или cstrike/sprites, но не файлы, которые за пределами cstrike директории.
  • Мы не можем использовать для motd_write некоторые типы файлов, такие как: exe, dll, cfg, rc, com, bat (возможно и другие, я указал те, о которых мне известно).
  • Мы не можем записывать файл в директорию, которая не существует в cstrike на клиенте. Другими словами, если мы хотим записать файл в cstrike/test/test.txt и у игрока нет директории cstrike/test, то ничего не выйдет.
  • Записывая данные через motd_write в файл, который уже существует, мы удаляем его содержимое полностью, заменяя своими данными. Другими словами, дописать в файл информацию нельзя.
  • Через motd_write мы можем записать максимум 1012 байт информации.

Итак, получается, что мы можем записать через motd_write 1012 байт информации, но как записать информацию в несколько строк? Потому что новый абзац в motd_write считается концом, тем самым обрывается дальнейшая запись строки. Не беда, я расскажу, как можно записать информацию в несколько строк и что нам это даст в практическом использовании.

Прежде всего помните, что через motd_write можно нарушить целостность игры клиента: повредить bsp карту, повредить mdl модель, повредить liblist.gam или какие-то другие важные файлы игры. Поэтому используйте возможности данной команды на своем сервере на свой страх и риск. Вы должны понимать результат своих действий.

К примеру, выполняя данный код:
Код: Выделить всё
// Указываем файл, который будет использоваться (cstrike/models/amx-x.mdl)
client_cmd(id, "motdfile models/amx-x.mdl")
// Записываем текст Example в файл
client_cmd(id, "motd_write Example")
// Возвращаем значение команды motdfile по умолчанию
client_cmd(id, "motdfile motd.txt")
 

В результате у игрока в директории cstrike/models появится новый файл amx-x.mdl с содержимым Example. Ясно, что данная модель работать не будет и использовать мы ее не сможем. Потому что модели имеют сложное содержимое, которое даже свыше допустимых 1012 байт.

Сейчас попробуем разобраться, как записать в файл данные в несколько строк. Для удобства воспользуемся бесплатным текстовым редактором Notepad++. Чтобы видеть скрытые символы в тексте нужно в меню программы выбрать "Вид" - "Отображение символов" - "Все символы". Теперь открыв какой-нибудь текстовый файл мы увидем такие символы, как CR LF, которые означают новую строку.
  • LF: подача строки (ALT + 010)
  • CR: возврат каретки (ALT + 013)
Теперь если мы в файле будем считывать информацию, где содержатся символы CR LF и передавать данную информацию через client_cmd(id, motd_write ...), то запись оборвется, как будут найдены символы CR LF, то есть движок игры не разрешает выполнить то, что мы хотим. Но если мы будем вместо CR LF использовать только символ CR, то запись пройдет успешно и фактически редакторы будут понимать, что это новая строка, кроме обычного Notepad. Главное, что движок игры будет понимать, что это новая строка. Почему главное? Сейчас рассмотрим пример, как добавить опцию подключения к вашему серверу в меню игрока игры Counter-Strike 1.6!
За меню игры отвечает файл cstrike/resource/GameMenu.res.
По умолчанию он имеет такой вид (взято из Steam версии игры):
Код: Выделить всё

"GameMenu"
{
   "1"
   {
      "label" "#GameUI_GameMenu_ResumeGame"
      "command" "ResumeGame"
      "OnlyInGame" "1"
   }
   "2"
   {
      "label" "#GameUI_GameMenu_Disconnect"
      "command" "Disconnect"
      "OnlyInGame" "1"
      "notsingle" "1"
   }
   "4"
   {
      "label" "#GameUI_GameMenu_PlayerList"
      "command" "OpenPlayerListDialog"
      "OnlyInGame" "1"
      "notsingle" "1"
   }
   "8"
   {
      "label" ""
      "command" ""
      "OnlyInGame" "1"
   }
   "9"
   {
      "label" "#GameUI_GameMenu_NewGame"
      "command" "OpenCreateMultiplayerGameDialog"
   }
   "10"
   {
      "label" "#GameUI_GameMenu_FindServers"
      "command" "OpenServerBrowser"
   }
   "11"
   {
      "label" "#GameUI_GameMenu_Options"
      "command" "OpenOptionsDialog"
   }
   "12"
   {
      "label" "#GameUI_GameMenu_Quit"
      "command" "Quit"
   }
}

Если попытаться разобраться в нем, то:
  • label - это название опции, которое и будет отображаться в меню игры
  • command - команда, которая будет выполняться при нажатии данной опции меню. В данном случае эти команды понятны только движку игры, но если использовать в них engine, то это приведет к выполнению консольной команды игры, то есть тоже самое, что если игрок выполнит ее в консоли лично:
    command "engine connect 127.0.0.1:27015

    Нажатие опции с данной командой приведет к подключению клиента к серверу с адресом 127.0.0.1:27015.
  • OnlyInGame - если имеет значение 1, то означает, что опция будет видна меню, если игрок будет в игре.
  • notsingle - если значение 1, то опция видна только в multiplayer режиме, а Counter-Strike 1.6 имеет как раз такой режим.
Допустим у нас есть сервер с адресом 127.0.0.1:27015 и мы хотим, чтобы в меню игры у игроков была опция подключения к нашему серверу. Для этого мы редактируем GameMenu.res и получаем:
Код: Выделить всё

"GameMenu"
{
   "1"
   {
      "label" "Join to AMX-X.RU Server"
      "command" "engine connect 127.0.0.1:27015"
   }
   "2"
   {
      "label" ""
      "command" ""
   }
   "3"
   {
      "label" "#GameUI_GameMenu_ResumeGame"
      "command" "ResumeGame"
      "OnlyInGame" "1"
   }
   "4"
   {
      "label" "#GameUI_GameMenu_Disconnect"
      "command" "Disconnect"
      "OnlyInGame" "1"
      "notsingle" "1"
   }
   "5"
   {
      "label" "#GameUI_GameMenu_PlayerList"
      "command" "OpenPlayerListDialog"
      "OnlyInGame" "1"
      "notsingle" "1"
   }
   "6"
   {
      "label" ""
      "command" ""
      "OnlyInGame" "1"
   }
   "7"
   {
      "label" "#GameUI_GameMenu_NewGame"
      "command" "OpenCreateMultiplayerGameDialog"
   }
   "8"
   {
      "label" "#GameUI_GameMenu_FindServers"
      "command" "OpenServerBrowser"
   }
   "9"
   {
      "label" "#GameUI_GameMenu_Options"
      "command" "OpenOptionsDialog"
   }
   "10"
   {
      "label" "#GameUI_GameMenu_Quit"
      "command" "Quit"
   }
}

Теперь нам нужно, чтобы файл имеел правильное содержимое для его использовании в нашем плагине. Заменяем CR LF на CR. Чтобы вставить символ CR, зажимаем на клавиатуре ALT затем набираем 013. В конце файла оставляем CR LF, как конец. После всех изменений у меня получился файл размером 776 байт, что не превышает наш лимит (1012 байт). Сохраняем его, как gamemenu.txt, к примеру, и ложим в addons/amxmodx/configs.

[align=center]
gamemenu.jpg
[/align]

Теперь напишем плагин для чтения нашего gamemenu.txt и записи его игроку:
Код: Выделить всё
#include <amxmodx>

#define PLUGIN "Game Menu"
#define VERSION "1.0"
#define AUTHOR "DJ_WEST"

#define GAMEMENU_FILE "resource/GameMenu.res"
#define MAX_SIZE 1012

new g_Text[MAX_SIZE]

public plugin_init() 
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    
    
// Вызываем функцию Read_GameMenu для чтения нашего исправленного файла меню.
    set_task(0.1, "Read_GameMenu")
}

public Read_GameMenu()
{
    new i_File, s_File[128]
    
    
// Получаем путь к директории с конфигами AMXX в s_File.
    get_configsdir(s_File, charsmax(s_File))
    
    
// Формируем путь к gamemenu.txt файлу, используя путь к конфигам, и сохраняем в s_File.
    format(s_File, charsmax(s_File), "%s/gamemenu.txt", s_File)
    
    
// Открываем файл для чтения
    i_File = fopen(s_File, "r")
    
    
// Читаем содержимое файла в g_Text. Данная функция поддерживает чтение символов CR, LF.
    fgets(i_File, g_Text, MAX_SIZE)
    
    
// Закрываем файл
    fclose(i_File)
}

public client_putinserver(id)
{
    // Вызываем функцию Change_GameMenu
    set_task(3.0, "Change_GameMenu", id)
}

stock get_configsdir(s_Name[], i_Len)
{
    return get_localinfo("amxx_configsdir", s_Name, i_Len)
}

public Change_GameMenu(id)
{
    // Указываем путь к файлу resource/GameMenu.res
    client_cmd(id, "motdfile %s", GAMEMENU_FILE)
    
    
// Записываем в файл содержимое g_Text
    client_cmd(id, "motd_write %s", g_Text)
    
    
// Возвращаем значение команды по умолчанию
    client_cmd(id, "motdfile motd.txt")    
}
 

Изменения меню вступят в силу после перезапуска игры. Или выполнения команды _restart.
Помните, что данным способом вы стираете клиентский GameMenu.res файл, который может быть уже был изменен игроком по его предпочтениям и желанию.

[align=center]
gamemenu_after.jpg
[/align]
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Использование возможностей motd_write

Сообщение Co6aka » 28 сен 2009, 00:53

Nice :) Очень полезная статья.
Аватара пользователя
Co6aka
 
Сообщения: 226
Зарегистрирован: 30 авг 2009, 21:19
Благодарил (а): 54 раз.
Поблагодарили: 114 раз.
Языки программирования: Counter-Strike 1.6

Re: Использование возможностей motd_write

Сообщение Fedcomp » 28 сен 2009, 02:33

опана убойная статья .... кто там говорил что файлы на клиенте не меняются? мы идем к вам
Не помогаю в ЛС - есть форум.
Плагины тоже не пишу, на форуме достаточно хороших скриптеров.


"я ставлю зависимости потому что мне приятно" - subb98 @ 2017
Аватара пользователя
Fedcomp
Администратор
 
Сообщения: 4936
Зарегистрирован: 28 авг 2009, 20:47
Благодарил (а): 813 раз.
Поблагодарили: 1317 раз.
Языки программирования: =>
pawn / php / python / ruby
javascript / rust

Re: Использование возможностей motd_write

Сообщение Co6aka » 28 сен 2009, 02:52

Fedcomp, я говорил :-[
реаллайт лабс - нет ничего невозможного? :bravo:
Аватара пользователя
Co6aka
 
Сообщения: 226
Зарегистрирован: 30 авг 2009, 21:19
Благодарил (а): 54 раз.
Поблагодарили: 114 раз.
Языки программирования: Counter-Strike 1.6

Re: Использование возможностей motd_write

Сообщение Fedcomp » 28 сен 2009, 11:10

Я тоже так говорил. Но это наверно первый форум на русском где я действительно вижу как минимум одного проф. скриптера, который в отличие от остальных наиболее полно отвечает на вопросы, причем сразу. :thumbs_up
:ps: смайл :thumbs_up
Код: Выделить всё
:thumbs_up
почему то, а не
:thumbs_up:
Не помогаю в ЛС - есть форум.
Плагины тоже не пишу, на форуме достаточно хороших скриптеров.


"я ставлю зависимости потому что мне приятно" - subb98 @ 2017
Аватара пользователя
Fedcomp
Администратор
 
Сообщения: 4936
Зарегистрирован: 28 авг 2009, 20:47
Благодарил (а): 813 раз.
Поблагодарили: 1317 раз.
Языки программирования: =>
pawn / php / python / ruby
javascript / rust

Re: Использование возможностей motd_write

Сообщение whuru » 28 сен 2009, 17:32

Код в посте:

Код: Выделить всё
{
    new i_File, s_File[128]
   
    // Получаем путь к директории с конфигами AMXX в s_File.
    get_configsdir(s_File, charsmax(s_File))
   
    // Формируем путь к gamemenu.txt файлу, используя путь к конфигам, и сохраняем в s_File.
    format(s_File, charsmax(s_File), "%s/gamemenu.txt", s_File)
   
    // Открываем файл для чтения
    i_File = fopen(s_File, "r")
   
    // Читаем содержимое файла в g_Text. Данная функция поддерживает чтение символов CR, LF.
    fgets(i_File, g_Text, MAX_SIZE)
   
    // Закрываем файл
    fclose(i_File)
}


Код в прикрепленном файле:
Код: Выделить всё
{
   new i_File, s_File[128]
   
   // Получаем путь к директории с конфигами AMXX в s_File.
   get_configsdir(s_File, charsmax(s_File))
   
   // Формируем путь к gamemenu.txt файлу, используя путь к конфигам, и сохраняем в s_File.
   format(s_File, charsmax(s_File), "%s/gamemenu.txt", s_File)
   
   // Открываем файл для чтения
   i_File = fopen(s_File, "r")
   
   // Читаем содержимое файла в g_Text. Данная функция поддерживает чтение символов CR, LF.
   fgets(i_File, g_Text, MAX_SIZE)
   
   write_file("TEST.txt", g_Text)
   
   
   // Закрываем файл
   fclose(i_File)
}


Откуда тут взялся TEST.txt? :dntknw:
И вообще, который в теле поста не компилируется - 5 ошибок.
91.207.238.49:27015
Аватара пользователя
whuru
 
Сообщения: 26
Зарегистрирован: 03 сен 2009, 11:31
Откуда: Саратовская обл.
Благодарил (а): 18 раз.
Поблагодарили: 1 раз.

Re: Использование возможностей motd_write

Сообщение Ser_UFL » 28 сен 2009, 18:07

Всё без ошибок и прикрепленный, и из поста.
AMXModX последний.
P.S. Удали
Код: Выделить всё
   
   write_file("TEST.txt", g_Text)
   
Запомните, всегда по жизни вас будут красить вежливость и спокойствие, а не наезды и дешевые понты ;)
Аватара пользователя
Ser_UFL
 
Сообщения: 975
Зарегистрирован: 22 авг 2009, 19:30
Откуда: Hell
Благодарил (а): 276 раз.
Поблагодарили: 380 раз.
Языки программирования: Counter-Strike 1.6:
WebMod-scripts, little Pawn.

Re: Использование возможностей motd_write

Сообщение DJ_WEST » 28 сен 2009, 18:50

Код: Выделить всё
 write_file("TEST.txt"g_Text

Не нужно, это я для проверки делал =)
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Использование возможностей motd_write

Сообщение DJ_WEST » 29 сен 2009, 17:08

Я помню пытался изменить hud.txt, чтобы добавить новые спрайты на клиент, тем самым добавив возможность их использования через сервер, но 1012 байт маловато для всех спрайтов, даже на перечень стандартных не хватает, обидно =(
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Использование возможностей motd_write

Сообщение whuru » 29 сен 2009, 17:21

Для Windows 7 64bit не работает. Менюшку не заменяет. Обидно...
91.207.238.49:27015
Аватара пользователя
whuru
 
Сообщения: 26
Зарегистрирован: 03 сен 2009, 11:31
Откуда: Саратовская обл.
Благодарил (а): 18 раз.
Поблагодарили: 1 раз.

След.

Вернуться в Статьи / фрагменты кода

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10