Консоль разработчика
Этот документ объясняет, как писать код в консоль , как исполнять и создавать консольные команды и переменные. Смотрите Консоль разработчика для обзора возможностей консоли.
Печать в консоли
Ввод текста в консоль доступен из всех модулей и контролируется через Tier(). Есть 3 дополнительные команды Msg()
, DevMsg()
и Warning()
которые поддерживают вывод форматированной строки, как sprintf()
:
DevMsg (char const* pMsg, ... ) - только в режиме разработчика Msg(char const* pMsg, ... ) - всегда, белый текст Warning(char const *pMsg, ... ) - всегда, красный текст
Для обратной совместимости с HL1 сохранены команды Con_Printf()
и Con_DPrintf()
.
Исполнение команд
Движок использует интерфейс сервера и клиента, чтобы исполнять команды (строки). Сервер использует интерфейс IVEngineServer::ServerCommand()
:
engine->ServerCommand("changelevel de_dust\n");
Клиент использует интерфейс IVEngineClient и выбирает между двумя командами, от этого зависит, будет ли команда исполняться сначала на клиенте или посылаться непосредственно серверу:
engine->ServerCmd( "say hello\n" ); // послать команду на сервер
или
engine->ClientCmd( "say hello\n" ); // выполнить команду на клиенте
Добавление новых команд и переменных
Консоль разработчика - это подсистема движка Source, которая дает доступ к различным модулям, это осуществляется через интерфейс ICvar
( см. \public\icvar.h
). Этот интерфейс регистрирует новые команды и ищет существующие. Этот интрефейс доступен через глобальную переменную CVAR в клиент-серверном коде (cv в коде движка). Консольные команды принадлежат классу ConCommand
, а консольные переменные ConVar
, которые оба происходят от базового класса ConCommandBase
(см. \public\convar.h
).
Добавление новых команд и переменных довольно просто и дуступно для использования и для серверных и для клиентских (одинаково для всего движка) модулей. Конструктор этих классов автоматически регистрирует новую команду/переменную в системе консоли. Этот короткий пример кода добавляет новую команду my_function и новую переменную my_variable инициализированную значение 42:
#include <convar.h> ConVar my_variable( "my_variable", "42", FCVAR_ARCHIVE, "My favorite number" ); void MyFunction_f( void ) { Msg("This is my function\n"); } ConCommand my_function( "my_function", MyFunction_f, "Shows a message.", FCVAR_CHEAT );
Это обычное использование когда имя объекта и команды одинаковое и переменные используются только в одном исходнике описываются как static.
Использование класса ConVar
Для начала рассмотрим наиболее используемый ConVar конструктор:
ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString )
Первый аргумент pName
это имя переменной (без пробелов), следующий pDefaultValue
,всегда является строковым, даже для ConVar 's с числовыми значениями. Flags
пределяет специальные характеристики переменной, все описания флагов начинаются с FCVAR_*
, но об этом позже. Очень хорошо использовать pHelpString
, чтобы пользователи могли понять для чего эта переменная предназначена. ConVar s не огрнаичиваются определненным типом, их значение может быть целым или вещественным или строкой и вы можете его использовать как вам угодно. Так долго как у вас есть ConVar объект сам или указатель на него, вы можете смотреть и изменять его значение напрямую. Все эти примеры правильны и дадут одинаковый результат:
if ( my_variable.GetInt() == 42 ) DoSomething(); if ( my_variable.GetFloat() == 42.0f ) DoSomething(); if ( strcmp(my_variable.GetString(), "42")==0 ) DoSomething();
Для установки значения ConVar вы должны использовать функцию SetValue()
, использующая любые типы данных:
my_variable.SetValue( 42 ); my_variable.SetValue( 42.0f ); my_variable.SetValue( "42" );
В любое время вы можете вернуть значение [ConVar]] назад к значению по-умолчанию использовав функцию Revert()
.
Если ConVar создан в разных модулях, то в интерфейсе ICvar
функция FindVar()
спользуется для получения указателя на объект, если имя переменной установлено. Вот простой пример, который проверяет установлена ли ConVar sv_cheats определенная в модуле движка:
ConVar *pCheats = cvar->FindVar( "sv_cheats" ); if ( pCheats && pCheats->GetInt() == 1 ) AllowCheating();
Диапозон правильных значений может быть определен для числовых ConVar s используя другой конструктор. Тогда ConVar автоматически проверяется консольной системой всякий когда она изменяется вручную. Если введенное число выходит за границы диапозона, оно округляется к следующему правильному значению. Установка диапозона правильных значений от 1 до 100:
ConVar my_variable( "my_variable", "42", 0, "helptext", true, 1, true, 100 );
Иногда необходимо чтобы вы получали извещение когда пользователь или другая подсистема меняет значение вашей ConVar , поэтому может быть установлена функция обратного вызова:
static void OnChangeMyVariable ( ConVar *var, char const *pOldString ) { DevMsg( "ConVar %s was changed from %s to %s\n", var->GetName(), pOldString, var->GetString() ); } ConVar my_variable( "my_variable", "42", 0, "My favorite number", OnChangeMyVariable );
Использование класса ConCommand
Class
ConCommand проще чем ConVar и у него только один конструктор:
ConCommand( char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
Как и у ConVar pName
определяет имя команды (без пробелов!). callback
эта функция выполняемая когда пользователь исполняет эту команду, pHelpString
и флаги имебт те же функции что и в ConVar. ConCommands поддерживает автозавершение для первого параметра,
особенно используемый для которые обрабатывают файлы. Например, вы используете команду loadtext lt;textfilegt
; которая предполагает .txt файл для ввода, консоль ищет все доступные .txt файлы и позволяет пользователю выбрать один из списка. Если правильно то completionFunc
проходит, она вызывается каждый раз когда консольной системе требуется список доступных аргументов.
Когда callback
фунция выполняется, параметры введенные в консоле не подаются как аргументы функции. callback
функциям необходимо запрашивать у движка как много аргументов поступило используя фунцию интерфейса движка Cmd_Argc()
. Затем можно получить отдельные аргументы используя Cmd_Argv(index)
, где index 1 это первый аргумент. Аргументы всегда возвращаются как строки.
void MySay_f ( void ) { if ( engine->Cmd_Argc() < 1 ) { Msg(""Usage: my_say <text>\n"); return; } Msg("I say: %s\n", engine->Cmd_Argv(1) ); } ConCommand my_say( "my_say", MySay_f, "say something", 0);
Это пример как построить простой спивок авто завершения. Неполный параметр не используется здесь; он содержит символы введеные так давно (включая само имя команды) :
static int MySayAutoComplete ( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEвMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ) { strcpy( commands[0], "hello" ); strcpy( commands[1], "goodbye" ); return 2; // number of entries } ConCommand my_say( "my_say", MySay_f, "say something", 0, MySayAutoComplete);
Флаги FCVAR_
Консольные команды/переменные используют флаги, которые обладают определенными характеристиками и должны обрабатываться с осторожностью. Эти флаги используются конструктором и могут быть изменены с помощью ConCommandBase::AddFlags()
(не используются сильно часто). Невозможно изменить эти флаги подругому как в исходных кодах чтобы избежать читов. Некоторые флаги должны быть установлены вручную, другие устанавливаются автоматически консольной системой:
FCVAR_LAUNCHER, FCVAR_GAMEDLL, FCVAR_CLIENTDLL, FCVAR_MATERIAL_SYSTEM, FCVAR_STUDIORENDER
Эти флаги устанавливаются в процессе регистрации и указывают на модуль, где команда создана (вам не нужно устанавливать их). Следующие флаги должны быть установлены вручную:
FCVAR_CHEAT
|
Используются при отладке, не удаляются из релиза по причине того, что могут потребоваться разработчикам модов и карт. К сожелению мы неможем позволить нормальным игрокам использовать эти инструменты отладки так как это бы было нечестно по отношению к другим игрокам (читерство). Хорошее правило добавлять FCVAR_CHEAT по началу ко всем новым консольным командам которые вы добавляете, если это не конечная и законная опция для игроков. Опыт показывает что даже наиболее безвредные отладочные команды могут быть использоваться тем или иным образом как чит.
Игровой сервер устанавливая |
FCVAR_USERINFO
|
Некоторые консольные переменные содержат клиентскую информацию о которой должен знать сервер, такое как имаена пользователей или их четевые настройки. Эти переменные должны быть помечены флагом FCVAR_USERINFO , тогда они будут преданы серверу и обновляться каждый раз когда пользователь изменяет их. Когда пользователь изменяет эти переменные движок оповещает серверный код с помощью ClientSettingsChanged() . Затем сервер может запросить движок отдельные клиентские настройки с помощью GetClientConVarValue() .
|
FCVAR_REPLICATED
|
Игровой сервер и клиент используют общий код, поэтому важно чтобы обе стороны выполнялись по одиноковому пути используя одинаковые данные (например предсказание движения/оружий, правил игы). Если этот код использует консольные переменные, они должны иметь одинаковые значения на обоих сторонах. Флаг FCVAR_REPLICATED гарантирует рассылку значений всем клиентам. Пока подключены, клиенты немогут менять эти значения так как будут использовать серверные значения.
|
FCVAR_ARCHIVE
|
Некоторые консольные переменные содержат пользовательские настройки мы хотим их востанавливать кадый раз когда игра запущена ( как имя или network_rate ). Если консольная переменная помечена как FCVAR_ARCHIVE , она сохраняется в файл config.cfg когда игра завершается и она будет загружена при следующем запуске. (Также команда host_writeconfig сохранет все FCVAR_ARCHIVE значения в файл).
|
FCVAR_NOTIFY
|
Если консольная переменная помечена как FCVAR_NOTIFY , сервер отправляет сообщение всем клиентам всякий раз когда переменная изменена. Это должно быть использовано для перменных которые меняют правила игры, которые важны для всех игроков (mp_friendlyfire например).
|
FCVAR_PROTECTED
|
Жта консольная перменная содержащая частную информацию (пароль например), мы нехотим чтобы она была видна другим пользователям. Для этого должен быть установлен флаг FCVAR_PROTECTED чтобы пометить эту информацию как конфиденциальную.
|
FCVAR_SPONLY
|
Иногда исполнение команды или изменение переменной может быть правильно только в однопользовательском режиме, тогда пометьте эту команду как FCVAR_SPONLY .
|
FCVAR_PRINTABLEONLY
|
Некоторые важные переменные тяжелые или шировещательные (например правила игры) и важно что они содержат только печатные сиволы (например нет управляющих символов). |
FCVAR_NEVER_AS_STRING
|
Этот флаг говорит движку никогда невыводить эту переменную как строку так как она содержит последовательность управляющих символов. |
FCVAR_DEMO
|
Когда на чинаешь записывать демо файл, некоторые консольные перменные должны быть добавлены к записи чтобы быть уверенными что она правильна будет воспроизведена. |
FCVAR_DONTRECORD
|
Это обратно FCVAR_DEMO, некоторые консольные переменные не должны быть записаны в демо файлы. |