Консоль разработчика
Этот документ объясняет, как писать код в консоль, как исполнять и создавать консольные команды и переменные. Смотрите Консоль разработчика для обзора возможностей консоли.
Contents
Печать в консоли
Ввод текста в консоль доступен из всех модулей и контролируется через 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
, чтобы пользователи могли понять для чего эта переменная предназначена. ConVars не огрнаичиваются определненным типом, их значение может быть целым или вещественным или строкой и вы можете его использовать как вам угодно. Так долго как у вас есть 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();
Диапозон правильных значений может быть определен для числовых ConVars используя другой конструктор. Тогда 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, некоторые консольные переменные не должны быть записаны в демо файлы. |