hello world

This commit is contained in:
Timothee 'TTimo' Besset
2011-11-22 15:28:15 -06:00
commit fb1609f554
2155 changed files with 1017022 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*
===============================================================================
Preprocessor settings for compiling different versions.
===============================================================================
*/
// memory debugging
//#define ID_REDIRECT_NEWDELETE
//#define ID_DEBUG_MEMORY
//#define ID_DEBUG_UNINITIALIZED_MEMORY
// if enabled, the console won't toggle upon ~, unless you start the binary with +set com_allowConsole 1
// Ctrl+Alt+~ will always toggle the console no matter what
#ifndef ID_CONSOLE_LOCK
#if defined(_WIN32) || defined(MACOS_X)
#ifdef _DEBUG
#define ID_CONSOLE_LOCK 0
#else
#define ID_CONSOLE_LOCK 1
#endif
#else
#define ID_CONSOLE_LOCK 0
#endif
#endif
// useful for network debugging, turns off 'LAN' checks, all IPs are classified 'internet'
#ifndef ID_NOLANADDRESS
#define ID_NOLANADDRESS 0
#endif
// let .dds be loaded from FS without altering pure state. only for developement.
#ifndef ID_PURE_ALLOWDDS
#define ID_PURE_ALLOWDDS 0
#endif
// build an exe with no CVAR_CHEAT controls
#ifndef ID_ALLOW_CHEATS
#define ID_ALLOW_CHEATS 0
#endif
#ifndef ID_ENABLE_CURL
#define ID_ENABLE_CURL 1
#endif
// fake a pure client. useful to connect an all-debug client to a server
#ifndef ID_FAKE_PURE
#define ID_FAKE_PURE 0
#endif
// verify checksums in clientinfo traffic
// NOTE: this makes the network protocol incompatible
#ifndef ID_CLIENTINFO_TAGS
#define ID_CLIENTINFO_TAGS 0
#endif
// for win32 this is defined in preprocessor settings so that MFC can be
// compiled out.
//#define ID_DEDICATED
// if this is defined, the executable positively won't work with any paks other
// than the demo pak, even if productid is present.
//#define ID_DEMO_BUILD
// don't define ID_ALLOW_TOOLS when we don't want tool code in the executable.
#if defined( _WIN32 ) && !defined( ID_DEDICATED ) && !defined( ID_DEMO_BUILD )
#define ID_ALLOW_TOOLS
#endif
// don't do backtraces in release builds.
// atm, we have no useful way to reconstruct the trace, so let's leave it off
#define ID_BT_STUB
#ifndef ID_BT_STUB
#if defined( __linux__ )
#if defined( _DEBUG )
#define ID_BT_STUB
#endif
#else
#define ID_BT_STUB
#endif
#endif
#ifndef ID_ENFORCE_KEY
# if !defined( ID_DEDICATED ) && !defined( ID_DEMO_BUILD )
# define ID_ENFORCE_KEY 1
# else
# define ID_ENFORCE_KEY 0
# endif
#endif
#ifndef ID_OPENAL
# if ( defined(_WIN32) || defined(MACOS_X) ) && !defined( ID_DEDICATED )
# define ID_OPENAL 1
# else
# define ID_OPENAL 0
# endif
#endif
#ifndef ID_ALLOW_D3XP
# if defined( MACOS_X )
# define ID_ALLOW_D3XP 0
# else
# define ID_ALLOW_D3XP 1
# endif
#endif

View File

@@ -0,0 +1,28 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
const int BUILD_NUMBER = 1304;

1257
neo/framework/CVarSystem.cpp Normal file

File diff suppressed because it is too large Load Diff

309
neo/framework/CVarSystem.h Normal file
View File

@@ -0,0 +1,309 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __CVARSYSTEM_H__
#define __CVARSYSTEM_H__
/*
===============================================================================
Console Variables (CVars) are used to hold scalar or string variables
that can be changed or displayed at the console as well as accessed
directly in code.
CVars are mostly used to hold settings that can be changed from the
console or saved to and loaded from configuration files. CVars are also
occasionally used to communicate information between different modules
of the program.
CVars are restricted from having the same names as console commands to
keep the console interface from being ambiguous.
CVars can be accessed from the console in three ways:
cvarName prints the current value
cvarName X sets the value to X if the variable exists
set cvarName X as above, but creates the CVar if not present
CVars may be declared in the global namespace, in classes and in functions.
However declarations in classes and functions should always be static to
save space and time. Making CVars static does not change their
functionality due to their global nature.
CVars should be contructed only through one of the constructors with name,
value, flags and description. The name, value and description parameters
to the constructor have to be static strings, do not use va() or the like
functions returning a string.
CVars may be declared multiple times using the same name string. However,
they will all reference the same value and changing the value of one CVar
changes the value of all CVars with the same name.
CVars should always be declared with the correct type flag: CVAR_BOOL,
CVAR_INTEGER or CVAR_FLOAT. If no such flag is specified the CVar
defaults to type string. If the CVAR_BOOL flag is used there is no need
to specify an argument auto-completion function because the CVar gets
one assigned automatically.
CVars are automatically range checked based on their type and any min/max
or valid string set specified in the constructor.
CVars are always considered cheats except when CVAR_NOCHEAT, CVAR_INIT,
CVAR_ROM, CVAR_ARCHIVE, CVAR_USERINFO, CVAR_SERVERINFO, CVAR_NETWORKSYNC
is set.
===============================================================================
*/
typedef enum {
CVAR_ALL = -1, // all flags
CVAR_BOOL = BIT(0), // variable is a boolean
CVAR_INTEGER = BIT(1), // variable is an integer
CVAR_FLOAT = BIT(2), // variable is a float
CVAR_SYSTEM = BIT(3), // system variable
CVAR_RENDERER = BIT(4), // renderer variable
CVAR_SOUND = BIT(5), // sound variable
CVAR_GUI = BIT(6), // gui variable
CVAR_GAME = BIT(7), // game variable
CVAR_TOOL = BIT(8), // tool variable
CVAR_USERINFO = BIT(9), // sent to servers, available to menu
CVAR_SERVERINFO = BIT(10), // sent from servers, available to menu
CVAR_NETWORKSYNC = BIT(11), // cvar is synced from the server to clients
CVAR_STATIC = BIT(12), // statically declared, not user created
CVAR_CHEAT = BIT(13), // variable is considered a cheat
CVAR_NOCHEAT = BIT(14), // variable is not considered a cheat
CVAR_INIT = BIT(15), // can only be set from the command-line
CVAR_ROM = BIT(16), // display only, cannot be set by user at all
CVAR_ARCHIVE = BIT(17), // set to cause it to be saved to a config file
CVAR_MODIFIED = BIT(18) // set when the variable is modified
} cvarFlags_t;
/*
===============================================================================
idCVar
===============================================================================
*/
class idCVar {
public:
// Never use the default constructor.
idCVar( void ) { assert( typeid( this ) != typeid( idCVar ) ); }
// Always use one of the following constructors.
idCVar( const char *name, const char *value, int flags, const char *description,
argCompletion_t valueCompletion = NULL );
idCVar( const char *name, const char *value, int flags, const char *description,
float valueMin, float valueMax, argCompletion_t valueCompletion = NULL );
idCVar( const char *name, const char *value, int flags, const char *description,
const char **valueStrings, argCompletion_t valueCompletion = NULL );
virtual ~idCVar( void ) {}
const char * GetName( void ) const { return internalVar->name; }
int GetFlags( void ) const { return internalVar->flags; }
const char * GetDescription( void ) const { return internalVar->description; }
float GetMinValue( void ) const { return internalVar->valueMin; }
float GetMaxValue( void ) const { return internalVar->valueMax; }
const char ** GetValueStrings( void ) const { return valueStrings; }
argCompletion_t GetValueCompletion( void ) const { return valueCompletion; }
bool IsModified( void ) const { return ( internalVar->flags & CVAR_MODIFIED ) != 0; }
void SetModified( void ) { internalVar->flags |= CVAR_MODIFIED; }
void ClearModified( void ) { internalVar->flags &= ~CVAR_MODIFIED; }
const char * GetString( void ) const { return internalVar->value; }
bool GetBool( void ) const { return ( internalVar->integerValue != 0 ); }
int GetInteger( void ) const { return internalVar->integerValue; }
float GetFloat( void ) const { return internalVar->floatValue; }
void SetString( const char *value ) { internalVar->InternalSetString( value ); }
void SetBool( const bool value ) { internalVar->InternalSetBool( value ); }
void SetInteger( const int value ) { internalVar->InternalSetInteger( value ); }
void SetFloat( const float value ) { internalVar->InternalSetFloat( value ); }
void SetInternalVar( idCVar *cvar ) { internalVar = cvar; }
static void RegisterStaticVars( void );
protected:
const char * name; // name
const char * value; // value
const char * description; // description
int flags; // CVAR_? flags
float valueMin; // minimum value
float valueMax; // maximum value
const char ** valueStrings; // valid value strings
argCompletion_t valueCompletion; // value auto-completion function
int integerValue; // atoi( string )
float floatValue; // atof( value )
idCVar * internalVar; // internal cvar
idCVar * next; // next statically declared cvar
private:
void Init( const char *name, const char *value, int flags, const char *description,
float valueMin, float valueMax, const char **valueStrings, argCompletion_t valueCompletion );
virtual void InternalSetString( const char *newValue ) {}
virtual void InternalSetBool( const bool newValue ) {}
virtual void InternalSetInteger( const int newValue ) {}
virtual void InternalSetFloat( const float newValue ) {}
static idCVar * staticVars;
};
ID_INLINE idCVar::idCVar( const char *name, const char *value, int flags, const char *description,
argCompletion_t valueCompletion ) {
if ( !valueCompletion && ( flags & CVAR_BOOL ) ) {
valueCompletion = idCmdSystem::ArgCompletion_Boolean;
}
Init( name, value, flags, description, 1, -1, NULL, valueCompletion );
}
ID_INLINE idCVar::idCVar( const char *name, const char *value, int flags, const char *description,
float valueMin, float valueMax, argCompletion_t valueCompletion ) {
Init( name, value, flags, description, valueMin, valueMax, NULL, valueCompletion );
}
ID_INLINE idCVar::idCVar( const char *name, const char *value, int flags, const char *description,
const char **valueStrings, argCompletion_t valueCompletion ) {
Init( name, value, flags, description, 1, -1, valueStrings, valueCompletion );
}
/*
===============================================================================
idCVarSystem
===============================================================================
*/
class idCVarSystem {
public:
virtual ~idCVarSystem( void ) {}
virtual void Init( void ) = 0;
virtual void Shutdown( void ) = 0;
virtual bool IsInitialized( void ) const = 0;
// Registers a CVar.
virtual void Register( idCVar *cvar ) = 0;
// Finds the CVar with the given name.
// Returns NULL if there is no CVar with the given name.
virtual idCVar * Find( const char *name ) = 0;
// Sets the value of a CVar by name.
virtual void SetCVarString( const char *name, const char *value, int flags = 0 ) = 0;
virtual void SetCVarBool( const char *name, const bool value, int flags = 0 ) = 0;
virtual void SetCVarInteger( const char *name, const int value, int flags = 0 ) = 0;
virtual void SetCVarFloat( const char *name, const float value, int flags = 0 ) = 0;
// Gets the value of a CVar by name.
virtual const char * GetCVarString( const char *name ) const = 0;
virtual bool GetCVarBool( const char *name ) const = 0;
virtual int GetCVarInteger( const char *name ) const = 0;
virtual float GetCVarFloat( const char *name ) const = 0;
// Called by the command system when argv(0) doesn't match a known command.
// Returns true if argv(0) is a variable reference and prints or changes the CVar.
virtual bool Command( const idCmdArgs &args ) = 0;
// Command and argument completion using callback for each valid string.
virtual void CommandCompletion( void(*callback)( const char *s ) ) = 0;
virtual void ArgCompletion( const char *cmdString, void(*callback)( const char *s ) ) = 0;
// Sets/gets/clears modified flags that tell what kind of CVars have changed.
virtual void SetModifiedFlags( int flags ) = 0;
virtual int GetModifiedFlags( void ) const = 0;
virtual void ClearModifiedFlags( int flags ) = 0;
// Resets variables with one of the given flags set.
virtual void ResetFlaggedVariables( int flags ) = 0;
// Removes auto-completion from the flagged variables.
virtual void RemoveFlaggedAutoCompletion( int flags ) = 0;
// Writes variables with one of the given flags set to the given file.
virtual void WriteFlaggedVariables( int flags, const char *setCmd, idFile *f ) const = 0;
// Moves CVars to and from dictionaries.
virtual const idDict * MoveCVarsToDict( int flags ) const = 0;
virtual void SetCVarsFromDict( const idDict &dict ) = 0;
};
extern idCVarSystem * cvarSystem;
/*
===============================================================================
CVar Registration
Each DLL using CVars has to declare a private copy of the static variable
idCVar::staticVars like this: idCVar * idCVar::staticVars = NULL;
Furthermore idCVar::RegisterStaticVars() has to be called after the
cvarSystem pointer is set when the DLL is first initialized.
===============================================================================
*/
ID_INLINE void idCVar::Init( const char *name, const char *value, int flags, const char *description,
float valueMin, float valueMax, const char **valueStrings, argCompletion_t valueCompletion ) {
this->name = name;
this->value = value;
this->flags = flags;
this->description = description;
this->flags = flags | CVAR_STATIC;
this->valueMin = valueMin;
this->valueMax = valueMax;
this->valueStrings = valueStrings;
this->valueCompletion = valueCompletion;
this->integerValue = 0;
this->floatValue = 0.0f;
this->internalVar = this;
if ( staticVars != (idCVar *)0xFFFFFFFF ) {
this->next = staticVars;
staticVars = this;
} else {
cvarSystem->Register( this );
}
}
ID_INLINE void idCVar::RegisterStaticVars( void ) {
if ( staticVars != (idCVar *)0xFFFFFFFF ) {
for ( idCVar *cvar = staticVars; cvar; cvar = cvar->next ) {
cvarSystem->Register( cvar );
}
staticVars = (idCVar *)0xFFFFFFFF;
}
}
#endif /* !__CVARSYSTEM_H__ */

783
neo/framework/CmdSystem.cpp Normal file
View File

@@ -0,0 +1,783 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
/*
===============================================================================
idCmdSystemLocal
===============================================================================
*/
typedef struct commandDef_s {
struct commandDef_s * next;
char * name;
cmdFunction_t function;
argCompletion_t argCompletion;
int flags;
char * description;
} commandDef_t;
class idCmdSystemLocal : public idCmdSystem {
public:
virtual void Init( void );
virtual void Shutdown( void );
virtual void AddCommand( const char *cmdName, cmdFunction_t function, int flags, const char *description, argCompletion_t argCompletion = NULL );
virtual void RemoveCommand( const char *cmdName );
virtual void RemoveFlaggedCommands( int flags );
virtual void CommandCompletion( void(*callback)( const char *s ) );
virtual void ArgCompletion( const char *cmdString, void(*callback)( const char *s ) );
virtual void BufferCommandText( cmdExecution_t exec, const char *text );
virtual void ExecuteCommandBuffer( void );
virtual void ArgCompletion_FolderExtension( const idCmdArgs &args, void(*callback)( const char *s ), const char *folder, bool stripFolder, ... );
virtual void ArgCompletion_DeclName( const idCmdArgs &args, void(*callback)( const char *s ), int type );
virtual void BufferCommandArgs( cmdExecution_t exec, const idCmdArgs &args );
virtual void SetupReloadEngine( const idCmdArgs &args );
virtual bool PostReloadEngine( void );
void SetWait( int numFrames ) { wait = numFrames; }
commandDef_t * GetCommands( void ) const { return commands; }
private:
static const int MAX_CMD_BUFFER = 0x10000;
commandDef_t * commands;
int wait;
int textLength;
byte textBuf[MAX_CMD_BUFFER];
idStr completionString;
idStrList completionParms;
// piggybacks on the text buffer, avoids tokenize again and screwing it up
idList<idCmdArgs> tokenizedCmds;
// a command stored to be executed after a reloadEngine and all associated commands have been processed
idCmdArgs postReload;
private:
void ExecuteTokenizedString( const idCmdArgs &args );
void ExecuteCommandText( const char *text );
void InsertCommandText( const char *text );
void AppendCommandText( const char *text );
static void ListByFlags( const idCmdArgs &args, cmdFlags_t flags );
static void List_f( const idCmdArgs &args );
static void SystemList_f( const idCmdArgs &args );
static void RendererList_f( const idCmdArgs &args );
static void SoundList_f( const idCmdArgs &args );
static void GameList_f( const idCmdArgs &args );
static void ToolList_f( const idCmdArgs &args );
static void Exec_f( const idCmdArgs &args );
static void Vstr_f( const idCmdArgs &args );
static void Echo_f( const idCmdArgs &args );
static void Parse_f( const idCmdArgs &args );
static void Wait_f( const idCmdArgs &args );
static void PrintMemInfo_f( const idCmdArgs &args );
};
idCmdSystemLocal cmdSystemLocal;
idCmdSystem * cmdSystem = &cmdSystemLocal;
/*
============
idCmdSystemLocal::ListByFlags
============
*/
// NOTE: the const wonkyness is required to make msvc happy
template<>
ID_INLINE int idListSortCompare( const commandDef_t * const *a, const commandDef_t * const *b ) {
return idStr::Icmp( (*a)->name, (*b)->name );
}
void idCmdSystemLocal::ListByFlags( const idCmdArgs &args, cmdFlags_t flags ) {
int i;
idStr match;
const commandDef_t *cmd;
idList<const commandDef_t *> cmdList;
if ( args.Argc() > 1 ) {
match = args.Args( 1, -1 );
match.Replace( " ", "" );
} else {
match = "";
}
for ( cmd = cmdSystemLocal.GetCommands(); cmd; cmd = cmd->next ) {
if ( !( cmd->flags & flags ) ) {
continue;
}
if ( match.Length() && idStr( cmd->name ).Filter( match, false ) == 0 ) {
continue;
}
cmdList.Append( cmd );
}
cmdList.Sort();
for ( i = 0; i < cmdList.Num(); i++ ) {
cmd = cmdList[i];
common->Printf( " %-21s %s\n", cmd->name, cmd->description );
}
common->Printf( "%i commands\n", cmdList.Num() );
}
/*
============
idCmdSystemLocal::List_f
============
*/
void idCmdSystemLocal::List_f( const idCmdArgs &args ) {
idCmdSystemLocal::ListByFlags( args, CMD_FL_ALL );
}
/*
============
idCmdSystemLocal::SystemList_f
============
*/
void idCmdSystemLocal::SystemList_f( const idCmdArgs &args ) {
idCmdSystemLocal::ListByFlags( args, CMD_FL_SYSTEM );
}
/*
============
idCmdSystemLocal::RendererList_f
============
*/
void idCmdSystemLocal::RendererList_f( const idCmdArgs &args ) {
idCmdSystemLocal::ListByFlags( args, CMD_FL_RENDERER );
}
/*
============
idCmdSystemLocal::SoundList_f
============
*/
void idCmdSystemLocal::SoundList_f( const idCmdArgs &args ) {
idCmdSystemLocal::ListByFlags( args, CMD_FL_SOUND );
}
/*
============
idCmdSystemLocal::GameList_f
============
*/
void idCmdSystemLocal::GameList_f( const idCmdArgs &args ) {
idCmdSystemLocal::ListByFlags( args, CMD_FL_GAME );
}
/*
============
idCmdSystemLocal::ToolList_f
============
*/
void idCmdSystemLocal::ToolList_f( const idCmdArgs &args ) {
idCmdSystemLocal::ListByFlags( args, CMD_FL_TOOL );
}
/*
===============
idCmdSystemLocal::Exec_f
===============
*/
void idCmdSystemLocal::Exec_f( const idCmdArgs &args ) {
char * f;
int len;
idStr filename;
if ( args.Argc () != 2 ) {
common->Printf( "exec <filename> : execute a script file\n" );
return;
}
filename = args.Argv(1);
filename.DefaultFileExtension( ".cfg" );
len = fileSystem->ReadFile( filename, reinterpret_cast<void **>(&f), NULL );
if ( !f ) {
common->Printf( "couldn't exec %s\n", args.Argv(1) );
return;
}
common->Printf( "execing %s\n", args.Argv(1) );
cmdSystemLocal.BufferCommandText( CMD_EXEC_INSERT, f );
fileSystem->FreeFile( f );
}
/*
===============
idCmdSystemLocal::Vstr_f
Inserts the current value of a cvar as command text
===============
*/
void idCmdSystemLocal::Vstr_f( const idCmdArgs &args ) {
const char *v;
if ( args.Argc () != 2 ) {
common->Printf( "vstr <variablename> : execute a variable command\n" );
return;
}
v = cvarSystem->GetCVarString( args.Argv( 1 ) );
cmdSystemLocal.BufferCommandText( CMD_EXEC_APPEND, va( "%s\n", v ) );
}
/*
===============
idCmdSystemLocal::Echo_f
Just prints the rest of the line to the console
===============
*/
void idCmdSystemLocal::Echo_f( const idCmdArgs &args ) {
int i;
for ( i = 1; i < args.Argc(); i++ ) {
common->Printf( "%s ", args.Argv( i ) );
}
common->Printf( "\n" );
}
/*
============
idCmdSystemLocal::Wait_f
Causes execution of the remainder of the command buffer to be delayed until next frame.
============
*/
void idCmdSystemLocal::Wait_f( const idCmdArgs &args ) {
if ( args.Argc() == 2 ) {
cmdSystemLocal.SetWait( atoi( args.Argv( 1 ) ) );
} else {
cmdSystemLocal.SetWait( 1 );
}
}
/*
============
idCmdSystemLocal::Parse_f
This just prints out how the rest of the line was parsed, as a debugging tool.
============
*/
void idCmdSystemLocal::Parse_f( const idCmdArgs &args ) {
int i;
for ( i = 0; i < args.Argc(); i++ ) {
common->Printf( "%i: %s\n", i, args.Argv(i) );
}
}
/*
============
idCmdSystemLocal::Init
============
*/
void idCmdSystemLocal::Init( void ) {
AddCommand( "listCmds", List_f, CMD_FL_SYSTEM, "lists commands" );
AddCommand( "listSystemCmds", SystemList_f, CMD_FL_SYSTEM, "lists system commands" );
AddCommand( "listRendererCmds", RendererList_f, CMD_FL_SYSTEM, "lists renderer commands" );
AddCommand( "listSoundCmds", SoundList_f, CMD_FL_SYSTEM, "lists sound commands" );
AddCommand( "listGameCmds", GameList_f, CMD_FL_SYSTEM, "lists game commands" );
AddCommand( "listToolCmds", ToolList_f, CMD_FL_SYSTEM, "lists tool commands" );
AddCommand( "exec", Exec_f, CMD_FL_SYSTEM, "executes a config file", ArgCompletion_ConfigName );
AddCommand( "vstr", Vstr_f, CMD_FL_SYSTEM, "inserts the current value of a cvar as command text" );
AddCommand( "echo", Echo_f, CMD_FL_SYSTEM, "prints text" );
AddCommand( "parse", Parse_f, CMD_FL_SYSTEM, "prints tokenized string" );
AddCommand( "wait", Wait_f, CMD_FL_SYSTEM, "delays remaining buffered commands one or more frames" );
completionString = "*";
textLength = 0;
}
/*
============
idCmdSystemLocal::Shutdown
============
*/
void idCmdSystemLocal::Shutdown( void ) {
commandDef_t *cmd;
for ( cmd = commands; cmd; cmd = commands ) {
commands = commands->next;
Mem_Free( cmd->name );
Mem_Free( cmd->description );
delete cmd;
}
completionString.Clear();
completionParms.Clear();
tokenizedCmds.Clear();
postReload.Clear();
}
/*
============
idCmdSystemLocal::AddCommand
============
*/
void idCmdSystemLocal::AddCommand( const char *cmdName, cmdFunction_t function, int flags, const char *description, argCompletion_t argCompletion ) {
commandDef_t *cmd;
// fail if the command already exists
for ( cmd = commands; cmd; cmd = cmd->next ) {
if ( idStr::Cmp( cmdName, cmd->name ) == 0 ) {
if ( function != cmd->function ) {
common->Printf( "idCmdSystemLocal::AddCommand: %s already defined\n", cmdName );
}
return;
}
}
cmd = new commandDef_t;
cmd->name = Mem_CopyString( cmdName );
cmd->function = function;
cmd->argCompletion = argCompletion;
cmd->flags = flags;
cmd->description = Mem_CopyString( description );
cmd->next = commands;
commands = cmd;
}
/*
============
idCmdSystemLocal::RemoveCommand
============
*/
void idCmdSystemLocal::RemoveCommand( const char *cmdName ) {
commandDef_t *cmd, **last;
for ( last = &commands, cmd = *last; cmd; cmd = *last ) {
if ( idStr::Cmp( cmdName, cmd->name ) == 0 ) {
*last = cmd->next;
Mem_Free( cmd->name );
Mem_Free( cmd->description );
delete cmd;
return;
}
last = &cmd->next;
}
}
/*
============
idCmdSystemLocal::RemoveFlaggedCommands
============
*/
void idCmdSystemLocal::RemoveFlaggedCommands( int flags ) {
commandDef_t *cmd, **last;
for ( last = &commands, cmd = *last; cmd; cmd = *last ) {
if ( cmd->flags & flags ) {
*last = cmd->next;
Mem_Free( cmd->name );
Mem_Free( cmd->description );
delete cmd;
continue;
}
last = &cmd->next;
}
}
/*
============
idCmdSystemLocal::CommandCompletion
============
*/
void idCmdSystemLocal::CommandCompletion( void(*callback)( const char *s ) ) {
commandDef_t *cmd;
for ( cmd = commands; cmd; cmd = cmd->next ) {
callback( cmd->name );
}
}
/*
============
idCmdSystemLocal::ArgCompletion
============
*/
void idCmdSystemLocal::ArgCompletion( const char *cmdString, void(*callback)( const char *s ) ) {
commandDef_t *cmd;
idCmdArgs args;
args.TokenizeString( cmdString, false );
for ( cmd = commands; cmd; cmd = cmd->next ) {
if ( !cmd->argCompletion ) {
continue;
}
if ( idStr::Icmp( args.Argv( 0 ), cmd->name ) == 0 ) {
cmd->argCompletion( args, callback );
break;
}
}
}
/*
============
idCmdSystemLocal::ExecuteTokenizedString
============
*/
void idCmdSystemLocal::ExecuteTokenizedString( const idCmdArgs &args ) {
commandDef_t *cmd, **prev;
// execute the command line
if ( !args.Argc() ) {
return; // no tokens
}
// check registered command functions
for ( prev = &commands; *prev; prev = &cmd->next ) {
cmd = *prev;
if ( idStr::Icmp( args.Argv( 0 ), cmd->name ) == 0 ) {
// rearrange the links so that the command will be
// near the head of the list next time it is used
*prev = cmd->next;
cmd->next = commands;
commands = cmd;
if ( ( cmd->flags & (CMD_FL_CHEAT|CMD_FL_TOOL) ) && session && session->IsMultiplayer() && !cvarSystem->GetCVarBool( "net_allowCheats" ) ) {
common->Printf( "Command '%s' not valid in multiplayer mode.\n", cmd->name );
return;
}
// perform the action
if ( !cmd->function ) {
break;
} else {
cmd->function( args );
}
return;
}
}
// check cvars
if ( cvarSystem->Command( args ) ) {
return;
}
common->Printf( "Unknown command '%s'\n", args.Argv( 0 ) );
}
/*
============
idCmdSystemLocal::ExecuteCommandText
Tokenizes, then executes.
============
*/
void idCmdSystemLocal::ExecuteCommandText( const char *text ) {
ExecuteTokenizedString( idCmdArgs( text, false ) );
}
/*
============
idCmdSystemLocal::InsertCommandText
Adds command text immediately after the current command
Adds a \n to the text
============
*/
void idCmdSystemLocal::InsertCommandText( const char *text ) {
int len;
int i;
len = strlen( text ) + 1;
if ( len + textLength > (int)sizeof( textBuf ) ) {
common->Printf( "idCmdSystemLocal::InsertText: buffer overflow\n" );
return;
}
// move the existing command text
for ( i = textLength - 1; i >= 0; i-- ) {
textBuf[ i + len ] = textBuf[ i ];
}
// copy the new text in
memcpy( textBuf, text, len - 1 );
// add a \n
textBuf[ len - 1 ] = '\n';
textLength += len;
}
/*
============
idCmdSystemLocal::AppendCommandText
Adds command text at the end of the buffer, does NOT add a final \n
============
*/
void idCmdSystemLocal::AppendCommandText( const char *text ) {
int l;
l = strlen( text );
if ( textLength + l >= (int)sizeof( textBuf ) ) {
common->Printf( "idCmdSystemLocal::AppendText: buffer overflow\n" );
return;
}
memcpy( textBuf + textLength, text, l );
textLength += l;
}
/*
============
idCmdSystemLocal::BufferCommandText
============
*/
void idCmdSystemLocal::BufferCommandText( cmdExecution_t exec, const char *text ) {
switch( exec ) {
case CMD_EXEC_NOW: {
ExecuteCommandText( text );
break;
}
case CMD_EXEC_INSERT: {
InsertCommandText( text );
break;
}
case CMD_EXEC_APPEND: {
AppendCommandText( text );
break;
}
default: {
common->FatalError( "idCmdSystemLocal::BufferCommandText: bad exec type" );
}
}
}
/*
============
idCmdSystemLocal::BufferCommandArgs
============
*/
void idCmdSystemLocal::BufferCommandArgs( cmdExecution_t exec, const idCmdArgs &args ) {
switch ( exec ) {
case CMD_EXEC_NOW: {
ExecuteTokenizedString( args );
break;
}
case CMD_EXEC_APPEND: {
AppendCommandText( "_execTokenized\n" );
tokenizedCmds.Append( args );
break;
}
default: {
common->FatalError( "idCmdSystemLocal::BufferCommandArgs: bad exec type" );
}
}
}
/*
============
idCmdSystemLocal::ExecuteCommandBuffer
============
*/
void idCmdSystemLocal::ExecuteCommandBuffer( void ) {
int i;
char * text;
int quotes;
idCmdArgs args;
while( textLength ) {
if ( wait ) {
// skip out while text still remains in buffer, leaving it for next frame
wait--;
break;
}
// find a \n or ; line break
text = (char *)textBuf;
quotes = 0;
for ( i = 0; i < textLength; i++ ) {
if ( text[i] == '"' ) {
quotes++;
}
if ( !( quotes & 1 ) && text[i] == ';' ) {
break; // don't break if inside a quoted string
}
if ( text[i] == '\n' || text[i] == '\r' ) {
break;
}
}
text[i] = 0;
if ( !idStr::Cmp( text, "_execTokenized" ) ) {
args = tokenizedCmds[ 0 ];
tokenizedCmds.RemoveIndex( 0 );
} else {
args.TokenizeString( text, false );
}
// delete the text from the command buffer and move remaining commands down
// this is necessary because commands (exec) can insert data at the
// beginning of the text buffer
if ( i == textLength ) {
textLength = 0;
} else {
i++;
textLength -= i;
memmove( text, text+i, textLength );
}
// execute the command line that we have already tokenized
ExecuteTokenizedString( args );
}
}
/*
============
idCmdSystemLocal::ArgCompletion_FolderExtension
============
*/
void idCmdSystemLocal::ArgCompletion_FolderExtension( const idCmdArgs &args, void(*callback)( const char *s ), const char *folder, bool stripFolder, ... ) {
int i;
idStr string;
const char *extension;
va_list argPtr;
string = args.Argv( 0 );
string += " ";
string += args.Argv( 1 );
if ( string.Icmp( completionString ) != 0 ) {
idStr parm, path;
idFileList *names;
completionString = string;
completionParms.Clear();
parm = args.Argv( 1 );
parm.ExtractFilePath( path );
if ( stripFolder || path.Length() == 0 ) {
path = folder + path;
}
path.StripTrailing( '/' );
// list folders
names = fileSystem->ListFiles( path, "/", true, true );
for ( i = 0; i < names->GetNumFiles(); i++ ) {
idStr name = names->GetFile( i );
if ( stripFolder ) {
name.Strip( folder );
} else {
name.Strip( "/" );
}
name = args.Argv( 0 ) + ( " " + name ) + "/";
completionParms.Append( name );
}
fileSystem->FreeFileList( names );
// list files
va_start( argPtr, stripFolder );
for ( extension = va_arg( argPtr, const char * ); extension; extension = va_arg( argPtr, const char * ) ) {
names = fileSystem->ListFiles( path, extension, true, true );
for ( i = 0; i < names->GetNumFiles(); i++ ) {
idStr name = names->GetFile( i );
if ( stripFolder ) {
name.Strip( folder );
} else {
name.Strip( "/" );
}
name = args.Argv( 0 ) + ( " " + name );
completionParms.Append( name );
}
fileSystem->FreeFileList( names );
}
va_end( argPtr );
}
for ( i = 0; i < completionParms.Num(); i++ ) {
callback( completionParms[i] );
}
}
/*
============
idCmdSystemLocal::ArgCompletion_DeclName
============
*/
void idCmdSystemLocal::ArgCompletion_DeclName( const idCmdArgs &args, void(*callback)( const char *s ), int type ) {
int i, num;
if ( declManager == NULL ) {
return;
}
num = declManager->GetNumDecls( (declType_t)type );
for ( i = 0; i < num; i++ ) {
callback( idStr( args.Argv( 0 ) ) + " " + declManager->DeclByIndex( (declType_t)type, i , false )->GetName() );
}
}
/*
============
idCmdSystemLocal::SetupReloadEngine
============
*/
void idCmdSystemLocal::SetupReloadEngine( const idCmdArgs &args ) {
BufferCommandText( CMD_EXEC_APPEND, "reloadEngine\n" );
postReload = args;
}
/*
============
idCmdSystemLocal::PostReloadEngine
============
*/
bool idCmdSystemLocal::PostReloadEngine( void ) {
if ( !postReload.Argc() ) {
return false;
}
BufferCommandArgs( CMD_EXEC_APPEND, postReload );
postReload.Clear();
return true;
}

188
neo/framework/CmdSystem.h Normal file
View File

@@ -0,0 +1,188 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __CMDSYSTEM_H__
#define __CMDSYSTEM_H__
/*
===============================================================================
Console command execution and command text buffering.
Any number of commands can be added in a frame from several different
sources. Most commands come from either key bindings or console line input,
but entire text files can be execed.
Command execution takes a null terminated string, breaks it into tokens,
then searches for a command or variable that matches the first token.
===============================================================================
*/
// command flags
typedef enum {
CMD_FL_ALL = -1,
CMD_FL_CHEAT = BIT(0), // command is considered a cheat
CMD_FL_SYSTEM = BIT(1), // system command
CMD_FL_RENDERER = BIT(2), // renderer command
CMD_FL_SOUND = BIT(3), // sound command
CMD_FL_GAME = BIT(4), // game command
CMD_FL_TOOL = BIT(5) // tool command
} cmdFlags_t;
// parameters for command buffer stuffing
typedef enum {
CMD_EXEC_NOW, // don't return until completed
CMD_EXEC_INSERT, // insert at current position, but don't run yet
CMD_EXEC_APPEND // add to end of the command buffer (normal case)
} cmdExecution_t;
// command function
typedef void (*cmdFunction_t)( const idCmdArgs &args );
// argument completion function
typedef void (*argCompletion_t)( const idCmdArgs &args, void(*callback)( const char *s ) );
class idCmdSystem {
public:
virtual ~idCmdSystem( void ) {}
virtual void Init( void ) = 0;
virtual void Shutdown( void ) = 0;
// Registers a command and the function to call for it.
virtual void AddCommand( const char *cmdName, cmdFunction_t function, int flags, const char *description, argCompletion_t argCompletion = NULL ) = 0;
// Removes a command.
virtual void RemoveCommand( const char *cmdName ) = 0;
// Remove all commands with one of the flags set.
virtual void RemoveFlaggedCommands( int flags ) = 0;
// Command and argument completion using callback for each valid string.
virtual void CommandCompletion( void(*callback)( const char *s ) ) = 0;
virtual void ArgCompletion( const char *cmdString, void(*callback)( const char *s ) ) = 0;
// Adds command text to the command buffer, does not add a final \n
virtual void BufferCommandText( cmdExecution_t exec, const char *text ) = 0;
// Pulls off \n \r or ; terminated lines of text from the command buffer and
// executes the commands. Stops when the buffer is empty.
// Normally called once per frame, but may be explicitly invoked.
virtual void ExecuteCommandBuffer( void ) = 0;
// Base for path/file auto-completion.
virtual void ArgCompletion_FolderExtension( const idCmdArgs &args, void(*callback)( const char *s ), const char *folder, bool stripFolder, ... ) = 0;
// Base for decl name auto-completion.
virtual void ArgCompletion_DeclName( const idCmdArgs &args, void(*callback)( const char *s ), int type ) = 0;
// Adds to the command buffer in tokenized form ( CMD_EXEC_NOW or CMD_EXEC_APPEND only )
virtual void BufferCommandArgs( cmdExecution_t exec, const idCmdArgs &args ) = 0;
// Setup a reloadEngine to happen on next command run, and give a command to execute after reload
virtual void SetupReloadEngine( const idCmdArgs &args ) = 0;
virtual bool PostReloadEngine( void ) = 0;
// Default argument completion functions.
static void ArgCompletion_Boolean( const idCmdArgs &args, void(*callback)( const char *s ) );
template<int min,int max>
static void ArgCompletion_Integer( const idCmdArgs &args, void(*callback)( const char *s ) );
template<const char **strings>
static void ArgCompletion_String( const idCmdArgs &args, void(*callback)( const char *s ) );
template<int type>
static void ArgCompletion_Decl( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_FileName( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_MapName( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_ModelName( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_SoundName( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_ImageName( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_VideoName( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_ConfigName( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_SaveGame( const idCmdArgs &args, void(*callback)( const char *s ) );
static void ArgCompletion_DemoName( const idCmdArgs &args, void(*callback)( const char *s ) );
};
extern idCmdSystem * cmdSystem;
ID_INLINE void idCmdSystem::ArgCompletion_Boolean( const idCmdArgs &args, void(*callback)( const char *s ) ) {
callback( va( "%s 0", args.Argv( 0 ) ) );
callback( va( "%s 1", args.Argv( 0 ) ) );
}
template<int min,int max> ID_STATIC_TEMPLATE ID_INLINE void idCmdSystem::ArgCompletion_Integer( const idCmdArgs &args, void(*callback)( const char *s ) ) {
for ( int i = min; i <= max; i++ ) {
callback( va( "%s %d", args.Argv( 0 ), i ) );
}
}
template<const char **strings> ID_STATIC_TEMPLATE ID_INLINE void idCmdSystem::ArgCompletion_String( const idCmdArgs &args, void(*callback)( const char *s ) ) {
for ( int i = 0; strings[i]; i++ ) {
callback( va( "%s %s", args.Argv( 0 ), strings[i] ) );
}
}
template<int type> ID_STATIC_TEMPLATE ID_INLINE void idCmdSystem::ArgCompletion_Decl( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_DeclName( args, callback, type );
}
ID_INLINE void idCmdSystem::ArgCompletion_FileName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "/", true, "", NULL );
}
ID_INLINE void idCmdSystem::ArgCompletion_MapName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "maps/", true, ".map", NULL );
}
ID_INLINE void idCmdSystem::ArgCompletion_ModelName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "models/", false, ".lwo", ".ase", ".md5mesh", ".ma", NULL );
}
ID_INLINE void idCmdSystem::ArgCompletion_SoundName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "sound/", false, ".wav", ".ogg", NULL );
}
ID_INLINE void idCmdSystem::ArgCompletion_ImageName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "/", false, ".tga", ".dds", ".jpg", ".pcx", NULL );
}
ID_INLINE void idCmdSystem::ArgCompletion_VideoName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "video/", false, ".roq", NULL );
}
ID_INLINE void idCmdSystem::ArgCompletion_ConfigName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "/", true, ".cfg", NULL );
}
ID_INLINE void idCmdSystem::ArgCompletion_SaveGame( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "SaveGames/", true, ".save", NULL );
}
ID_INLINE void idCmdSystem::ArgCompletion_DemoName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
cmdSystem->ArgCompletion_FolderExtension( args, callback, "demos/", true, ".demo", NULL );
}
#endif /* !__CMDSYSTEM_H__ */

3101
neo/framework/Common.cpp Normal file

File diff suppressed because it is too large Load Diff

215
neo/framework/Common.h Normal file
View File

@@ -0,0 +1,215 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __COMMON_H__
#define __COMMON_H__
/*
==============================================================
Common
==============================================================
*/
typedef enum {
EDITOR_NONE = 0,
EDITOR_RADIANT = BIT(1),
EDITOR_GUI = BIT(2),
EDITOR_DEBUGGER = BIT(3),
EDITOR_SCRIPT = BIT(4),
EDITOR_LIGHT = BIT(5),
EDITOR_SOUND = BIT(6),
EDITOR_DECL = BIT(7),
EDITOR_AF = BIT(8),
EDITOR_PARTICLE = BIT(9),
EDITOR_PDA = BIT(10),
EDITOR_AAS = BIT(11),
EDITOR_MATERIAL = BIT(12)
} toolFlag_t;
#define STRTABLE_ID "#str_"
#define STRTABLE_ID_LENGTH 5
extern idCVar com_version;
extern idCVar com_skipRenderer;
extern idCVar com_asyncInput;
extern idCVar com_asyncSound;
extern idCVar com_machineSpec;
extern idCVar com_purgeAll;
extern idCVar com_developer;
extern idCVar com_allowConsole;
extern idCVar com_speeds;
extern idCVar com_showFPS;
extern idCVar com_showMemoryUsage;
extern idCVar com_showAsyncStats;
extern idCVar com_showSoundDecoders;
extern idCVar com_makingBuild;
extern idCVar com_updateLoadSize;
extern idCVar com_videoRam;
extern int time_gameFrame; // game logic time
extern int time_gameDraw; // game present time
extern int time_frontend; // renderer frontend time
extern int time_backend; // renderer backend time
extern int com_frameTime; // time for the current frame in milliseconds
extern volatile int com_ticNumber; // 60 hz tics, incremented by async function
extern int com_editors; // current active editor(s)
extern bool com_editorActive; // true if an editor has focus
#ifdef _WIN32
const char DMAP_MSGID[] = "DMAPOutput";
const char DMAP_DONE[] = "DMAPDone";
extern HWND com_hwndMsg;
extern bool com_outputMsg;
#endif
struct MemInfo_t {
idStr filebase;
int total;
int assetTotals;
// memory manager totals
int memoryManagerTotal;
// subsystem totals
int gameSubsystemTotal;
int renderSubsystemTotal;
// asset totals
int imageAssetsTotal;
int modelAssetsTotal;
int soundAssetsTotal;
};
class idCommon {
public:
virtual ~idCommon( void ) {}
// Initialize everything.
// if the OS allows, pass argc/argv directly (without executable name)
// otherwise pass the command line in a single string (without executable name)
virtual void Init( int argc, const char **argv, const char *cmdline ) = 0;
// Shuts down everything.
virtual void Shutdown( void ) = 0;
// Shuts down everything.
virtual void Quit( void ) = 0;
// Returns true if common initialization is complete.
virtual bool IsInitialized( void ) const = 0;
// Called repeatedly as the foreground thread for rendering and game logic.
virtual void Frame( void ) = 0;
// Called repeatedly by blocking function calls with GUI interactivity.
virtual void GUIFrame( bool execCmd, bool network ) = 0;
// Called 60 times a second from a background thread for sound mixing,
// and input generation. Not called until idCommon::Init() has completed.
virtual void Async( void ) = 0;
// Checks for and removes command line "+set var arg" constructs.
// If match is NULL, all set commands will be executed, otherwise
// only a set with the exact name. Only used during startup.
// set once to clear the cvar from +set for early init code
virtual void StartupVariable( const char *match, bool once ) = 0;
// Initializes a tool with the given dictionary.
virtual void InitTool( const toolFlag_t tool, const idDict *dict ) = 0;
// Activates or deactivates a tool.
virtual void ActivateTool( bool active ) = 0;
// Writes the user's configuration to a file
virtual void WriteConfigToFile( const char *filename ) = 0;
// Writes cvars with the given flags to a file.
virtual void WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd ) = 0;
// Begins redirection of console output to the given buffer.
virtual void BeginRedirect( char *buffer, int buffersize, void (*flush)( const char * ) ) = 0;
// Stops redirection of console output.
virtual void EndRedirect( void ) = 0;
// Update the screen with every message printed.
virtual void SetRefreshOnPrint( bool set ) = 0;
// Prints message to the console, which may cause a screen update if com_refreshOnPrint is set.
virtual void Printf( const char *fmt, ... )id_attribute((format(printf,2,3))) = 0;
// Same as Printf, with a more usable API - Printf pipes to this.
virtual void VPrintf( const char *fmt, va_list arg ) = 0;
// Prints message that only shows up if the "developer" cvar is set,
// and NEVER forces a screen update, which could cause reentrancy problems.
virtual void DPrintf( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
// Prints WARNING %s message and adds the warning message to a queue for printing later on.
virtual void Warning( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
// Prints WARNING %s message in yellow that only shows up if the "developer" cvar is set.
virtual void DWarning( const char *fmt, ...) id_attribute((format(printf,2,3))) = 0;
// Prints all queued warnings.
virtual void PrintWarnings( void ) = 0;
// Removes all queued warnings.
virtual void ClearWarnings( const char *reason ) = 0;
// Issues a C++ throw. Normal errors just abort to the game loop,
// which is appropriate for media or dynamic logic errors.
virtual void Error( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
// Fatal errors quit all the way to a system dialog box, which is appropriate for
// static internal errors or cases where the system may be corrupted.
virtual void FatalError( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
// Returns a pointer to the dictionary with language specific strings.
virtual const idLangDict * GetLanguageDict( void ) = 0;
// Returns key bound to the command
virtual const char * KeysFromBinding( const char *bind ) = 0;
// Returns the binding bound to the key
virtual const char * BindingFromKey( const char *key ) = 0;
// Directly sample a button.
virtual int ButtonState( int key ) = 0;
// Directly sample a keystate.
virtual int KeyState( int key ) = 0;
};
extern idCommon * common;
#endif /* !__COMMON_H__ */

2576
neo/framework/Compressor.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __COMPRESSOR_H__
#define __COMPRESSOR_H__
/*
===============================================================================
idCompressor is a layer ontop of idFile which provides lossless data
compression. The compressor can be used as a regular file and multiple
compressors can be stacked ontop of each other.
===============================================================================
*/
class idCompressor : public idFile {
public:
// compressor allocation
static idCompressor * AllocNoCompression( void );
static idCompressor * AllocBitStream( void );
static idCompressor * AllocRunLength( void );
static idCompressor * AllocRunLength_ZeroBased( void );
static idCompressor * AllocHuffman( void );
static idCompressor * AllocArithmetic( void );
static idCompressor * AllocLZSS( void );
static idCompressor * AllocLZSS_WordAligned( void );
static idCompressor * AllocLZW( void );
// initialization
virtual void Init( idFile *f, bool compress, int wordLength ) = 0;
virtual void FinishCompress( void ) = 0;
virtual float GetCompressionRatio( void ) const = 0;
// common idFile interface
virtual const char * GetName( void ) = 0;
virtual const char * GetFullPath( void ) = 0;
virtual int Read( void *outData, int outLength ) = 0;
virtual int Write( const void *inData, int inLength ) = 0;
virtual int Length( void ) = 0;
virtual ID_TIME_T Timestamp( void ) = 0;
virtual int Tell( void ) = 0;
virtual void ForceFlush( void ) = 0;
virtual void Flush( void ) = 0;
virtual int Seek( long offset, fsOrigin_t origin ) = 0;
};
#endif /* !__COMPRESSOR_H__ */

1186
neo/framework/Console.cpp Normal file

File diff suppressed because it is too large Load Diff

72
neo/framework/Console.h Normal file
View File

@@ -0,0 +1,72 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __CONSOLE_H__
#define __CONSOLE_H__
/*
===============================================================================
The console is strictly for development and advanced users. It should
never be used to convey actual game information to the user, which should
always be done through a GUI.
The force options are for the editor console display window, which
doesn't respond to pull up / pull down
===============================================================================
*/
class idConsole {
public:
virtual ~idConsole( void ) {}
virtual void Init( void ) = 0;
virtual void Shutdown( void ) = 0;
// can't be combined with Init, because Init happens before renderer is started
virtual void LoadGraphics() = 0;
virtual bool ProcessEvent( const struct sysEvent_s *event, bool forceAccept ) = 0;
// the system code can release the mouse pointer when the console is active
virtual bool Active( void ) = 0;
// clear the timers on any recent prints that are displayed in the notify lines
virtual void ClearNotifyLines( void ) = 0;
// some console commands, like timeDemo, will force the console closed before they start
virtual void Close( void ) = 0;
virtual void Draw( bool forceFullScreen ) = 0;
virtual void Print( const char *text ) = 0;
};
extern idConsole * console; // statically initialized to an idConsoleLocal
#endif /* !__CONSOLE_H__ */

1745
neo/framework/DeclAF.cpp Normal file

File diff suppressed because it is too large Load Diff

216
neo/framework/DeclAF.h Normal file
View File

@@ -0,0 +1,216 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DECLAF_H__
#define __DECLAF_H__
/*
===============================================================================
Articulated Figure
===============================================================================
*/
class idDeclAF;
typedef enum {
DECLAF_CONSTRAINT_INVALID,
DECLAF_CONSTRAINT_FIXED,
DECLAF_CONSTRAINT_BALLANDSOCKETJOINT,
DECLAF_CONSTRAINT_UNIVERSALJOINT,
DECLAF_CONSTRAINT_HINGE,
DECLAF_CONSTRAINT_SLIDER,
DECLAF_CONSTRAINT_SPRING
} declAFConstraintType_t;
typedef enum {
DECLAF_JOINTMOD_AXIS,
DECLAF_JOINTMOD_ORIGIN,
DECLAF_JOINTMOD_BOTH
} declAFJointMod_t;
typedef bool (*getJointTransform_t)( void *model, const idJointMat *frame, const char *jointName, idVec3 &origin, idMat3 &axis );
class idAFVector {
public:
enum {
VEC_COORDS = 0,
VEC_JOINT,
VEC_BONECENTER,
VEC_BONEDIR
} type;
idStr joint1;
idStr joint2;
public:
idAFVector( void );
bool Parse( idLexer &src );
bool Finish( const char *fileName, const getJointTransform_t GetJointTransform, const idJointMat *frame, void *model ) const;
bool Write( idFile *f ) const;
const char * ToString( idStr &str, const int precision = 8 );
const idVec3 & ToVec3( void ) const { return vec; }
idVec3 & ToVec3( void ) { return vec; }
private:
mutable idVec3 vec;
bool negate;
};
class idDeclAF_Body {
public:
idStr name;
idStr jointName;
declAFJointMod_t jointMod;
int modelType;
idAFVector v1, v2;
int numSides;
float width;
float density;
idAFVector origin;
idAngles angles;
int contents;
int clipMask;
bool selfCollision;
idMat3 inertiaScale;
float linearFriction;
float angularFriction;
float contactFriction;
idStr containedJoints;
idAFVector frictionDirection;
idAFVector contactMotorDirection;
public:
void SetDefault( const idDeclAF *file );
};
class idDeclAF_Constraint {
public:
idStr name;
idStr body1;
idStr body2;
declAFConstraintType_t type;
float friction;
float stretch;
float compress;
float damping;
float restLength;
float minLength;
float maxLength;
idAFVector anchor;
idAFVector anchor2;
idAFVector shaft[2];
idAFVector axis;
enum {
LIMIT_NONE = -1,
LIMIT_CONE,
LIMIT_PYRAMID
} limit;
idAFVector limitAxis;
float limitAngles[3];
public:
void SetDefault( const idDeclAF *file );
};
class idDeclAF : public idDecl {
friend class idAFFileManager;
public:
idDeclAF( void );
virtual ~idDeclAF( void );
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
virtual void Finish( const getJointTransform_t GetJointTransform, const idJointMat *frame, void *model ) const;
bool Save( void );
void NewBody( const char *name );
void RenameBody( const char *oldName, const char *newName );
void DeleteBody( const char *name );
void NewConstraint( const char *name );
void RenameConstraint( const char *oldName, const char *newName );
void DeleteConstraint( const char *name );
static int ContentsFromString( const char *str );
static const char * ContentsToString( const int contents, idStr &str );
static declAFJointMod_t JointModFromString( const char *str );
static const char * JointModToString( declAFJointMod_t jointMod );
public:
bool modified;
idStr model;
idStr skin;
float defaultLinearFriction;
float defaultAngularFriction;
float defaultContactFriction;
float defaultConstraintFriction;
float totalMass;
idVec2 suspendVelocity;
idVec2 suspendAcceleration;
float noMoveTime;
float noMoveTranslation;
float noMoveRotation;
float minMoveTime;
float maxMoveTime;
int contents;
int clipMask;
bool selfCollision;
idList<idDeclAF_Body *> bodies;
idList<idDeclAF_Constraint *> constraints;
private:
bool ParseContents( idLexer &src, int &c ) const;
bool ParseBody( idLexer &src );
bool ParseFixed( idLexer &src );
bool ParseBallAndSocketJoint( idLexer &src );
bool ParseUniversalJoint( idLexer &src );
bool ParseHinge( idLexer &src );
bool ParseSlider( idLexer &src );
bool ParseSpring( idLexer &src );
bool ParseSettings( idLexer &src );
bool WriteBody( idFile *f, const idDeclAF_Body &body ) const;
bool WriteFixed( idFile *f, const idDeclAF_Constraint &c ) const;
bool WriteBallAndSocketJoint( idFile *f, const idDeclAF_Constraint &c ) const;
bool WriteUniversalJoint( idFile *f, const idDeclAF_Constraint &c ) const;
bool WriteHinge( idFile *f, const idDeclAF_Constraint &c ) const;
bool WriteSlider( idFile *f, const idDeclAF_Constraint &c ) const;
bool WriteSpring( idFile *f, const idDeclAF_Constraint &c ) const;
bool WriteConstraint( idFile *f, const idDeclAF_Constraint &c ) const;
bool WriteSettings( idFile *f ) const;
bool RebuildTextSource( void );
};
#endif /* !__DECLAF_H__ */

View File

@@ -0,0 +1,153 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
/*
=================
idDeclEntityDef::Size
=================
*/
size_t idDeclEntityDef::Size( void ) const {
return sizeof( idDeclEntityDef ) + dict.Allocated();
}
/*
================
idDeclEntityDef::FreeData
================
*/
void idDeclEntityDef::FreeData( void ) {
dict.Clear();
}
/*
================
idDeclEntityDef::Parse
================
*/
bool idDeclEntityDef::Parse( const char *text, const int textLength ) {
idLexer src;
idToken token, token2;
src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
src.SetFlags( DECL_LEXER_FLAGS );
src.SkipUntilString( "{" );
while (1) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( !token.Icmp( "}" ) ) {
break;
}
if ( token.type != TT_STRING ) {
src.Warning( "Expected quoted string, but found '%s'", token.c_str() );
MakeDefault();
return false;
}
if ( !src.ReadToken( &token2 ) ) {
src.Warning( "Unexpected end of file" );
MakeDefault();
return false;
}
if ( dict.FindKey( token ) ) {
src.Warning( "'%s' already defined", token.c_str() );
}
dict.Set( token, token2 );
}
// we always automatically set a "classname" key to our name
dict.Set( "classname", GetName() );
// "inherit" keys will cause all values from another entityDef to be copied into this one
// if they don't conflict. We can't have circular recursions, because each entityDef will
// never be parsed mroe than once
// find all of the dicts first, because copying inherited values will modify the dict
idList<const idDeclEntityDef *> defList;
while ( 1 ) {
const idKeyValue *kv;
kv = dict.MatchPrefix( "inherit", NULL );
if ( !kv ) {
break;
}
const idDeclEntityDef *copy = static_cast<const idDeclEntityDef *>( declManager->FindType( DECL_ENTITYDEF, kv->GetValue(), false ) );
if ( !copy ) {
src.Warning( "Unknown entityDef '%s' inherited by '%s'", kv->GetValue().c_str(), GetName() );
} else {
defList.Append( copy );
}
// delete this key/value pair
dict.Delete( kv->GetKey() );
}
// now copy over the inherited key / value pairs
for ( int i = 0 ; i < defList.Num() ; i++ ) {
dict.SetDefaults( &defList[ i ]->dict );
}
// precache all referenced media
// do this as long as we arent in modview
if ( !( com_editors & (EDITOR_RADIANT|EDITOR_AAS) ) ) {
game->CacheDictionaryMedia( &dict );
}
return true;
}
/*
================
idDeclEntityDef::DefaultDefinition
================
*/
const char *idDeclEntityDef::DefaultDefinition( void ) const {
return
"{\n"
"\t" "\"DEFAULTED\"\t\"1\"\n"
"}";
}
/*
================
idDeclEntityDef::Print
Dumps all key/value pairs, including inherited ones
================
*/
void idDeclEntityDef::Print( void ) {
dict.Print();
}

View File

@@ -0,0 +1,51 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DECLENTITYDEF_H__
#define __DECLENTITYDEF_H__
/*
===============================================================================
idDeclEntityDef
===============================================================================
*/
class idDeclEntityDef : public idDecl {
public:
idDict dict;
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition() const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
virtual void Print( void );
};
#endif /* !__DECLENTITYDEF_H__ */

473
neo/framework/DeclFX.cpp Normal file
View File

@@ -0,0 +1,473 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
/*
=================
idDeclFX::Size
=================
*/
size_t idDeclFX::Size( void ) const {
return sizeof( idDeclFX );
}
/*
===============
idDeclFX::Print
===============
*/
void idDeclFX::Print( void ) const {
const idDeclFX *list = this;
common->Printf("%d events\n", list->events.Num() );
for( int i = 0; i < list->events.Num(); i++ ) {
switch( list->events[i].type ) {
case FX_LIGHT:
common->Printf("FX_LIGHT %s\n", list->events[i].data.c_str());
break;
case FX_PARTICLE:
common->Printf("FX_PARTICLE %s\n", list->events[i].data.c_str());
break;
case FX_MODEL:
common->Printf("FX_MODEL %s\n", list->events[i].data.c_str());
break;
case FX_SOUND:
common->Printf("FX_SOUND %s\n", list->events[i].data.c_str());
break;
case FX_DECAL:
common->Printf("FX_DECAL %s\n", list->events[i].data.c_str());
break;
case FX_SHAKE:
common->Printf("FX_SHAKE %s\n", list->events[i].data.c_str());
break;
case FX_ATTACHLIGHT:
common->Printf("FX_ATTACHLIGHT %s\n", list->events[i].data.c_str());
break;
case FX_ATTACHENTITY:
common->Printf("FX_ATTACHENTITY %s\n", list->events[i].data.c_str());
break;
case FX_LAUNCH:
common->Printf("FX_LAUNCH %s\n", list->events[i].data.c_str());
break;
case FX_SHOCKWAVE:
common->Printf("FX_SHOCKWAVE %s\n", list->events[i].data.c_str());
break;
}
}
}
/*
===============
idDeclFX::List
===============
*/
void idDeclFX::List( void ) const {
common->Printf("%s, %d stages\n", GetName(), events.Num() );
}
/*
================
idDeclFX::ParseSingleFXAction
================
*/
void idDeclFX::ParseSingleFXAction( idLexer &src, idFXSingleAction& FXAction ) {
idToken token;
FXAction.type = -1;
FXAction.sibling = -1;
FXAction.data = "<none>";
FXAction.name = "<none>";
FXAction.fire = "<none>";
FXAction.delay = 0.0f;
FXAction.duration = 0.0f;
FXAction.restart = 0.0f;
FXAction.size = 0.0f;
FXAction.fadeInTime = 0.0f;
FXAction.fadeOutTime = 0.0f;
FXAction.shakeTime = 0.0f;
FXAction.shakeAmplitude = 0.0f;
FXAction.shakeDistance = 0.0f;
FXAction.shakeFalloff = false;
FXAction.shakeImpulse = 0.0f;
FXAction.shakeIgnoreMaster = false;
FXAction.lightRadius = 0.0f;
FXAction.rotate = 0.0f;
FXAction.random1 = 0.0f;
FXAction.random2 = 0.0f;
FXAction.lightColor = vec3_origin;
FXAction.offset = vec3_origin;
FXAction.axis = mat3_identity;
FXAction.bindParticles = false;
FXAction.explicitAxis = false;
FXAction.noshadows = false;
FXAction.particleTrackVelocity = false;
FXAction.trackOrigin = false;
FXAction.soundStarted = false;
while (1) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( !token.Icmp( "}" ) ) {
break;
}
if ( !token.Icmp( "shake" ) ) {
FXAction.type = FX_SHAKE;
FXAction.shakeTime = src.ParseFloat();
src.ExpectTokenString(",");
FXAction.shakeAmplitude = src.ParseFloat();
src.ExpectTokenString(",");
FXAction.shakeDistance = src.ParseFloat();
src.ExpectTokenString(",");
FXAction.shakeFalloff = src.ParseBool();
src.ExpectTokenString(",");
FXAction.shakeImpulse = src.ParseFloat();
continue;
}
if ( !token.Icmp( "noshadows" ) ) {
FXAction.noshadows = true;
continue;
}
if ( !token.Icmp( "name" ) ) {
src.ReadToken( &token );
FXAction.name = token;
continue;
}
if ( !token.Icmp( "fire") ) {
src.ReadToken( &token );
FXAction.fire = token;
continue;
}
if ( !token.Icmp( "random" ) ) {
FXAction.random1 = src.ParseFloat();
src.ExpectTokenString( "," );
FXAction.random2 = src.ParseFloat();
FXAction.delay = 0.0f; // check random
continue;
}
if ( !token.Icmp( "delay" ) ) {
FXAction.delay = src.ParseFloat();
continue;
}
if ( !token.Icmp( "rotate" ) ) {
FXAction.rotate = src.ParseFloat();
continue;
}
if ( !token.Icmp( "duration" ) ) {
FXAction.duration = src.ParseFloat();
continue;
}
if ( !token.Icmp( "trackorigin" ) ) {
FXAction.trackOrigin = src.ParseBool();
continue;
}
if (!token.Icmp("restart")) {
FXAction.restart = src.ParseFloat();
continue;
}
if ( !token.Icmp( "fadeIn" ) ) {
FXAction.fadeInTime = src.ParseFloat();
continue;
}
if ( !token.Icmp( "fadeOut" ) ) {
FXAction.fadeOutTime = src.ParseFloat();
continue;
}
if ( !token.Icmp( "size" ) ) {
FXAction.size = src.ParseFloat();
continue;
}
if ( !token.Icmp( "offset" ) ) {
FXAction.offset.x = src.ParseFloat();
src.ExpectTokenString( "," );
FXAction.offset.y = src.ParseFloat();
src.ExpectTokenString( "," );
FXAction.offset.z = src.ParseFloat();
continue;
}
if ( !token.Icmp( "axis" ) ) {
idVec3 v;
v.x = src.ParseFloat();
src.ExpectTokenString( "," );
v.y = src.ParseFloat();
src.ExpectTokenString( "," );
v.z = src.ParseFloat();
v.Normalize();
FXAction.axis = v.ToMat3();
FXAction.explicitAxis = true;
continue;
}
if ( !token.Icmp( "angle" ) ) {
idAngles a;
a[0] = src.ParseFloat();
src.ExpectTokenString( "," );
a[1] = src.ParseFloat();
src.ExpectTokenString( "," );
a[2] = src.ParseFloat();
FXAction.axis = a.ToMat3();
FXAction.explicitAxis = true;
continue;
}
if ( !token.Icmp( "uselight" ) ) {
src.ReadToken( &token );
FXAction.data = token;
for( int i = 0; i < events.Num(); i++ ) {
if ( events[i].name.Icmp( FXAction.data ) == 0 ) {
FXAction.sibling = i;
FXAction.lightColor = events[i].lightColor;
FXAction.lightRadius = events[i].lightRadius;
}
}
FXAction.type = FX_LIGHT;
// precache the light material
declManager->FindMaterial( FXAction.data );
continue;
}
if ( !token.Icmp( "attachlight" ) ) {
src.ReadToken( &token );
FXAction.data = token;
FXAction.type = FX_ATTACHLIGHT;
// precache it
declManager->FindMaterial( FXAction.data );
continue;
}
if ( !token.Icmp( "attachentity" ) ) {
src.ReadToken( &token );
FXAction.data = token;
FXAction.type = FX_ATTACHENTITY;
// precache the model
renderModelManager->FindModel( FXAction.data );
continue;
}
if ( !token.Icmp( "launch" ) ) {
src.ReadToken( &token );
FXAction.data = token;
FXAction.type = FX_LAUNCH;
// precache the entity def
declManager->FindType( DECL_ENTITYDEF, FXAction.data );
continue;
}
if ( !token.Icmp( "useModel" ) ) {
src.ReadToken( &token );
FXAction.data = token;
for( int i = 0; i < events.Num(); i++ ) {
if ( events[i].name.Icmp( FXAction.data ) == 0 ) {
FXAction.sibling = i;
}
}
FXAction.type = FX_MODEL;
// precache the model
renderModelManager->FindModel( FXAction.data );
continue;
}
if ( !token.Icmp( "light" ) ) {
src.ReadToken( &token );
FXAction.data = token;
src.ExpectTokenString( "," );
FXAction.lightColor[0] = src.ParseFloat();
src.ExpectTokenString( "," );
FXAction.lightColor[1] = src.ParseFloat();
src.ExpectTokenString( "," );
FXAction.lightColor[2] = src.ParseFloat();
src.ExpectTokenString( "," );
FXAction.lightRadius = src.ParseFloat();
FXAction.type = FX_LIGHT;
// precache the light material
declManager->FindMaterial( FXAction.data );
continue;
}
if ( !token.Icmp( "model" ) ) {
src.ReadToken( &token );
FXAction.data = token;
FXAction.type = FX_MODEL;
// precache it
renderModelManager->FindModel( FXAction.data );
continue;
}
if ( !token.Icmp( "particle" ) ) { // FIXME: now the same as model
src.ReadToken( &token );
FXAction.data = token;
FXAction.type = FX_PARTICLE;
// precache it
renderModelManager->FindModel( FXAction.data );
continue;
}
if ( !token.Icmp( "decal" ) ) {
src.ReadToken( &token );
FXAction.data = token;
FXAction.type = FX_DECAL;
// precache it
declManager->FindMaterial( FXAction.data );
continue;
}
if ( !token.Icmp( "particleTrackVelocity" ) ) {
FXAction.particleTrackVelocity = true;
continue;
}
if ( !token.Icmp( "sound" ) ) {
src.ReadToken( &token );
FXAction.data = token;
FXAction.type = FX_SOUND;
// precache it
declManager->FindSound( FXAction.data );
continue;
}
if ( !token.Icmp( "ignoreMaster" ) ) {
FXAction.shakeIgnoreMaster = true;
continue;
}
if ( !token.Icmp( "shockwave" ) ) {
src.ReadToken( &token );
FXAction.data = token;
FXAction.type = FX_SHOCKWAVE;
// precache the entity def
declManager->FindType( DECL_ENTITYDEF, FXAction.data );
continue;
}
src.Warning( "FX File: bad token" );
continue;
}
}
/*
================
idDeclFX::Parse
================
*/
bool idDeclFX::Parse( const char *text, const int textLength ) {
idLexer src;
idToken token;
src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
src.SetFlags( DECL_LEXER_FLAGS );
src.SkipUntilString( "{" );
// scan through, identifying each individual parameter
while( 1 ) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( token == "}" ) {
break;
}
if ( !token.Icmp( "bindto" ) ) {
src.ReadToken( &token );
joint = token;
continue;
}
if ( !token.Icmp( "{" ) ) {
idFXSingleAction action;
ParseSingleFXAction( src, action );
events.Append( action );
continue;
}
}
if ( src.HadError() ) {
src.Warning( "FX decl '%s' had a parse error", GetName() );
return false;
}
return true;
}
/*
===================
idDeclFX::DefaultDefinition
===================
*/
const char *idDeclFX::DefaultDefinition( void ) const {
return
"{\n"
"\t" "{\n"
"\t\t" "duration\t5\n"
"\t\t" "model\t\t_default\n"
"\t" "}\n"
"}";
}
/*
===================
idDeclFX::FreeData
===================
*/
void idDeclFX::FreeData( void ) {
events.Clear();
}

113
neo/framework/DeclFX.h Normal file
View File

@@ -0,0 +1,113 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DECLFX_H__
#define __DECLFX_H__
/*
===============================================================================
idDeclFX
===============================================================================
*/
enum {
FX_LIGHT,
FX_PARTICLE,
FX_DECAL,
FX_MODEL,
FX_SOUND,
FX_SHAKE,
FX_ATTACHLIGHT,
FX_ATTACHENTITY,
FX_LAUNCH,
FX_SHOCKWAVE
};
//
// single fx structure
//
typedef struct {
int type;
int sibling;
idStr data;
idStr name;
idStr fire;
float delay;
float duration;
float restart;
float size;
float fadeInTime;
float fadeOutTime;
float shakeTime;
float shakeAmplitude;
float shakeDistance;
float shakeImpulse;
float lightRadius;
float rotate;
float random1;
float random2;
idVec3 lightColor;
idVec3 offset;
idMat3 axis;
bool soundStarted;
bool shakeStarted;
bool shakeFalloff;
bool shakeIgnoreMaster;
bool bindParticles;
bool explicitAxis;
bool noshadows;
bool particleTrackVelocity;
bool trackOrigin;
} idFXSingleAction;
//
// grouped fx structures
//
class idDeclFX : public idDecl {
public:
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
virtual void Print( void ) const;
virtual void List( void ) const;
idList<idFXSingleAction>events;
idStr joint;
private:
void ParseSingleFXAction( idLexer &src, idFXSingleAction& FXAction );
};
#endif /* !__DECLFX_H__ */

File diff suppressed because it is too large Load Diff

336
neo/framework/DeclManager.h Normal file
View File

@@ -0,0 +1,336 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DECLMANAGER_H__
#define __DECLMANAGER_H__
/*
===============================================================================
Declaration Manager
All "small text" data types, like materials, sound shaders, fx files,
entity defs, etc. are managed uniformly, allowing reloading, purging,
listing, printing, etc. All "large text" data types that never have more
than one declaration in a given file, like maps, models, AAS files, etc.
are not handled here.
A decl will never, ever go away once it is created. The manager is
garranteed to always return the same decl pointer for a decl type/name
combination. The index of a decl in the per type list also stays the
same throughout the lifetime of the engine. Although the pointer to
a decl always stays the same, one should never maintain pointers to
data inside decls. The data stored in a decl is not garranteed to stay
the same for more than one engine frame.
The decl indexes of explicitely defined decls are garrenteed to be
consistent based on the parsed decl files. However, the indexes of
implicit decls may be different based on the order in which levels
are loaded.
The decl namespaces are separate for each type. Comments for decls go
above the text definition to keep them associated with the proper decl.
During decl parsing, errors should never be issued, only warnings
followed by a call to MakeDefault().
===============================================================================
*/
typedef enum {
DECL_TABLE = 0,
DECL_MATERIAL,
DECL_SKIN,
DECL_SOUND,
DECL_ENTITYDEF,
DECL_MODELDEF,
DECL_FX,
DECL_PARTICLE,
DECL_AF,
DECL_PDA,
DECL_VIDEO,
DECL_AUDIO,
DECL_EMAIL,
DECL_MODELEXPORT,
DECL_MAPDEF,
// new decl types can be added here
DECL_MAX_TYPES = 32
} declType_t;
typedef enum {
DS_UNPARSED,
DS_DEFAULTED, // set if a parse failed due to an error, or the lack of any source
DS_PARSED
} declState_t;
const int DECL_LEXER_FLAGS = LEXFL_NOSTRINGCONCAT | // multiple strings seperated by whitespaces are not concatenated
LEXFL_NOSTRINGESCAPECHARS | // no escape characters inside strings
LEXFL_ALLOWPATHNAMES | // allow path seperators in names
LEXFL_ALLOWMULTICHARLITERALS | // allow multi character literals
LEXFL_ALLOWBACKSLASHSTRINGCONCAT | // allow multiple strings seperated by '\' to be concatenated
LEXFL_NOFATALERRORS; // just set a flag instead of fatal erroring
class idDeclBase {
public:
virtual ~idDeclBase() {};
virtual const char * GetName( void ) const = 0;
virtual declType_t GetType( void ) const = 0;
virtual declState_t GetState( void ) const = 0;
virtual bool IsImplicit( void ) const = 0;
virtual bool IsValid( void ) const = 0;
virtual void Invalidate( void ) = 0;
virtual void Reload( void ) = 0;
virtual void EnsureNotPurged( void ) = 0;
virtual int Index( void ) const = 0;
virtual int GetLineNum( void ) const = 0;
virtual const char * GetFileName( void ) const = 0;
virtual void GetText( char *text ) const = 0;
virtual int GetTextLength( void ) const = 0;
virtual void SetText( const char *text ) = 0;
virtual bool ReplaceSourceFileText( void ) = 0;
virtual bool SourceFileChanged( void ) const = 0;
virtual void MakeDefault( void ) = 0;
virtual bool EverReferenced( void ) const = 0;
virtual bool SetDefaultText( void ) = 0;
virtual const char * DefaultDefinition( void ) const = 0;
virtual bool Parse( const char *text, const int textLength ) = 0;
virtual void FreeData( void ) = 0;
virtual size_t Size( void ) const = 0;
virtual void List( void ) const = 0;
virtual void Print( void ) const = 0;
};
class idDecl {
public:
// The constructor should initialize variables such that
// an immediate call to FreeData() does no harm.
idDecl( void ) { base = NULL; }
virtual ~idDecl( void ) {};
// Returns the name of the decl.
const char * GetName( void ) const { return base->GetName(); }
// Returns the decl type.
declType_t GetType( void ) const { return base->GetType(); }
// Returns the decl state which is usefull for finding out if a decl defaulted.
declState_t GetState( void ) const { return base->GetState(); }
// Returns true if the decl was defaulted or the text was created with a call to SetDefaultText.
bool IsImplicit( void ) const { return base->IsImplicit(); }
// The only way non-manager code can have an invalid decl is if the *ByIndex()
// call was used with forceParse = false to walk the lists to look at names
// without touching the media.
bool IsValid( void ) const { return base->IsValid(); }
// Sets state back to unparsed.
// Used by decl editors to undo any changes to the decl.
void Invalidate( void ) { base->Invalidate(); }
// if a pointer might possible be stale from a previous level,
// call this to have it re-parsed
void EnsureNotPurged( void ) { base->EnsureNotPurged(); }
// Returns the index in the per-type list.
int Index( void ) const { return base->Index(); }
// Returns the line number the decl starts.
int GetLineNum( void ) const { return base->GetLineNum(); }
// Returns the name of the file in which the decl is defined.
const char * GetFileName( void ) const { return base->GetFileName(); }
// Returns the decl text.
void GetText( char *text ) const { base->GetText( text ); }
// Returns the length of the decl text.
int GetTextLength( void ) const { return base->GetTextLength(); }
// Sets new decl text.
void SetText( const char *text ) { base->SetText( text ); }
// Saves out new text for the decl.
// Used by decl editors to replace the decl text in the source file.
bool ReplaceSourceFileText( void ) { return base->ReplaceSourceFileText(); }
// Returns true if the source file changed since it was loaded and parsed.
bool SourceFileChanged( void ) const { return base->SourceFileChanged(); }
// Frees data and makes the decl a default.
void MakeDefault( void ) { base->MakeDefault(); }
// Returns true if the decl was ever referenced.
bool EverReferenced( void ) const { return base->EverReferenced(); }
public:
// Sets textSource to a default text if necessary.
// This may be overridden to provide a default definition based on the
// decl name. For instance materials may default to an implicit definition
// using a texture with the same name as the decl.
virtual bool SetDefaultText( void ) { return base->SetDefaultText(); }
// Each declaration type must have a default string that it is guaranteed
// to parse acceptably. When a decl is not explicitly found, is purged, or
// has an error while parsing, MakeDefault() will do a FreeData(), then a
// Parse() with DefaultDefinition(). The defaultDefintion should start with
// an open brace and end with a close brace.
virtual const char * DefaultDefinition( void ) const { return base->DefaultDefinition(); }
// The manager will have already parsed past the type, name and opening brace.
// All necessary media will be touched before return.
// The manager will have called FreeData() before issuing a Parse().
// The subclass can call MakeDefault() internally at any point if
// there are parse errors.
virtual bool Parse( const char *text, const int textLength ) { return base->Parse( text, textLength ); }
// Frees any pointers held by the subclass. This may be called before
// any Parse(), so the constructor must have set sane values. The decl will be
// invalid after issuing this call, but it will always be immediately followed
// by a Parse()
virtual void FreeData( void ) { base->FreeData(); }
// Returns the size of the decl in memory.
virtual size_t Size( void ) const { return base->Size(); }
// If this isn't overridden, it will just print the decl name.
// The manager will have printed 7 characters on the line already,
// containing the reference state and index number.
virtual void List( void ) const { base->List(); }
// The print function will already have dumped the text source
// and common data, subclasses can override this to dump more
// explicit data.
virtual void Print( void ) const { base->Print(); }
public:
idDeclBase * base;
};
template< class type >
ID_INLINE idDecl *idDeclAllocator( void ) {
return new type;
}
class idMaterial;
class idDeclSkin;
class idSoundShader;
class idDeclManager {
public:
virtual ~idDeclManager( void ) {}
virtual void Init( void ) = 0;
virtual void Shutdown( void ) = 0;
virtual void Reload( bool force ) = 0;
virtual void BeginLevelLoad() = 0;
virtual void EndLevelLoad() = 0;
// Registers a new decl type.
virtual void RegisterDeclType( const char *typeName, declType_t type, idDecl *(*allocator)( void ) ) = 0;
// Registers a new folder with decl files.
virtual void RegisterDeclFolder( const char *folder, const char *extension, declType_t defaultType ) = 0;
// Returns a checksum for all loaded decl text.
virtual int GetChecksum( void ) const = 0;
// Returns the number of decl types.
virtual int GetNumDeclTypes( void ) const = 0;
// Returns the type name for a decl type.
virtual const char * GetDeclNameFromType( declType_t type ) const = 0;
// Returns the decl type for a type name.
virtual declType_t GetDeclTypeFromName( const char *typeName ) const = 0;
// If makeDefault is true, a default decl of appropriate type will be created
// if an explicit one isn't found. If makeDefault is false, NULL will be returned
// if the decl wasn't explcitly defined.
virtual const idDecl * FindType( declType_t type, const char *name, bool makeDefault = true ) = 0;
virtual const idDecl* FindDeclWithoutParsing( declType_t type, const char *name, bool makeDefault = true ) = 0;
virtual void ReloadFile( const char* filename, bool force ) = 0;
// Returns the number of decls of the given type.
virtual int GetNumDecls( declType_t type ) = 0;
// The complete lists of decls can be walked to populate editor browsers.
// If forceParse is set false, you can get the decl to check name / filename / etc.
// without causing it to parse the source and load media.
virtual const idDecl * DeclByIndex( declType_t type, int index, bool forceParse = true ) = 0;
// List and print decls.
virtual void ListType( const idCmdArgs &args, declType_t type ) = 0;
virtual void PrintType( const idCmdArgs &args, declType_t type ) = 0;
// Creates a new default decl of the given type with the given name in
// the given file used by editors to create a new decls.
virtual idDecl * CreateNewDecl( declType_t type, const char *name, const char *fileName ) = 0;
// BSM - Added for the material editors rename capabilities
virtual bool RenameDecl( declType_t type, const char* oldName, const char* newName ) = 0;
// When media files are loaded, a reference line can be printed at a
// proper indentation if decl_show is set
virtual void MediaPrint( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
virtual void WritePrecacheCommands( idFile *f ) = 0;
// Convenience functions for specific types.
virtual const idMaterial * FindMaterial( const char *name, bool makeDefault = true ) = 0;
virtual const idDeclSkin * FindSkin( const char *name, bool makeDefault = true ) = 0;
virtual const idSoundShader * FindSound( const char *name, bool makeDefault = true ) = 0;
virtual const idMaterial * MaterialByIndex( int index, bool forceParse = true ) = 0;
virtual const idDeclSkin * SkinByIndex( int index, bool forceParse = true ) = 0;
virtual const idSoundShader * SoundByIndex( int index, bool forceParse = true ) = 0;
};
extern idDeclManager * declManager;
template< declType_t type >
ID_INLINE void idListDecls_f( const idCmdArgs &args ) {
declManager->ListType( args, type );
}
template< declType_t type >
ID_INLINE void idPrintDecls_f( const idCmdArgs &args ) {
declManager->PrintType( args, type );
}
#endif /* !__DECLMANAGER_H__ */

668
neo/framework/DeclPDA.cpp Normal file
View File

@@ -0,0 +1,668 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
/*
=================
idDeclPDA::Size
=================
*/
size_t idDeclPDA::Size( void ) const {
return sizeof( idDeclPDA );
}
/*
===============
idDeclPDA::Print
===============
*/
void idDeclPDA::Print( void ) const {
common->Printf( "Implement me\n" );
}
/*
===============
idDeclPDA::List
===============
*/
void idDeclPDA::List( void ) const {
common->Printf( "Implement me\n" );
}
/*
================
idDeclPDA::Parse
================
*/
bool idDeclPDA::Parse( const char *text, const int textLength ) {
idLexer src;
idToken token;
src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
src.SetFlags( DECL_LEXER_FLAGS );
src.SkipUntilString( "{" );
// scan through, identifying each individual parameter
while( 1 ) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( token == "}" ) {
break;
}
if ( !token.Icmp( "name") ) {
src.ReadToken( &token );
pdaName = token;
continue;
}
if ( !token.Icmp( "fullname") ) {
src.ReadToken( &token );
fullName = token;
continue;
}
if ( !token.Icmp( "icon") ) {
src.ReadToken( &token );
icon = token;
continue;
}
if ( !token.Icmp( "id") ) {
src.ReadToken( &token );
id = token;
continue;
}
if ( !token.Icmp( "post") ) {
src.ReadToken( &token );
post = token;
continue;
}
if ( !token.Icmp( "title") ) {
src.ReadToken( &token );
title = token;
continue;
}
if ( !token.Icmp( "security") ) {
src.ReadToken( &token );
security = token;
continue;
}
if ( !token.Icmp( "pda_email") ) {
src.ReadToken( &token );
emails.Append( token );
declManager->FindType(DECL_EMAIL, token);
continue;
}
if ( !token.Icmp( "pda_audio") ) {
src.ReadToken( &token );
audios.Append( token );
declManager->FindType(DECL_AUDIO, token);
continue;
}
if ( !token.Icmp( "pda_video") ) {
src.ReadToken( &token );
videos.Append( token );
declManager->FindType(DECL_VIDEO, token);
continue;
}
}
if ( src.HadError() ) {
src.Warning( "PDA decl '%s' had a parse error", GetName() );
return false;
}
originalVideos = videos.Num();
originalEmails = emails.Num();
return true;
}
/*
===================
idDeclPDA::DefaultDefinition
===================
*/
const char *idDeclPDA::DefaultDefinition( void ) const {
return
"{\n"
"\t" "name \"default pda\"\n"
"}";
}
/*
===================
idDeclPDA::FreeData
===================
*/
void idDeclPDA::FreeData( void ) {
videos.Clear();
audios.Clear();
emails.Clear();
originalEmails = 0;
originalVideos = 0;
}
/*
=================
idDeclPDA::AddVideo
=================
*/
void idDeclPDA::AddVideo( const char *name, bool unique ) const {
if ( unique && ( videos.Find( name ) != NULL ) ) {
return;
}
if ( declManager->FindType( DECL_VIDEO, name, false ) == NULL ) {
common->Printf( "Video %s not found\n", name );
return;
}
videos.Append( name );
}
/*
=================
idDeclPDA::AddAudio
=================
*/
void idDeclPDA::AddAudio( const char *name, bool unique ) const {
if ( unique && ( audios.Find( name ) != NULL ) ) {
return;
}
if ( declManager->FindType( DECL_AUDIO, name, false ) == NULL ) {
common->Printf( "Audio log %s not found\n", name );
return;
}
audios.Append( name );
}
/*
=================
idDeclPDA::AddEmail
=================
*/
void idDeclPDA::AddEmail( const char *name, bool unique ) const {
if ( unique && ( emails.Find( name ) != NULL ) ) {
return;
}
if ( declManager->FindType( DECL_EMAIL, name, false ) == NULL ) {
common->Printf( "Email %s not found\n", name );
return;
}
emails.Append( name );
}
/*
=================
idDeclPDA::RemoveAddedEmailsAndVideos
=================
*/
void idDeclPDA::RemoveAddedEmailsAndVideos() const {
int num = emails.Num();
if ( originalEmails < num ) {
while ( num && num > originalEmails ) {
emails.RemoveIndex( --num );
}
}
num = videos.Num();
if ( originalVideos < num ) {
while ( num && num > originalVideos ) {
videos.RemoveIndex( --num );
}
}
}
/*
=================
idDeclPDA::SetSecurity
=================
*/
void idDeclPDA::SetSecurity( const char *sec ) const {
security = sec;
}
/*
=================
idDeclPDA::GetNumVideos
=================
*/
const int idDeclPDA::GetNumVideos() const {
return videos.Num();
}
/*
=================
idDeclPDA::GetNumAudios
=================
*/
const int idDeclPDA::GetNumAudios() const {
return audios.Num();
}
/*
=================
idDeclPDA::GetNumEmails
=================
*/
const int idDeclPDA::GetNumEmails() const {
return emails.Num();
}
/*
=================
idDeclPDA::GetVideoByIndex
=================
*/
const idDeclVideo* idDeclPDA::GetVideoByIndex( int index ) const {
if ( index >= 0 && index < videos.Num() ) {
return static_cast< const idDeclVideo* >( declManager->FindType( DECL_VIDEO, videos[index], false ) );
}
return NULL;
}
/*
=================
idDeclPDA::GetAudioByIndex
=================
*/
const idDeclAudio* idDeclPDA::GetAudioByIndex( int index ) const {
if ( index >= 0 && index < audios.Num() ) {
return static_cast< const idDeclAudio* >( declManager->FindType( DECL_AUDIO, audios[index], false ) );
}
return NULL;
}
/*
=================
idDeclPDA::GetEmailByIndex
=================
*/
const idDeclEmail* idDeclPDA::GetEmailByIndex( int index ) const {
if ( index >= 0 && index < emails.Num() ) {
return static_cast< const idDeclEmail* >( declManager->FindType( DECL_EMAIL, emails[index], false ) );
}
return NULL;
}
/*
=================
idDeclEmail::Size
=================
*/
size_t idDeclEmail::Size( void ) const {
return sizeof( idDeclEmail );
}
/*
===============
idDeclEmail::Print
===============
*/
void idDeclEmail::Print( void ) const {
common->Printf( "Implement me\n" );
}
/*
===============
idDeclEmail::List
===============
*/
void idDeclEmail::List( void ) const {
common->Printf( "Implement me\n" );
}
/*
================
idDeclEmail::Parse
================
*/
bool idDeclEmail::Parse( const char *_text, const int textLength ) {
idLexer src;
idToken token;
src.LoadMemory( _text, textLength, GetFileName(), GetLineNum() );
src.SetFlags( LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT | LEXFL_NOFATALERRORS );
src.SkipUntilString( "{" );
text = "";
// scan through, identifying each individual parameter
while( 1 ) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( token == "}" ) {
break;
}
if ( !token.Icmp( "subject") ) {
src.ReadToken( &token );
subject = token;
continue;
}
if ( !token.Icmp( "to") ) {
src.ReadToken( &token );
to = token;
continue;
}
if ( !token.Icmp( "from") ) {
src.ReadToken( &token );
from = token;
continue;
}
if ( !token.Icmp( "date") ) {
src.ReadToken( &token );
date = token;
continue;
}
if ( !token.Icmp( "text") ) {
src.ReadToken( &token );
if ( token != "{" ) {
src.Warning( "Email decl '%s' had a parse error", GetName() );
return false;
}
while ( src.ReadToken( &token ) && token != "}" ) {
text += token;
}
continue;
}
if ( !token.Icmp( "image") ) {
src.ReadToken( &token );
image = token;
continue;
}
}
if ( src.HadError() ) {
src.Warning( "Email decl '%s' had a parse error", GetName() );
return false;
}
return true;
}
/*
===================
idDeclEmail::DefaultDefinition
===================
*/
const char *idDeclEmail::DefaultDefinition( void ) const {
return
"{\n"
"\t" "{\n"
"\t\t" "to\t5Mail recipient\n"
"\t\t" "subject\t5Nothing\n"
"\t\t" "from\t5No one\n"
"\t" "}\n"
"}";
}
/*
===================
idDeclEmail::FreeData
===================
*/
void idDeclEmail::FreeData( void ) {
}
/*
=================
idDeclVideo::Size
=================
*/
size_t idDeclVideo::Size( void ) const {
return sizeof( idDeclVideo );
}
/*
===============
idDeclVideo::Print
===============
*/
void idDeclVideo::Print( void ) const {
common->Printf( "Implement me\n" );
}
/*
===============
idDeclVideo::List
===============
*/
void idDeclVideo::List( void ) const {
common->Printf( "Implement me\n" );
}
/*
================
idDeclVideo::Parse
================
*/
bool idDeclVideo::Parse( const char *text, const int textLength ) {
idLexer src;
idToken token;
src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
src.SetFlags( LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT | LEXFL_NOFATALERRORS );
src.SkipUntilString( "{" );
// scan through, identifying each individual parameter
while( 1 ) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( token == "}" ) {
break;
}
if ( !token.Icmp( "name") ) {
src.ReadToken( &token );
videoName = token;
continue;
}
if ( !token.Icmp( "preview") ) {
src.ReadToken( &token );
preview = token;
continue;
}
if ( !token.Icmp( "video") ) {
src.ReadToken( &token );
video = token;
declManager->FindMaterial( video );
continue;
}
if ( !token.Icmp( "info") ) {
src.ReadToken( &token );
info = token;
continue;
}
if ( !token.Icmp( "audio") ) {
src.ReadToken( &token );
audio = token;
declManager->FindSound(audio);
continue;
}
}
if ( src.HadError() ) {
src.Warning( "Video decl '%s' had a parse error", GetName() );
return false;
}
return true;
}
/*
===================
idDeclVideo::DefaultDefinition
===================
*/
const char *idDeclVideo::DefaultDefinition( void ) const {
return
"{\n"
"\t" "{\n"
"\t\t" "name\t5Default Video\n"
"\t" "}\n"
"}";
}
/*
===================
idDeclVideo::FreeData
===================
*/
void idDeclVideo::FreeData( void ) {
}
/*
=================
idDeclAudio::Size
=================
*/
size_t idDeclAudio::Size( void ) const {
return sizeof( idDeclAudio );
}
/*
===============
idDeclAudio::Print
===============
*/
void idDeclAudio::Print( void ) const {
common->Printf( "Implement me\n" );
}
/*
===============
idDeclAudio::List
===============
*/
void idDeclAudio::List( void ) const {
common->Printf( "Implement me\n" );
}
/*
================
idDeclAudio::Parse
================
*/
bool idDeclAudio::Parse( const char *text, const int textLength ) {
idLexer src;
idToken token;
src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
src.SetFlags( LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT | LEXFL_NOFATALERRORS );
src.SkipUntilString( "{" );
// scan through, identifying each individual parameter
while( 1 ) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( token == "}" ) {
break;
}
if ( !token.Icmp( "name") ) {
src.ReadToken( &token );
audioName = token;
continue;
}
if ( !token.Icmp( "audio") ) {
src.ReadToken( &token );
audio = token;
declManager->FindSound(audio);
continue;
}
if ( !token.Icmp( "info") ) {
src.ReadToken( &token );
info = token;
continue;
}
if ( !token.Icmp( "preview") ) {
src.ReadToken( &token );
preview = token;
continue;
}
}
if ( src.HadError() ) {
src.Warning( "Audio decl '%s' had a parse error", GetName() );
return false;
}
return true;
}
/*
===================
idDeclAudio::DefaultDefinition
===================
*/
const char *idDeclAudio::DefaultDefinition( void ) const {
return
"{\n"
"\t" "{\n"
"\t\t" "name\t5Default Audio\n"
"\t" "}\n"
"}";
}
/*
===================
idDeclAudio::FreeData
===================
*/
void idDeclAudio::FreeData( void ) {
}

167
neo/framework/DeclPDA.h Normal file
View File

@@ -0,0 +1,167 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DECLPDA_H__
#define __DECLPDA_H__
/*
===============================================================================
idDeclPDA
===============================================================================
*/
class idDeclEmail : public idDecl {
public:
idDeclEmail() {}
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
virtual void Print( void ) const;
virtual void List( void ) const;
const char * GetFrom() const { return from; }
const char * GetBody() const { return text; }
const char * GetSubject() const { return subject; }
const char * GetDate() const { return date; }
const char * GetTo() const { return to; }
const char * GetImage() const { return image; }
private:
idStr text;
idStr subject;
idStr date;
idStr to;
idStr from;
idStr image;
};
class idDeclVideo : public idDecl {
public:
idDeclVideo() {};
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
virtual void Print( void ) const;
virtual void List( void ) const;
const char * GetRoq() const { return video; }
const char * GetWave() const { return audio; }
const char * GetVideoName() const { return videoName; }
const char * GetInfo() const { return info; }
const char * GetPreview() const { return preview; }
private:
idStr preview;
idStr video;
idStr videoName;
idStr info;
idStr audio;
};
class idDeclAudio : public idDecl {
public:
idDeclAudio() {};
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
virtual void Print( void ) const;
virtual void List( void ) const;
const char * GetAudioName() const { return audioName; }
const char * GetWave() const { return audio; }
const char * GetInfo() const { return info; }
const char * GetPreview() const { return preview; }
private:
idStr audio;
idStr audioName;
idStr info;
idStr preview;
};
class idDeclPDA : public idDecl {
public:
idDeclPDA() { originalEmails = originalVideos = 0; };
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
virtual void Print( void ) const;
virtual void List( void ) const;
virtual void AddVideo( const char *name, bool unique = true ) const;
virtual void AddAudio( const char *name, bool unique = true ) const;
virtual void AddEmail( const char *name, bool unique = true ) const;
virtual void RemoveAddedEmailsAndVideos() const;
virtual const int GetNumVideos() const;
virtual const int GetNumAudios() const;
virtual const int GetNumEmails() const;
virtual const idDeclVideo *GetVideoByIndex( int index ) const;
virtual const idDeclAudio *GetAudioByIndex( int index ) const;
virtual const idDeclEmail *GetEmailByIndex( int index ) const;
virtual void SetSecurity( const char *sec ) const;
const char * GetPdaName() const { return pdaName; }
const char * GetSecurity() const {return security; }
const char * GetFullName() const { return fullName; }
const char * GetIcon() const { return icon; }
const char * GetPost() const { return post; }
const char * GetID() const { return id; }
const char * GetTitle() const { return title; }
private:
mutable idStrList videos;
mutable idStrList audios;
mutable idStrList emails;
idStr pdaName;
idStr fullName;
idStr icon;
idStr id;
idStr post;
idStr title;
mutable idStr security;
mutable int originalEmails;
mutable int originalVideos;
};
#endif /* !__DECLPDA_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,218 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DECLPARTICLE_H__
#define __DECLPARTICLE_H__
/*
===============================================================================
idDeclParticle
===============================================================================
*/
class idParticleParm {
public:
idParticleParm( void ) { table = NULL; from = to = 0.0f; }
const idDeclTable * table;
float from;
float to;
float Eval( float frac, idRandom &rand ) const;
float Integrate( float frac, idRandom &rand ) const;
};
typedef enum {
PDIST_RECT, // ( sizeX sizeY sizeZ )
PDIST_CYLINDER, // ( sizeX sizeY sizeZ )
PDIST_SPHERE // ( sizeX sizeY sizeZ ringFraction )
// a ringFraction of zero allows the entire sphere, 0.9 would only
// allow the outer 10% of the sphere
} prtDistribution_t;
typedef enum {
PDIR_CONE, // parm0 is the solid cone angle
PDIR_OUTWARD // direction is relative to offset from origin, parm0 is an upward bias
} prtDirection_t;
typedef enum {
PPATH_STANDARD,
PPATH_HELIX, // ( sizeX sizeY sizeZ radialSpeed climbSpeed )
PPATH_FLIES,
PPATH_ORBIT,
PPATH_DRIP
} prtCustomPth_t;
typedef enum {
POR_VIEW,
POR_AIMED, // angle and aspect are disregarded
POR_X,
POR_Y,
POR_Z
} prtOrientation_t;
typedef struct renderEntity_s renderEntity_t;
typedef struct renderView_s renderView_t;
typedef struct {
const renderEntity_t * renderEnt; // for shaderParms, etc
const renderView_t * renderView;
int index; // particle number in the system
float frac; // 0.0 to 1.0
idRandom random;
idVec3 origin; // dynamic smoke particles can have individual origins and axis
idMat3 axis;
float age; // in seconds, calculated as fraction * stage->particleLife
idRandom originalRandom; // needed so aimed particles can reset the random for another origin calculation
float animationFrameFrac; // set by ParticleTexCoords, used to make the cross faded version
} particleGen_t;
//
// single particle stage
//
class idParticleStage {
public:
idParticleStage( void );
virtual ~idParticleStage( void ) {}
void Default();
virtual int NumQuadsPerParticle() const; // includes trails and cross faded animations
// returns the number of verts created, which will range from 0 to 4*NumQuadsPerParticle()
virtual int CreateParticle( particleGen_t *g, idDrawVert *verts ) const;
void ParticleOrigin( particleGen_t *g, idVec3 &origin ) const;
int ParticleVerts( particleGen_t *g, const idVec3 origin, idDrawVert *verts ) const;
void ParticleTexCoords( particleGen_t *g, idDrawVert *verts ) const;
void ParticleColors( particleGen_t *g, idDrawVert *verts ) const;
const char * GetCustomPathName();
const char * GetCustomPathDesc();
int NumCustomPathParms();
void SetCustomPathType( const char *p );
void operator=( const idParticleStage &src );
//------------------------------
const idMaterial * material;
int totalParticles; // total number of particles, although some may be invisible at a given time
float cycles; // allows things to oneShot ( 1 cycle ) or run for a set number of cycles
// on a per stage basis
int cycleMsec; // ( particleLife + deadTime ) in msec
float spawnBunching; // 0.0 = all come out at first instant, 1.0 = evenly spaced over cycle time
float particleLife; // total seconds of life for each particle
float timeOffset; // time offset from system start for the first particle to spawn
float deadTime; // time after particleLife before respawning
//------------------------------- // standard path parms
prtDistribution_t distributionType;
float distributionParms[4];
prtDirection_t directionType;
float directionParms[4];
idParticleParm speed;
float gravity; // can be negative to float up
bool worldGravity; // apply gravity in world space
bool randomDistribution; // randomly orient the quad on emission ( defaults to true )
bool entityColor; // force color from render entity ( fadeColor is still valid )
//------------------------------ // custom path will completely replace the standard path calculations
prtCustomPth_t customPathType; // use custom C code routines for determining the origin
float customPathParms[8];
//--------------------------------
idVec3 offset; // offset from origin to spawn all particles, also applies to customPath
int animationFrames; // if > 1, subdivide the texture S axis into frames and crossfade
float animationRate; // frames per second
float initialAngle; // in degrees, random angle is used if zero ( default )
idParticleParm rotationSpeed; // half the particles will have negative rotation speeds
prtOrientation_t orientation; // view, aimed, or axis fixed
float orientationParms[4];
idParticleParm size;
idParticleParm aspect; // greater than 1 makes the T axis longer
idVec4 color;
idVec4 fadeColor; // either 0 0 0 0 for additive, or 1 1 1 0 for blended materials
float fadeInFraction; // in 0.0 to 1.0 range
float fadeOutFraction; // in 0.0 to 1.0 range
float fadeIndexFraction; // in 0.0 to 1.0 range, causes later index smokes to be more faded
bool hidden; // for editor use
//-----------------------------------
float boundsExpansion; // user tweak to fix poorly calculated bounds
idBounds bounds; // derived
};
//
// group of particle stages
//
class idDeclParticle : public idDecl {
public:
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
bool Save( const char *fileName = NULL );
idList<idParticleStage *>stages;
idBounds bounds;
float depthHack;
private:
bool RebuildTextSource( void );
void GetStageBounds( idParticleStage *stage );
idParticleStage * ParseParticleStage( idLexer &src );
void ParseParms( idLexer &src, float *parms, int maxParms );
void ParseParametric( idLexer &src, idParticleParm *parm );
void WriteStage( idFile *f, idParticleStage *stage );
void WriteParticleParm( idFile *f, idParticleParm *parm, const char *name );
};
#endif /* !__DECLPARTICLE_H__ */

185
neo/framework/DeclSkin.cpp Normal file
View File

@@ -0,0 +1,185 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
/*
=================
idDeclSkin::Size
=================
*/
size_t idDeclSkin::Size( void ) const {
return sizeof( idDeclSkin );
}
/*
================
idDeclSkin::FreeData
================
*/
void idDeclSkin::FreeData( void ) {
mappings.Clear();
}
/*
================
idDeclSkin::Parse
================
*/
bool idDeclSkin::Parse( const char *text, const int textLength ) {
idLexer src;
idToken token, token2;
src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
src.SetFlags( DECL_LEXER_FLAGS );
src.SkipUntilString( "{" );
associatedModels.Clear();
while (1) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( !token.Icmp( "}" ) ) {
break;
}
if ( !src.ReadToken( &token2 ) ) {
src.Warning( "Unexpected end of file" );
MakeDefault();
return false;
}
if ( !token.Icmp( "model" ) ) {
associatedModels.Append( token2 );
continue;
}
skinMapping_t map;
if ( !token.Icmp( "*" ) ) {
// wildcard
map.from = NULL;
} else {
map.from = declManager->FindMaterial( token );
}
map.to = declManager->FindMaterial( token2 );
mappings.Append( map );
}
return false;
}
/*
================
idDeclSkin::SetDefaultText
================
*/
bool idDeclSkin::SetDefaultText( void ) {
// if there exists a material with the same name
if ( declManager->FindType( DECL_MATERIAL, GetName(), false ) ) {
char generated[2048];
idStr::snPrintf( generated, sizeof( generated ),
"skin %s // IMPLICITLY GENERATED\n"
"{\n"
"_default %s\n"
"}\n", GetName(), GetName() );
SetText( generated );
return true;
} else {
return false;
}
}
/*
================
idDeclSkin::DefaultDefinition
================
*/
const char *idDeclSkin::DefaultDefinition( void ) const {
return
"{\n"
"\t" "\"*\"\t\"_default\"\n"
"}";
}
/*
================
idDeclSkin::GetNumModelAssociations
================
*/
const int idDeclSkin::GetNumModelAssociations(void ) const {
return associatedModels.Num();
}
/*
================
idDeclSkin::GetAssociatedModel
================
*/
const char *idDeclSkin::GetAssociatedModel( int index ) const {
if ( index >= 0 && index < associatedModels.Num() ) {
return associatedModels[ index ];
}
return "";
}
/*
===============
RemapShaderBySkin
===============
*/
const idMaterial *idDeclSkin::RemapShaderBySkin( const idMaterial *shader ) const {
int i;
if ( !shader ) {
return NULL;
}
// never remap surfaces that were originally nodraw, like collision hulls
if ( !shader->IsDrawn() ) {
return shader;
}
for ( i = 0; i < mappings.Num() ; i++ ) {
const skinMapping_t *map = &mappings[i];
// NULL = wildcard match
if ( !map->from || map->from == shader ) {
return map->to;
}
}
// didn't find a match or wildcard, so stay the same
return shader;
}

64
neo/framework/DeclSkin.h Normal file
View File

@@ -0,0 +1,64 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DECLSKIN_H__
#define __DECLSKIN_H__
/*
===============================================================================
idDeclSkin
===============================================================================
*/
typedef struct {
const idMaterial * from; // 0 == any unmatched shader
const idMaterial * to;
} skinMapping_t;
class idDeclSkin : public idDecl {
public:
virtual size_t Size( void ) const;
virtual bool SetDefaultText( void );
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
const idMaterial * RemapShaderBySkin( const idMaterial *shader ) const;
// model associations are just for the preview dialog in the editor
const int GetNumModelAssociations() const;
const char * GetAssociatedModel( int index ) const;
private:
idList<skinMapping_t> mappings;
idStrList associatedModels;
};
#endif /* !__DECLSKIN_H__ */

177
neo/framework/DeclTable.cpp Normal file
View File

@@ -0,0 +1,177 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
/*
=================
idDeclTable::TableLookup
=================
*/
float idDeclTable::TableLookup( float index ) const {
int iIndex;
float iFrac;
int domain = values.Num() - 1;
if ( domain <= 1 ) {
return 1.0f;
}
if ( clamp ) {
index *= (domain-1);
if ( index >= domain - 1 ) {
return values[domain - 1];
} else if ( index <= 0 ) {
return values[0];
}
iIndex = idMath::Ftoi( index );
iFrac = index - iIndex;
} else {
index *= domain;
if ( index < 0 ) {
index += domain * idMath::Ceil( -index / domain );
}
iIndex = idMath::FtoiFast( idMath::Floor( index ) );
iFrac = index - iIndex;
iIndex = iIndex % domain;
}
if ( !snap ) {
// we duplicated the 0 index at the end at creation time, so we
// don't need to worry about wrapping the filter
return values[iIndex] * ( 1.0f - iFrac ) + values[iIndex + 1] * iFrac;
}
return values[iIndex];
}
/*
=================
idDeclTable::Size
=================
*/
size_t idDeclTable::Size( void ) const {
return sizeof( idDeclTable ) + values.Allocated();
}
/*
=================
idDeclTable::FreeData
=================
*/
void idDeclTable::FreeData( void ) {
snap = false;
clamp = false;
values.Clear();
}
/*
=================
idDeclTable::DefaultDefinition
=================
*/
const char *idDeclTable::DefaultDefinition( void ) const {
return "{ { 0 } }";
}
/*
=================
idDeclTable::Parse
=================
*/
bool idDeclTable::Parse( const char *text, const int textLength ) {
idLexer src;
idToken token;
float v;
src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
src.SetFlags( DECL_LEXER_FLAGS );
src.SkipUntilString( "{" );
snap = false;
clamp = false;
values.Clear();
while ( 1 ) {
if ( !src.ReadToken( &token ) ) {
break;
}
if ( token == "}" ) {
break;
}
if ( token.Icmp( "snap" ) == 0 ) {
snap = true;
} else if ( token.Icmp( "clamp" ) == 0 ) {
clamp = true;
} else if ( token.Icmp( "{" ) == 0 ) {
while ( 1 ) {
bool errorFlag;
v = src.ParseFloat( &errorFlag );
if ( errorFlag ) {
// we got something non-numeric
MakeDefault();
return false;
}
values.Append( v );
src.ReadToken( &token );
if ( token == "}" ) {
break;
}
if ( token == "," ) {
continue;
}
src.Warning( "expected comma or brace" );
MakeDefault();
return false;
}
} else {
src.Warning( "unknown token '%s'", token.c_str() );
MakeDefault();
return false;
}
}
// copy the 0 element to the end, so lerping doesn't
// need to worry about the wrap case
float val = values[0]; // template bug requires this to not be in the Append()?
values.Append( val );
return true;
}

56
neo/framework/DeclTable.h Normal file
View File

@@ -0,0 +1,56 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DECLTABLE_H__
#define __DECLTABLE_H__
/*
===============================================================================
tables are used to map a floating point input value to a floating point
output value, with optional wrap / clamp and interpolation
===============================================================================
*/
class idDeclTable : public idDecl {
public:
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
float TableLookup( float index ) const;
private:
bool clamp;
bool snap;
idList<float> values;
};
#endif /* !__DECLTABLE_H__ */

View File

@@ -0,0 +1,39 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*
===============================================================================
Pak file checksum for demo build.
===============================================================================
*/
// every time a new demo pk4 file is built, this checksum must be updated.
// the easiest way to get it is to just run the game and see what it spits out
#define DEMO_PAK_CHECKSUM 0xfe75bbef

328
neo/framework/DemoFile.cpp Normal file
View File

@@ -0,0 +1,328 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
idCVar idDemoFile::com_logDemos( "com_logDemos", "0", CVAR_SYSTEM | CVAR_BOOL, "Write demo.log with debug information in it" );
idCVar idDemoFile::com_compressDemos( "com_compressDemos", "1", CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE, "Compression scheme for demo files\n0: None (Fast, large files)\n1: LZW (Fast to compress, Fast to decompress, medium/small files)\n2: LZSS (Slow to compress, Fast to decompress, small files)\n3: Huffman (Fast to compress, Slow to decompress, medium files)\nSee also: The 'CompressDemo' command" );
idCVar idDemoFile::com_preloadDemos( "com_preloadDemos", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_ARCHIVE, "Load the whole demo in to RAM before running it" );
#define DEMO_MAGIC GAME_NAME " RDEMO"
/*
================
idDemoFile::idDemoFile
================
*/
idDemoFile::idDemoFile() {
f = NULL;
fLog = NULL;
log = false;
fileImage = NULL;
compressor = NULL;
writing = false;
}
/*
================
idDemoFile::~idDemoFile
================
*/
idDemoFile::~idDemoFile() {
Close();
}
/*
================
idDemoFile::AllocCompressor
================
*/
idCompressor *idDemoFile::AllocCompressor( int type ) {
switch ( type ) {
case 0: return idCompressor::AllocNoCompression();
default:
case 1: return idCompressor::AllocLZW();
case 2: return idCompressor::AllocLZSS();
case 3: return idCompressor::AllocHuffman();
}
}
/*
================
idDemoFile::OpenForReading
================
*/
bool idDemoFile::OpenForReading( const char *fileName ) {
static const int magicLen = sizeof(DEMO_MAGIC) / sizeof(DEMO_MAGIC[0]);
char magicBuffer[magicLen];
int compression;
int fileLength;
Close();
f = fileSystem->OpenFileRead( fileName );
if ( !f ) {
return false;
}
fileLength = f->Length();
if ( com_preloadDemos.GetBool() ) {
fileImage = (byte *)Mem_Alloc( fileLength );
f->Read( fileImage, fileLength );
fileSystem->CloseFile( f );
f = new idFile_Memory( va( "preloaded(%s)", fileName ), (const char *)fileImage, fileLength );
}
if ( com_logDemos.GetBool() ) {
fLog = fileSystem->OpenFileWrite( "demoread.log" );
}
writing = false;
f->Read(magicBuffer, magicLen);
if ( memcmp(magicBuffer, DEMO_MAGIC, magicLen) == 0 ) {
f->ReadInt( compression );
} else {
// Ideally we would error out if the magic string isn't there,
// but for backwards compatibility we are going to assume it's just an uncompressed demo file
compression = 0;
f->Rewind();
}
compressor = AllocCompressor( compression );
compressor->Init( f, false, 8 );
return true;
}
/*
================
idDemoFile::SetLog
================
*/
void idDemoFile::SetLog(bool b, const char *p) {
log = b;
if (p) {
logStr = p;
}
}
/*
================
idDemoFile::Log
================
*/
void idDemoFile::Log(const char *p) {
if ( fLog && p && *p ) {
fLog->Write( p, strlen(p) );
}
}
/*
================
idDemoFile::OpenForWriting
================
*/
bool idDemoFile::OpenForWriting( const char *fileName ) {
Close();
f = fileSystem->OpenFileWrite( fileName );
if ( f == NULL ) {
return false;
}
if ( com_logDemos.GetBool() ) {
fLog = fileSystem->OpenFileWrite( "demowrite.log" );
}
writing = true;
f->Write(DEMO_MAGIC, sizeof(DEMO_MAGIC));
f->WriteInt( com_compressDemos.GetInteger() );
f->Flush();
compressor = AllocCompressor( com_compressDemos.GetInteger() );
compressor->Init( f, true, 8 );
return true;
}
/*
================
idDemoFile::Close
================
*/
void idDemoFile::Close() {
if ( writing && compressor ) {
compressor->FinishCompress();
}
if ( f ) {
fileSystem->CloseFile( f );
f = NULL;
}
if ( fLog ) {
fileSystem->CloseFile( fLog );
fLog = NULL;
}
if ( fileImage ) {
Mem_Free( fileImage );
fileImage = NULL;
}
if ( compressor ) {
delete compressor;
compressor = NULL;
}
demoStrings.DeleteContents( true );
}
/*
================
idDemoFile::ReadHashString
================
*/
const char *idDemoFile::ReadHashString() {
int index;
if ( log && fLog ) {
const char *text = va( "%s > Reading hash string\n", logStr.c_str() );
fLog->Write( text, strlen( text ) );
}
ReadInt( index );
if ( index == -1 ) {
// read a new string for the table
idStr *str = new idStr;
idStr data;
ReadString( data );
*str = data;
demoStrings.Append( str );
return *str;
}
if ( index < -1 || index >= demoStrings.Num() ) {
Close();
common->Error( "demo hash index out of range" );
}
return demoStrings[index]->c_str();
}
/*
================
idDemoFile::WriteHashString
================
*/
void idDemoFile::WriteHashString( const char *str ) {
if ( log && fLog ) {
const char *text = va( "%s > Writing hash string\n", logStr.c_str() );
fLog->Write( text, strlen( text ) );
}
// see if it is already in the has table
for ( int i = 0 ; i < demoStrings.Num() ; i++ ) {
if ( !strcmp( demoStrings[i]->c_str(), str ) ) {
WriteInt( i );
return;
}
}
// add it to our table and the demo table
idStr *copy = new idStr( str );
//common->Printf( "hash:%i = %s\n", demoStrings.Num(), str );
demoStrings.Append( copy );
int cmd = -1;
WriteInt( cmd );
WriteString( str );
}
/*
================
idDemoFile::ReadDict
================
*/
void idDemoFile::ReadDict( idDict &dict ) {
int i, c;
idStr key, val;
dict.Clear();
ReadInt( c );
for ( i = 0; i < c; i++ ) {
key = ReadHashString();
val = ReadHashString();
dict.Set( key, val );
}
}
/*
================
idDemoFile::WriteDict
================
*/
void idDemoFile::WriteDict( const idDict &dict ) {
int i, c;
c = dict.GetNumKeyVals();
WriteInt( c );
for ( i = 0; i < c; i++ ) {
WriteHashString( dict.GetKeyVal( i )->GetKey() );
WriteHashString( dict.GetKeyVal( i )->GetValue() );
}
}
/*
================
idDemoFile::Read
================
*/
int idDemoFile::Read( void *buffer, int len ) {
int read = compressor->Read( buffer, len );
if ( read == 0 && len >= 4 ) {
*(demoSystem_t *)buffer = DS_FINISHED;
}
return read;
}
/*
================
idDemoFile::Write
================
*/
int idDemoFile::Write( const void *buffer, int len ) {
return compressor->Write( buffer, len );
}

88
neo/framework/DemoFile.h Normal file
View File

@@ -0,0 +1,88 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __DEMOFILE_H__
#define __DEMOFILE_H__
/*
===============================================================================
Demo file
===============================================================================
*/
typedef enum {
DS_FINISHED,
DS_RENDER,
DS_SOUND,
DS_VERSION
} demoSystem_t;
class idDemoFile : public idFile {
public:
idDemoFile();
~idDemoFile();
const char * GetName( void ) { return (f?f->GetName():""); }
const char * GetFullPath( void ) { return (f?f->GetFullPath():""); }
void SetLog( bool b, const char *p );
void Log( const char *p );
bool OpenForReading( const char *fileName );
bool OpenForWriting( const char *fileName );
void Close();
const char * ReadHashString();
void WriteHashString( const char *str );
void ReadDict( idDict &dict );
void WriteDict( const idDict &dict );
int Read( void *buffer, int len );
int Write( const void *buffer, int len );
private:
static idCompressor *AllocCompressor( int type );
bool writing;
byte * fileImage;
idFile * f;
idCompressor * compressor;
idList<idStr*> demoStrings;
idFile * fLog;
bool log;
idStr logStr;
static idCVar com_logDemos;
static idCVar com_compressDemos;
static idCVar com_preloadDemos;
};
#endif /* !__DEMOFILE_H__ */

604
neo/framework/EditField.cpp Normal file
View File

@@ -0,0 +1,604 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
static autoComplete_t globalAutoComplete;
/*
===============
FindMatches
===============
*/
static void FindMatches( const char *s ) {
int i;
if ( idStr::Icmpn( s, globalAutoComplete.completionString, strlen( globalAutoComplete.completionString ) ) != 0 ) {
return;
}
globalAutoComplete.matchCount++;
if ( globalAutoComplete.matchCount == 1 ) {
idStr::Copynz( globalAutoComplete.currentMatch, s, sizeof( globalAutoComplete.currentMatch ) );
return;
}
// cut currentMatch to the amount common with s
for ( i = 0; s[i]; i++ ) {
if ( tolower( globalAutoComplete.currentMatch[i] ) != tolower( s[i] ) ) {
globalAutoComplete.currentMatch[i] = 0;
break;
}
}
globalAutoComplete.currentMatch[i] = 0;
}
/*
===============
FindIndexMatch
===============
*/
static void FindIndexMatch( const char *s ) {
if ( idStr::Icmpn( s, globalAutoComplete.completionString, strlen( globalAutoComplete.completionString ) ) != 0 ) {
return;
}
if( globalAutoComplete.findMatchIndex == globalAutoComplete.matchIndex ) {
idStr::Copynz( globalAutoComplete.currentMatch, s, sizeof( globalAutoComplete.currentMatch ) );
}
globalAutoComplete.findMatchIndex++;
}
/*
===============
PrintMatches
===============
*/
static void PrintMatches( const char *s ) {
if ( idStr::Icmpn( s, globalAutoComplete.currentMatch, strlen( globalAutoComplete.currentMatch ) ) == 0 ) {
common->Printf( " %s\n", s );
}
}
/*
===============
PrintCvarMatches
===============
*/
static void PrintCvarMatches( const char *s ) {
if ( idStr::Icmpn( s, globalAutoComplete.currentMatch, strlen( globalAutoComplete.currentMatch ) ) == 0 ) {
common->Printf( " %s" S_COLOR_WHITE " = \"%s\"\n", s, cvarSystem->GetCVarString( s ) );
}
}
/*
===============
idEditField::idEditField
===============
*/
idEditField::idEditField() {
widthInChars = 0;
Clear();
}
/*
===============
idEditField::~idEditField
===============
*/
idEditField::~idEditField() {
}
/*
===============
idEditField::Clear
===============
*/
void idEditField::Clear( void ) {
buffer[0] = 0;
cursor = 0;
scroll = 0;
autoComplete.length = 0;
autoComplete.valid = false;
}
/*
===============
idEditField::SetWidthInChars
===============
*/
void idEditField::SetWidthInChars( int w ) {
assert( w <= MAX_EDIT_LINE );
widthInChars = w;
}
/*
===============
idEditField::SetCursor
===============
*/
void idEditField::SetCursor( int c ) {
assert( c <= MAX_EDIT_LINE );
cursor = c;
}
/*
===============
idEditField::GetCursor
===============
*/
int idEditField::GetCursor( void ) const {
return cursor;
}
/*
===============
idEditField::ClearAutoComplete
===============
*/
void idEditField::ClearAutoComplete( void ) {
if ( autoComplete.length > 0 && autoComplete.length <= (int) strlen( buffer ) ) {
buffer[autoComplete.length] = '\0';
if ( cursor > autoComplete.length ) {
cursor = autoComplete.length;
}
}
autoComplete.length = 0;
autoComplete.valid = false;
}
/*
===============
idEditField::GetAutoCompleteLength
===============
*/
int idEditField::GetAutoCompleteLength( void ) const {
return autoComplete.length;
}
/*
===============
idEditField::AutoComplete
===============
*/
void idEditField::AutoComplete( void ) {
char completionArgString[MAX_EDIT_LINE];
idCmdArgs args;
if ( !autoComplete.valid ) {
args.TokenizeString( buffer, false );
idStr::Copynz( autoComplete.completionString, args.Argv( 0 ), sizeof( autoComplete.completionString ) );
idStr::Copynz( completionArgString, args.Args(), sizeof( completionArgString ) );
autoComplete.matchCount = 0;
autoComplete.matchIndex = 0;
autoComplete.currentMatch[0] = 0;
if ( strlen( autoComplete.completionString ) == 0 ) {
return;
}
globalAutoComplete = autoComplete;
cmdSystem->CommandCompletion( FindMatches );
cvarSystem->CommandCompletion( FindMatches );
autoComplete = globalAutoComplete;
if ( autoComplete.matchCount == 0 ) {
return; // no matches
}
// when there's only one match or there's an argument
if ( autoComplete.matchCount == 1 || completionArgString[0] != '\0' ) {
/// try completing arguments
idStr::Append( autoComplete.completionString, sizeof( autoComplete.completionString ), " " );
idStr::Append( autoComplete.completionString, sizeof( autoComplete.completionString ), completionArgString );
autoComplete.matchCount = 0;
globalAutoComplete = autoComplete;
cmdSystem->ArgCompletion( autoComplete.completionString, FindMatches );
cvarSystem->ArgCompletion( autoComplete.completionString, FindMatches );
autoComplete = globalAutoComplete;
idStr::snPrintf( buffer, sizeof( buffer ), "%s", autoComplete.currentMatch );
if ( autoComplete.matchCount == 0 ) {
// no argument matches
idStr::Append( buffer, sizeof( buffer ), " " );
idStr::Append( buffer, sizeof( buffer ), completionArgString );
SetCursor( strlen( buffer ) );
return;
}
} else {
// multiple matches, complete to shortest
idStr::snPrintf( buffer, sizeof( buffer ), "%s", autoComplete.currentMatch );
if ( strlen( completionArgString ) ) {
idStr::Append( buffer, sizeof( buffer ), " " );
idStr::Append( buffer, sizeof( buffer ), completionArgString );
}
}
autoComplete.length = strlen( buffer );
autoComplete.valid = ( autoComplete.matchCount != 1 );
SetCursor( autoComplete.length );
common->Printf( "]%s\n", buffer );
// run through again, printing matches
globalAutoComplete = autoComplete;
cmdSystem->CommandCompletion( PrintMatches );
cmdSystem->ArgCompletion( autoComplete.completionString, PrintMatches );
cvarSystem->CommandCompletion( PrintCvarMatches );
cvarSystem->ArgCompletion( autoComplete.completionString, PrintMatches );
} else if ( autoComplete.matchCount != 1 ) {
// get the next match and show instead
autoComplete.matchIndex++;
if ( autoComplete.matchIndex == autoComplete.matchCount ) {
autoComplete.matchIndex = 0;
}
autoComplete.findMatchIndex = 0;
globalAutoComplete = autoComplete;
cmdSystem->CommandCompletion( FindIndexMatch );
cmdSystem->ArgCompletion( autoComplete.completionString, FindIndexMatch );
cvarSystem->CommandCompletion( FindIndexMatch );
cvarSystem->ArgCompletion( autoComplete.completionString, FindIndexMatch );
autoComplete = globalAutoComplete;
// and print it
idStr::snPrintf( buffer, sizeof( buffer ), autoComplete.currentMatch );
if ( autoComplete.length > (int)strlen( buffer ) ) {
autoComplete.length = strlen( buffer );
}
SetCursor( autoComplete.length );
}
}
/*
===============
idEditField::CharEvent
===============
*/
void idEditField::CharEvent( int ch ) {
int len;
if ( ch == 'v' - 'a' + 1 ) { // ctrl-v is paste
Paste();
return;
}
if ( ch == 'c' - 'a' + 1 ) { // ctrl-c clears the field
Clear();
return;
}
len = strlen( buffer );
if ( ch == 'h' - 'a' + 1 || ch == K_BACKSPACE ) { // ctrl-h is backspace
if ( cursor > 0 ) {
memmove( buffer + cursor - 1, buffer + cursor, len + 1 - cursor );
cursor--;
if ( cursor < scroll ) {
scroll--;
}
}
return;
}
if ( ch == 'a' - 'a' + 1 ) { // ctrl-a is home
cursor = 0;
scroll = 0;
return;
}
if ( ch == 'e' - 'a' + 1 ) { // ctrl-e is end
cursor = len;
scroll = cursor - widthInChars;
return;
}
//
// ignore any other non printable chars
//
if ( ch < 32 ) {
return;
}
if ( idKeyInput::GetOverstrikeMode() ) {
if ( cursor == MAX_EDIT_LINE - 1 ) {
return;
}
buffer[cursor] = ch;
cursor++;
} else { // insert mode
if ( len == MAX_EDIT_LINE - 1 ) {
return; // all full
}
memmove( buffer + cursor + 1, buffer + cursor, len + 1 - cursor );
buffer[cursor] = ch;
cursor++;
}
if ( cursor >= widthInChars ) {
scroll++;
}
if ( cursor == len + 1 ) {
buffer[cursor] = 0;
}
}
/*
===============
idEditField::KeyDownEvent
===============
*/
void idEditField::KeyDownEvent( int key ) {
int len;
// shift-insert is paste
if ( ( ( key == K_INS ) || ( key == K_KP_INS ) ) && idKeyInput::IsDown( K_SHIFT ) ) {
ClearAutoComplete();
Paste();
return;
}
len = strlen( buffer );
if ( key == K_DEL ) {
if ( autoComplete.length ) {
ClearAutoComplete();
} else if ( cursor < len ) {
memmove( buffer + cursor, buffer + cursor + 1, len - cursor );
}
return;
}
if ( key == K_RIGHTARROW ) {
if ( idKeyInput::IsDown( K_CTRL ) ) {
// skip to next word
while( ( cursor < len ) && ( buffer[ cursor ] != ' ' ) ) {
cursor++;
}
while( ( cursor < len ) && ( buffer[ cursor ] == ' ' ) ) {
cursor++;
}
} else {
cursor++;
}
if ( cursor > len ) {
cursor = len;
}
if ( cursor >= scroll + widthInChars ) {
scroll = cursor - widthInChars + 1;
}
if ( autoComplete.length > 0 ) {
autoComplete.length = cursor;
}
return;
}
if ( key == K_LEFTARROW ) {
if ( idKeyInput::IsDown( K_CTRL ) ) {
// skip to previous word
while( ( cursor > 0 ) && ( buffer[ cursor - 1 ] == ' ' ) ) {
cursor--;
}
while( ( cursor > 0 ) && ( buffer[ cursor - 1 ] != ' ' ) ) {
cursor--;
}
} else {
cursor--;
}
if ( cursor < 0 ) {
cursor = 0;
}
if ( cursor < scroll ) {
scroll = cursor;
}
if ( autoComplete.length ) {
autoComplete.length = cursor;
}
return;
}
if ( key == K_HOME || ( tolower( key ) == 'a' && idKeyInput::IsDown( K_CTRL ) ) ) {
cursor = 0;
scroll = 0;
if ( autoComplete.length ) {
autoComplete.length = cursor;
autoComplete.valid = false;
}
return;
}
if ( key == K_END || ( tolower( key ) == 'e' && idKeyInput::IsDown( K_CTRL ) ) ) {
cursor = len;
if ( cursor >= scroll + widthInChars ) {
scroll = cursor - widthInChars + 1;
}
if ( autoComplete.length ) {
autoComplete.length = cursor;
autoComplete.valid = false;
}
return;
}
if ( key == K_INS ) {
idKeyInput::SetOverstrikeMode( !idKeyInput::GetOverstrikeMode() );
return;
}
// clear autocompletion buffer on normal key input
if ( key != K_CAPSLOCK && key != K_ALT && key != K_CTRL && key != K_SHIFT ) {
ClearAutoComplete();
}
}
/*
===============
idEditField::Paste
===============
*/
void idEditField::Paste( void ) {
char *cbd;
int pasteLen, i;
cbd = Sys_GetClipboardData();
if ( !cbd ) {
return;
}
// send as if typed, so insert / overstrike works properly
pasteLen = strlen( cbd );
for ( i = 0; i < pasteLen; i++ ) {
CharEvent( cbd[i] );
}
Mem_Free( cbd );
}
/*
===============
idEditField::GetBuffer
===============
*/
char *idEditField::GetBuffer( void ) {
return buffer;
}
/*
===============
idEditField::SetBuffer
===============
*/
void idEditField::SetBuffer( const char *buf ) {
Clear();
idStr::Copynz( buffer, buf, sizeof( buffer ) );
SetCursor( strlen( buffer ) );
}
/*
===============
idEditField::Draw
===============
*/
void idEditField::Draw( int x, int y, int width, bool showCursor, const idMaterial *shader ) {
int len;
int drawLen;
int prestep;
int cursorChar;
char str[MAX_EDIT_LINE];
int size;
size = SMALLCHAR_WIDTH;
drawLen = widthInChars;
len = strlen( buffer ) + 1;
// guarantee that cursor will be visible
if ( len <= drawLen ) {
prestep = 0;
} else {
if ( scroll + drawLen > len ) {
scroll = len - drawLen;
if ( scroll < 0 ) {
scroll = 0;
}
}
prestep = scroll;
// Skip color code
if ( idStr::IsColor( buffer + prestep ) ) {
prestep += 2;
}
if ( prestep > 0 && idStr::IsColor( buffer + prestep - 1 ) ) {
prestep++;
}
}
if ( prestep + drawLen > len ) {
drawLen = len - prestep;
}
// extract <drawLen> characters from the field at <prestep>
if ( drawLen >= MAX_EDIT_LINE ) {
common->Error( "drawLen >= MAX_EDIT_LINE" );
}
memcpy( str, buffer + prestep, drawLen );
str[ drawLen ] = 0;
// draw it
renderSystem->DrawSmallStringExt( x, y, str, colorWhite, false, shader );
// draw the cursor
if ( !showCursor ) {
return;
}
if ( (int)( com_ticNumber >> 4 ) & 1 ) {
return; // off blink
}
if ( idKeyInput::GetOverstrikeMode() ) {
cursorChar = 11;
} else {
cursorChar = 10;
}
// Move the cursor back to account for color codes
for ( int i = 0; i<cursor; i++ ) {
if ( idStr::IsColor( &str[i] ) ) {
i++;
prestep += 2;
}
}
renderSystem->DrawSmallChar( x + ( cursor - prestep ) * size, y, cursorChar, shader );
}

79
neo/framework/EditField.h Normal file
View File

@@ -0,0 +1,79 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __EDITFIELD_H__
#define __EDITFIELD_H__
/*
===============================================================================
Edit field
===============================================================================
*/
const int MAX_EDIT_LINE = 256;
typedef struct autoComplete_s {
bool valid;
int length;
char completionString[MAX_EDIT_LINE];
char currentMatch[MAX_EDIT_LINE];
int matchCount;
int matchIndex;
int findMatchIndex;
} autoComplete_t;
class idEditField {
public:
idEditField();
~idEditField();
void Clear( void );
void SetWidthInChars( int w );
void SetCursor( int c );
int GetCursor( void ) const;
void ClearAutoComplete( void );
int GetAutoCompleteLength( void ) const;
void AutoComplete( void );
void CharEvent( int c );
void KeyDownEvent( int key );
void Paste( void );
char * GetBuffer( void );
void Draw( int x, int y, int width, bool showCursor, const idMaterial *material );
void SetBuffer( const char *buffer );
private:
int cursor;
int scroll;
int widthInChars;
char buffer[MAX_EDIT_LINE];
autoComplete_t autoComplete;
};
#endif /* !__EDITFIELD_H__ */

274
neo/framework/EventLoop.cpp Normal file
View File

@@ -0,0 +1,274 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
idCVar idEventLoop::com_journal( "com_journal", "0", CVAR_INIT|CVAR_SYSTEM, "1 = record journal, 2 = play back journal", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
idEventLoop eventLoopLocal;
idEventLoop *eventLoop = &eventLoopLocal;
/*
=================
idEventLoop::idEventLoop
=================
*/
idEventLoop::idEventLoop( void ) {
com_journalFile = NULL;
com_journalDataFile = NULL;
initialTimeOffset = 0;
}
/*
=================
idEventLoop::~idEventLoop
=================
*/
idEventLoop::~idEventLoop( void ) {
}
/*
=================
idEventLoop::GetRealEvent
=================
*/
sysEvent_t idEventLoop::GetRealEvent( void ) {
int r;
sysEvent_t ev;
// either get an event from the system or the journal file
if ( com_journal.GetInteger() == 2 ) {
r = com_journalFile->Read( &ev, sizeof(ev) );
if ( r != sizeof(ev) ) {
common->FatalError( "Error reading from journal file" );
}
if ( ev.evPtrLength ) {
ev.evPtr = Mem_ClearedAlloc( ev.evPtrLength );
r = com_journalFile->Read( ev.evPtr, ev.evPtrLength );
if ( r != ev.evPtrLength ) {
common->FatalError( "Error reading from journal file" );
}
}
} else {
ev = Sys_GetEvent();
// write the journal value out if needed
if ( com_journal.GetInteger() == 1 ) {
r = com_journalFile->Write( &ev, sizeof(ev) );
if ( r != sizeof(ev) ) {
common->FatalError( "Error writing to journal file" );
}
if ( ev.evPtrLength ) {
r = com_journalFile->Write( ev.evPtr, ev.evPtrLength );
if ( r != ev.evPtrLength ) {
common->FatalError( "Error writing to journal file" );
}
}
}
}
return ev;
}
/*
=================
idEventLoop::PushEvent
=================
*/
void idEventLoop::PushEvent( sysEvent_t *event ) {
sysEvent_t *ev;
static bool printedWarning;
ev = &com_pushedEvents[ com_pushedEventsHead & (MAX_PUSHED_EVENTS-1) ];
if ( com_pushedEventsHead - com_pushedEventsTail >= MAX_PUSHED_EVENTS ) {
// don't print the warning constantly, or it can give time for more...
if ( !printedWarning ) {
printedWarning = true;
common->Printf( "WARNING: Com_PushEvent overflow\n" );
}
if ( ev->evPtr ) {
Mem_Free( ev->evPtr );
}
com_pushedEventsTail++;
} else {
printedWarning = false;
}
*ev = *event;
com_pushedEventsHead++;
}
/*
=================
idEventLoop::GetEvent
=================
*/
sysEvent_t idEventLoop::GetEvent( void ) {
if ( com_pushedEventsHead > com_pushedEventsTail ) {
com_pushedEventsTail++;
return com_pushedEvents[ (com_pushedEventsTail-1) & (MAX_PUSHED_EVENTS-1) ];
}
return GetRealEvent();
}
/*
=================
idEventLoop::ProcessEvent
=================
*/
void idEventLoop::ProcessEvent( sysEvent_t ev ) {
// track key up / down states
if ( ev.evType == SE_KEY ) {
idKeyInput::PreliminaryKeyEvent( ev.evValue, ( ev.evValue2 != 0 ) );
}
if ( ev.evType == SE_CONSOLE ) {
// from a text console outside the game window
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, (char *)ev.evPtr );
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" );
} else {
session->ProcessEvent( &ev );
}
// free any block data
if ( ev.evPtr ) {
Mem_Free( ev.evPtr );
}
}
/*
===============
idEventLoop::RunEventLoop
===============
*/
int idEventLoop::RunEventLoop( bool commandExecution ) {
sysEvent_t ev;
while ( 1 ) {
if ( commandExecution ) {
// execute any bound commands before processing another event
cmdSystem->ExecuteCommandBuffer();
}
ev = GetEvent();
// if no more events are available
if ( ev.evType == SE_NONE ) {
return 0;
}
ProcessEvent( ev );
}
return 0; // never reached
}
/*
=============
idEventLoop::Init
=============
*/
void idEventLoop::Init( void ) {
initialTimeOffset = Sys_Milliseconds();
common->StartupVariable( "journal", false );
if ( com_journal.GetInteger() == 1 ) {
common->Printf( "Journaling events\n" );
com_journalFile = fileSystem->OpenFileWrite( "journal.dat" );
com_journalDataFile = fileSystem->OpenFileWrite( "journaldata.dat" );
} else if ( com_journal.GetInteger() == 2 ) {
common->Printf( "Replaying journaled events\n" );
com_journalFile = fileSystem->OpenFileRead( "journal.dat" );
com_journalDataFile = fileSystem->OpenFileRead( "journaldata.dat" );
}
if ( !com_journalFile || !com_journalDataFile ) {
com_journal.SetInteger( 0 );
com_journalFile = 0;
com_journalDataFile = 0;
common->Printf( "Couldn't open journal files\n" );
}
}
/*
=============
idEventLoop::Shutdown
=============
*/
void idEventLoop::Shutdown( void ) {
if ( com_journalFile ) {
fileSystem->CloseFile( com_journalFile );
com_journalFile = NULL;
}
if ( com_journalDataFile ) {
fileSystem->CloseFile( com_journalDataFile );
com_journalDataFile = NULL;
}
}
/*
================
idEventLoop::Milliseconds
Can be used for profiling, but will be journaled accurately
================
*/
int idEventLoop::Milliseconds( void ) {
#if 1 // FIXME!
return Sys_Milliseconds() - initialTimeOffset;
#else
sysEvent_t ev;
// get events and push them until we get a null event with the current time
do {
ev = Com_GetRealEvent();
if ( ev.evType != SE_NONE ) {
Com_PushEvent( &ev );
}
} while ( ev.evType != SE_NONE );
return ev.evTime;
#endif
}
/*
================
idEventLoop::JournalLevel
================
*/
int idEventLoop::JournalLevel( void ) const {
return com_journal.GetInteger();
}

88
neo/framework/EventLoop.h Normal file
View File

@@ -0,0 +1,88 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__
/*
===============================================================================
The event loop receives events from the system and dispatches them to
the various parts of the engine. The event loop also handles journaling.
The file system copies .cfg files to the journaled file.
===============================================================================
*/
const int MAX_PUSHED_EVENTS = 64;
class idEventLoop {
public:
idEventLoop( void );
~idEventLoop( void );
void Init( void );
// Closes the journal file if needed.
void Shutdown( void );
// It is possible to get an event at the beginning of a frame that
// has a time stamp lower than the last event from the previous frame.
sysEvent_t GetEvent( void );
// Dispatches all pending events and returns the current time.
int RunEventLoop( bool commandExecution = true );
// Gets the current time in a way that will be journaled properly,
// as opposed to Sys_Milliseconds(), which always reads a real timer.
int Milliseconds( void );
// Returns the journal level, 1 = record, 2 = play back.
int JournalLevel( void ) const;
// Journal file.
idFile * com_journalFile;
idFile * com_journalDataFile;
private:
// all events will have this subtracted from their time
int initialTimeOffset;
int com_pushedEventsHead, com_pushedEventsTail;
sysEvent_t com_pushedEvents[MAX_PUSHED_EVENTS];
static idCVar com_journal;
sysEvent_t GetRealEvent( void );
void ProcessEvent( sysEvent_t ev );
void PushEvent( sysEvent_t *event );
};
extern idEventLoop *eventLoop;
#endif /* !__EVENTLOOP_H__ */

1365
neo/framework/File.cpp Normal file

File diff suppressed because it is too large Load Diff

243
neo/framework/File.h Normal file
View File

@@ -0,0 +1,243 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __FILE_H__
#define __FILE_H__
/*
==============================================================
File Streams.
==============================================================
*/
// mode parm for Seek
typedef enum {
FS_SEEK_CUR,
FS_SEEK_END,
FS_SEEK_SET
} fsOrigin_t;
class idFileSystemLocal;
class idFile {
public:
virtual ~idFile( void ) {};
// Get the name of the file.
virtual const char * GetName( void );
// Get the full file path.
virtual const char * GetFullPath( void );
// Read data from the file to the buffer.
virtual int Read( void *buffer, int len );
// Write data from the buffer to the file.
virtual int Write( const void *buffer, int len );
// Returns the length of the file.
virtual int Length( void );
// Return a time value for reload operations.
virtual ID_TIME_T Timestamp( void );
// Returns offset in file.
virtual int Tell( void );
// Forces flush on files being writting to.
virtual void ForceFlush( void );
// Causes any buffered data to be written to the file.
virtual void Flush( void );
// Seek on a file.
virtual int Seek( long offset, fsOrigin_t origin );
// Go back to the beginning of the file.
virtual void Rewind( void );
// Like fprintf.
virtual int Printf( const char *fmt, ... ) id_attribute((format(printf,2,3)));
// Like fprintf but with argument pointer
virtual int VPrintf( const char *fmt, va_list arg );
// Write a string with high precision floating point numbers to the file.
virtual int WriteFloatString( const char *fmt, ... ) id_attribute((format(printf,2,3)));
// Endian portable alternatives to Read(...)
virtual int ReadInt( int &value );
virtual int ReadUnsignedInt( unsigned int &value );
virtual int ReadShort( short &value );
virtual int ReadUnsignedShort( unsigned short &value );
virtual int ReadChar( char &value );
virtual int ReadUnsignedChar( unsigned char &value );
virtual int ReadFloat( float &value );
virtual int ReadBool( bool &value );
virtual int ReadString( idStr &string );
virtual int ReadVec2( idVec2 &vec );
virtual int ReadVec3( idVec3 &vec );
virtual int ReadVec4( idVec4 &vec );
virtual int ReadVec6( idVec6 &vec );
virtual int ReadMat3( idMat3 &mat );
// Endian portable alternatives to Write(...)
virtual int WriteInt( const int value );
virtual int WriteUnsignedInt( const unsigned int value );
virtual int WriteShort( const short value );
virtual int WriteUnsignedShort( unsigned short value );
virtual int WriteChar( const char value );
virtual int WriteUnsignedChar( const unsigned char value );
virtual int WriteFloat( const float value );
virtual int WriteBool( const bool value );
virtual int WriteString( const char *string );
virtual int WriteVec2( const idVec2 &vec );
virtual int WriteVec3( const idVec3 &vec );
virtual int WriteVec4( const idVec4 &vec );
virtual int WriteVec6( const idVec6 &vec );
virtual int WriteMat3( const idMat3 &mat );
};
class idFile_Memory : public idFile {
friend class idFileSystemLocal;
public:
idFile_Memory( void ); // file for writing without name
idFile_Memory( const char *name ); // file for writing
idFile_Memory( const char *name, char *data, int length ); // file for writing
idFile_Memory( const char *name, const char *data, int length ); // file for reading
virtual ~idFile_Memory( void );
virtual const char * GetName( void ) { return name.c_str(); }
virtual const char * GetFullPath( void ) { return name.c_str(); }
virtual int Read( void *buffer, int len );
virtual int Write( const void *buffer, int len );
virtual int Length( void );
virtual ID_TIME_T Timestamp( void );
virtual int Tell( void );
virtual void ForceFlush( void );
virtual void Flush( void );
virtual int Seek( long offset, fsOrigin_t origin );
// changes memory file to read only
virtual void MakeReadOnly( void );
// clear the file
virtual void Clear( bool freeMemory = true );
// set data for reading
void SetData( const char *data, int length );
// returns const pointer to the memory buffer
const char * GetDataPtr( void ) const { return filePtr; }
// set the file granularity
void SetGranularity( int g ) { assert( g > 0 ); granularity = g; }
private:
idStr name; // name of the file
int mode; // open mode
int maxSize; // maximum size of file
int fileSize; // size of the file
int allocated; // allocated size
int granularity; // file granularity
char * filePtr; // buffer holding the file data
char * curPtr; // current read/write pointer
};
class idFile_BitMsg : public idFile {
friend class idFileSystemLocal;
public:
idFile_BitMsg( idBitMsg &msg );
idFile_BitMsg( const idBitMsg &msg );
virtual ~idFile_BitMsg( void );
virtual const char * GetName( void ) { return name.c_str(); }
virtual const char * GetFullPath( void ) { return name.c_str(); }
virtual int Read( void *buffer, int len );
virtual int Write( const void *buffer, int len );
virtual int Length( void );
virtual ID_TIME_T Timestamp( void );
virtual int Tell( void );
virtual void ForceFlush( void );
virtual void Flush( void );
virtual int Seek( long offset, fsOrigin_t origin );
private:
idStr name; // name of the file
int mode; // open mode
idBitMsg * msg;
};
class idFile_Permanent : public idFile {
friend class idFileSystemLocal;
public:
idFile_Permanent( void );
virtual ~idFile_Permanent( void );
virtual const char * GetName( void ) { return name.c_str(); }
virtual const char * GetFullPath( void ) { return fullPath.c_str(); }
virtual int Read( void *buffer, int len );
virtual int Write( const void *buffer, int len );
virtual int Length( void );
virtual ID_TIME_T Timestamp( void );
virtual int Tell( void );
virtual void ForceFlush( void );
virtual void Flush( void );
virtual int Seek( long offset, fsOrigin_t origin );
// returns file pointer
FILE * GetFilePtr( void ) { return o; }
private:
idStr name; // relative path of the file - relative path
idStr fullPath; // full file path - OS path
int mode; // open mode
int fileSize; // size of the file
FILE * o; // file handle
bool handleSync; // true if written data is immediately flushed
};
class idFile_InZip : public idFile {
friend class idFileSystemLocal;
public:
idFile_InZip( void );
virtual ~idFile_InZip( void );
virtual const char * GetName( void ) { return name.c_str(); }
virtual const char * GetFullPath( void ) { return fullPath.c_str(); }
virtual int Read( void *buffer, int len );
virtual int Write( const void *buffer, int len );
virtual int Length( void );
virtual ID_TIME_T Timestamp( void );
virtual int Tell( void );
virtual void ForceFlush( void );
virtual void Flush( void );
virtual int Seek( long offset, fsOrigin_t origin );
private:
idStr name; // name of the file in the pak
idStr fullPath; // full file path including pak file name
int zipFilePos; // zip file info position in pak
int fileSize; // size of the file
void * z; // unzip info
};
#endif /* !__FILE_H__ */

4217
neo/framework/FileSystem.cpp Normal file

File diff suppressed because it is too large Load Diff

289
neo/framework/FileSystem.h Normal file
View File

@@ -0,0 +1,289 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __FILESYSTEM_H__
#define __FILESYSTEM_H__
/*
===============================================================================
File System
No stdio calls should be used by any part of the game, because of all sorts
of directory and separator char issues. Throughout the game a forward slash
should be used as a separator. The file system takes care of the conversion
to an OS specific separator. The file system treats all file and directory
names as case insensitive.
The following cvars store paths used by the file system:
"fs_basepath" path to local install, read-only
"fs_savepath" path to config, save game, etc. files, read & write
"fs_cdpath" path to cd, read-only
"fs_devpath" path to files created during development, read & write
The base path for file saving can be set to "fs_savepath" or "fs_devpath".
===============================================================================
*/
static const ID_TIME_T FILE_NOT_FOUND_TIMESTAMP = 0xFFFFFFFF;
static const int MAX_PURE_PAKS = 128;
static const int MAX_OSPATH = 256;
// modes for OpenFileByMode. used as bit mask internally
typedef enum {
FS_READ = 0,
FS_WRITE = 1,
FS_APPEND = 2
} fsMode_t;
typedef enum {
PURE_OK, // we are good to connect as-is
PURE_RESTART, // restart required
PURE_MISSING, // pak files missing on the client
PURE_NODLL // no DLL could be extracted
} fsPureReply_t;
typedef enum {
DLTYPE_URL,
DLTYPE_FILE
} dlType_t;
typedef enum {
DL_WAIT, // waiting in the list for beginning of the download
DL_INPROGRESS, // in progress
DL_DONE, // download completed, success
DL_ABORTING, // this one can be set during a download, it will force the next progress callback to abort - then will go to DL_FAILED
DL_FAILED
} dlStatus_t;
typedef enum {
FILE_EXEC,
FILE_OPEN
} dlMime_t;
typedef enum {
FIND_NO,
FIND_YES,
FIND_ADDON
} findFile_t;
typedef struct urlDownload_s {
idStr url;
char dlerror[ MAX_STRING_CHARS ];
int dltotal;
int dlnow;
int dlstatus;
dlStatus_t status;
} urlDownload_t;
typedef struct fileDownload_s {
int position;
int length;
void * buffer;
} fileDownload_t;
typedef struct backgroundDownload_s {
struct backgroundDownload_s *next; // set by the fileSystem
dlType_t opcode;
idFile * f;
fileDownload_t file;
urlDownload_t url;
volatile bool completed;
} backgroundDownload_t;
// file list for directory listings
class idFileList {
friend class idFileSystemLocal;
public:
const char * GetBasePath( void ) const { return basePath; }
int GetNumFiles( void ) const { return list.Num(); }
const char * GetFile( int index ) const { return list[index]; }
const idStrList & GetList( void ) const { return list; }
private:
idStr basePath;
idStrList list;
};
// mod list
class idModList {
friend class idFileSystemLocal;
public:
int GetNumMods( void ) const { return mods.Num(); }
const char * GetMod( int index ) const { return mods[index]; }
const char * GetDescription( int index ) const { return descriptions[index]; }
private:
idStrList mods;
idStrList descriptions;
};
class idFileSystem {
public:
virtual ~idFileSystem() {}
// Initializes the file system.
virtual void Init( void ) = 0;
// Restarts the file system.
virtual void Restart( void ) = 0;
// Shutdown the file system.
virtual void Shutdown( bool reloading ) = 0;
// Returns true if the file system is initialized.
virtual bool IsInitialized( void ) const = 0;
// Returns true if we are doing an fs_copyfiles.
virtual bool PerformingCopyFiles( void ) const = 0;
// Returns a list of mods found along with descriptions
// 'mods' contains the directory names to be passed to fs_game
// 'descriptions' contains a free form string to be used in the UI
virtual idModList * ListMods( void ) = 0;
// Frees the given mod list
virtual void FreeModList( idModList *modList ) = 0;
// Lists files with the given extension in the given directory.
// Directory should not have either a leading or trailing '/'
// The returned files will not include any directories or '/' unless fullRelativePath is set.
// The extension must include a leading dot and may not contain wildcards.
// If extension is "/", only subdirectories will be returned.
virtual idFileList * ListFiles( const char *relativePath, const char *extension, bool sort = false, bool fullRelativePath = false, const char* gamedir = NULL ) = 0;
// Lists files in the given directory and all subdirectories with the given extension.
// Directory should not have either a leading or trailing '/'
// The returned files include a full relative path.
// The extension must include a leading dot and may not contain wildcards.
virtual idFileList * ListFilesTree( const char *relativePath, const char *extension, bool sort = false, const char* gamedir = NULL ) = 0;
// Frees the given file list.
virtual void FreeFileList( idFileList *fileList ) = 0;
// Converts a relative path to a full OS path.
virtual const char * OSPathToRelativePath( const char *OSPath ) = 0;
// Converts a full OS path to a relative path.
virtual const char * RelativePathToOSPath( const char *relativePath, const char *basePath = "fs_devpath" ) = 0;
// Builds a full OS path from the given components.
virtual const char * BuildOSPath( const char *base, const char *game, const char *relativePath ) = 0;
// Creates the given OS path for as far as it doesn't exist already.
virtual void CreateOSPath( const char *OSPath ) = 0;
// Returns true if a file is in a pak file.
virtual bool FileIsInPAK( const char *relativePath ) = 0;
// Returns a space separated string containing the checksums of all referenced pak files.
// will call SetPureServerChecksums internally to restrict itself
virtual void UpdatePureServerChecksums( void ) = 0;
// setup the mapping of OS -> game pak checksum
virtual bool UpdateGamePakChecksums( void ) = 0;
// 0-terminated list of pak checksums
// if pureChecksums[ 0 ] == 0, all data sources will be allowed
// otherwise, only pak files that match one of the checksums will be checked for files
// with the sole exception of .cfg files.
// the function tries to configure pure mode from the paks already referenced and this new list
// it returns wether the switch was successfull, and sets the missing checksums
// the process is verbosive when fs_debug 1
virtual fsPureReply_t SetPureServerChecksums( const int pureChecksums[ MAX_PURE_PAKS ], int gamePakChecksum, int missingChecksums[ MAX_PURE_PAKS ], int *missingGamePakChecksum ) = 0;
// fills a 0-terminated list of pak checksums for a client
// if OS is -1, give the current game pak checksum. if >= 0, lookup the game pak table (server only)
virtual void GetPureServerChecksums( int checksums[ MAX_PURE_PAKS ], int OS, int *gamePakChecksum ) = 0;
// before doing a restart, force the pure list and the search order
// if the given checksum list can't be completely processed and set, will error out
virtual void SetRestartChecksums( const int pureChecksums[ MAX_PURE_PAKS ], int gamePakChecksum ) = 0;
// equivalent to calling SetPureServerChecksums with an empty list
virtual void ClearPureChecksums( void ) = 0;
// get a mask of supported OSes. if not pure, returns -1
virtual int GetOSMask( void ) = 0;
// Reads a complete file.
// Returns the length of the file, or -1 on failure.
// A null buffer will just return the file length without loading.
// A null timestamp will be ignored.
// As a quick check for existance. -1 length == not present.
// A 0 byte will always be appended at the end, so string ops are safe.
// The buffer should be considered read-only, because it may be cached for other uses.
virtual int ReadFile( const char *relativePath, void **buffer, ID_TIME_T *timestamp = NULL ) = 0;
// Frees the memory allocated by ReadFile.
virtual void FreeFile( void *buffer ) = 0;
// Writes a complete file, will create any needed subdirectories.
// Returns the length of the file, or -1 on failure.
virtual int WriteFile( const char *relativePath, const void *buffer, int size, const char *basePath = "fs_savepath" ) = 0;
// Removes the given file.
virtual void RemoveFile( const char *relativePath ) = 0;
// Opens a file for reading.
virtual idFile * OpenFileRead( const char *relativePath, bool allowCopyFiles = true, const char* gamedir = NULL ) = 0;
// Opens a file for writing, will create any needed subdirectories.
virtual idFile * OpenFileWrite( const char *relativePath, const char *basePath = "fs_savepath" ) = 0;
// Opens a file for writing at the end.
virtual idFile * OpenFileAppend( const char *filename, bool sync = false, const char *basePath = "fs_basepath" ) = 0;
// Opens a file for reading, writing, or appending depending on the value of mode.
virtual idFile * OpenFileByMode( const char *relativePath, fsMode_t mode ) = 0;
// Opens a file for reading from a full OS path.
virtual idFile * OpenExplicitFileRead( const char *OSPath ) = 0;
// Opens a file for writing to a full OS path.
virtual idFile * OpenExplicitFileWrite( const char *OSPath ) = 0;
// Closes a file.
virtual void CloseFile( idFile *f ) = 0;
// Returns immediately, performing the read from a background thread.
virtual void BackgroundDownload( backgroundDownload_t *bgl ) = 0;
// resets the bytes read counter
virtual void ResetReadCount( void ) = 0;
// retrieves the current read count
virtual int GetReadCount( void ) = 0;
// adds to the read count
virtual void AddToReadCount( int c ) = 0;
// look for a dynamic module
virtual void FindDLL( const char *basename, char dllPath[ MAX_OSPATH ], bool updateChecksum ) = 0;
// case sensitive filesystems use an internal directory cache
// the cache is cleared when calling OpenFileWrite and RemoveFile
// in some cases you may need to use this directly
virtual void ClearDirCache( void ) = 0;
// is D3XP installed? even if not running it atm
virtual bool HasD3XP( void ) = 0;
// are we using D3XP content ( through a real d3xp run or through a double mod )
virtual bool RunningD3XP( void ) = 0;
// don't use for large copies - allocates a single memory block for the copy
virtual void CopyFile( const char *fromOSPath, const char *toOSPath ) = 0;
// lookup a relative path, return the size or 0 if not found
virtual int ValidateDownloadPakForChecksum( int checksum, char path[ MAX_STRING_CHARS ], bool isGamePak ) = 0;
virtual idFile * MakeTemporaryFile( void ) = 0;
// make downloaded pak files known so pure negociation works next time
virtual int AddZipFile( const char *path ) = 0;
// look for a file in the loaded paks or the addon paks
// if the file is found in addons, FS's internal structures are ready for a reloadEngine
virtual findFile_t FindFile( const char *path, bool scheduleAddons = false ) = 0;
// get map/addon decls and take into account addon paks that are not on the search list
// the decl 'name' is in the "path" entry of the dict
virtual int GetNumMaps() = 0;
virtual const idDict * GetMapDecl( int i ) = 0;
virtual void FindMapScreenshot( const char *path, char *buf, int len ) = 0;
// ignore case and seperator char distinctions
virtual bool FilenameCompare( const char *s1, const char *s2 ) const = 0;
};
extern idFileSystem * fileSystem;
#endif /* !__FILESYSTEM_H__ */

785
neo/framework/KeyInput.cpp Normal file
View File

@@ -0,0 +1,785 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
typedef struct {
char *name;
int keynum;
char *strId; // localized string id
} keyname_t;
// keys that can be set without a special name
static const char unnamedkeys[] = "*,-=./[\\]1234567890abcdefghijklmnopqrstuvwxyz";
#if MACOS_X
const char* OSX_GetLocalizedString( const char* );
#endif
// names not in this list can either be lowercase ascii, or '0xnn' hex sequences
keyname_t keynames[] =
{
{"TAB", K_TAB, "#str_07018"},
{"ENTER", K_ENTER, "#str_07019"},
{"ESCAPE", K_ESCAPE, "#str_07020"},
{"SPACE", K_SPACE, "#str_07021"},
{"BACKSPACE", K_BACKSPACE, "#str_07022"},
{"UPARROW", K_UPARROW, "#str_07023"},
{"DOWNARROW", K_DOWNARROW, "#str_07024"},
{"LEFTARROW", K_LEFTARROW, "#str_07025"},
{"RIGHTARROW", K_RIGHTARROW, "#str_07026"},
{"ALT", K_ALT, "#str_07027"},
{"RIGHTALT", K_RIGHT_ALT, "#str_07027"},
{"CTRL", K_CTRL, "#str_07028"},
{"SHIFT", K_SHIFT, "#str_07029"},
{"LWIN", K_LWIN, "#str_07030"},
{"RWIN", K_RWIN, "#str_07031"},
{"MENU", K_MENU, "#str_07032"},
{"COMMAND", K_COMMAND, "#str_07033"},
{"CAPSLOCK", K_CAPSLOCK, "#str_07034"},
{"SCROLL", K_SCROLL, "#str_07035"},
{"PRINTSCREEN", K_PRINT_SCR, "#str_07179"},
{"F1", K_F1, "#str_07036"},
{"F2", K_F2, "#str_07037"},
{"F3", K_F3, "#str_07038"},
{"F4", K_F4, "#str_07039"},
{"F5", K_F5, "#str_07040"},
{"F6", K_F6, "#str_07041"},
{"F7", K_F7, "#str_07042"},
{"F8", K_F8, "#str_07043"},
{"F9", K_F9, "#str_07044"},
{"F10", K_F10, "#str_07045"},
{"F11", K_F11, "#str_07046"},
{"F12", K_F12, "#str_07047"},
{"INS", K_INS, "#str_07048"},
{"DEL", K_DEL, "#str_07049"},
{"PGDN", K_PGDN, "#str_07050"},
{"PGUP", K_PGUP, "#str_07051"},
{"HOME", K_HOME, "#str_07052"},
{"END", K_END, "#str_07053"},
{"MOUSE1", K_MOUSE1, "#str_07054"},
{"MOUSE2", K_MOUSE2, "#str_07055"},
{"MOUSE3", K_MOUSE3, "#str_07056"},
{"MOUSE4", K_MOUSE4, "#str_07057"},
{"MOUSE5", K_MOUSE5, "#str_07058"},
{"MOUSE6", K_MOUSE6, "#str_07059"},
{"MOUSE7", K_MOUSE7, "#str_07060"},
{"MOUSE8", K_MOUSE8, "#str_07061"},
{"MWHEELUP", K_MWHEELUP, "#str_07131"},
{"MWHEELDOWN", K_MWHEELDOWN, "#str_07132"},
{"JOY1", K_JOY1, "#str_07062"},
{"JOY2", K_JOY2, "#str_07063"},
{"JOY3", K_JOY3, "#str_07064"},
{"JOY4", K_JOY4, "#str_07065"},
{"JOY5", K_JOY5, "#str_07066"},
{"JOY6", K_JOY6, "#str_07067"},
{"JOY7", K_JOY7, "#str_07068"},
{"JOY8", K_JOY8, "#str_07069"},
{"JOY9", K_JOY9, "#str_07070"},
{"JOY10", K_JOY10, "#str_07071"},
{"JOY11", K_JOY11, "#str_07072"},
{"JOY12", K_JOY12, "#str_07073"},
{"JOY13", K_JOY13, "#str_07074"},
{"JOY14", K_JOY14, "#str_07075"},
{"JOY15", K_JOY15, "#str_07076"},
{"JOY16", K_JOY16, "#str_07077"},
{"JOY17", K_JOY17, "#str_07078"},
{"JOY18", K_JOY18, "#str_07079"},
{"JOY19", K_JOY19, "#str_07080"},
{"JOY20", K_JOY20, "#str_07081"},
{"JOY21", K_JOY21, "#str_07082"},
{"JOY22", K_JOY22, "#str_07083"},
{"JOY23", K_JOY23, "#str_07084"},
{"JOY24", K_JOY24, "#str_07085"},
{"JOY25", K_JOY25, "#str_07086"},
{"JOY26", K_JOY26, "#str_07087"},
{"JOY27", K_JOY27, "#str_07088"},
{"JOY28", K_JOY28, "#str_07089"},
{"JOY29", K_JOY29, "#str_07090"},
{"JOY30", K_JOY30, "#str_07091"},
{"JOY31", K_JOY31, "#str_07092"},
{"JOY32", K_JOY32, "#str_07093"},
{"AUX1", K_AUX1, "#str_07094"},
{"AUX2", K_AUX2, "#str_07095"},
{"AUX3", K_AUX3, "#str_07096"},
{"AUX4", K_AUX4, "#str_07097"},
{"AUX5", K_AUX5, "#str_07098"},
{"AUX6", K_AUX6, "#str_07099"},
{"AUX7", K_AUX7, "#str_07100"},
{"AUX8", K_AUX8, "#str_07101"},
{"AUX9", K_AUX9, "#str_07102"},
{"AUX10", K_AUX10, "#str_07103"},
{"AUX11", K_AUX11, "#str_07104"},
{"AUX12", K_AUX12, "#str_07105"},
{"AUX13", K_AUX13, "#str_07106"},
{"AUX14", K_AUX14, "#str_07107"},
{"AUX15", K_AUX15, "#str_07108"},
{"AUX16", K_AUX16, "#str_07109"},
{"KP_HOME", K_KP_HOME, "#str_07110"},
{"KP_UPARROW", K_KP_UPARROW, "#str_07111"},
{"KP_PGUP", K_KP_PGUP, "#str_07112"},
{"KP_LEFTARROW", K_KP_LEFTARROW, "#str_07113"},
{"KP_5", K_KP_5, "#str_07114"},
{"KP_RIGHTARROW", K_KP_RIGHTARROW, "#str_07115"},
{"KP_END", K_KP_END, "#str_07116"},
{"KP_DOWNARROW", K_KP_DOWNARROW, "#str_07117"},
{"KP_PGDN", K_KP_PGDN, "#str_07118"},
{"KP_ENTER", K_KP_ENTER, "#str_07119"},
{"KP_INS", K_KP_INS, "#str_07120"},
{"KP_DEL", K_KP_DEL, "#str_07121"},
{"KP_SLASH", K_KP_SLASH, "#str_07122"},
{"KP_MINUS", K_KP_MINUS, "#str_07123"},
{"KP_PLUS", K_KP_PLUS, "#str_07124"},
{"KP_NUMLOCK", K_KP_NUMLOCK, "#str_07125"},
{"KP_STAR", K_KP_STAR, "#str_07126"},
{"KP_EQUALS", K_KP_EQUALS, "#str_07127"},
{"PAUSE", K_PAUSE, "#str_07128"},
{"SEMICOLON", ';', "#str_07129"}, // because a raw semicolon separates commands
{"APOSTROPHE", '\'', "#str_07130"}, // because a raw apostrophe messes with parsing
{NULL, 0, NULL}
};
static const int MAX_KEYS = 256;
class idKey {
public:
idKey( void ) { down = false; repeats = 0; usercmdAction = 0; }
bool down;
int repeats; // if > 1, it is autorepeating
idStr binding;
int usercmdAction; // for testing by the asyncronous usercmd generation
};
bool key_overstrikeMode = false;
idKey * keys = NULL;
#define ID_DOOM_LEGACY
#ifdef ID_DOOM_LEGACY
char * cheatCodes[] = {
"iddqd", // Invincibility
"idkfa", // All weapons, keys, ammo, and 200% armor
"idfa", // Reset ammunition
"idspispopd", // Walk through walls
"idclip", // Walk through walls
"idchoppers", // Chainsaw
/*
"idbeholds", // Berserker strength
"idbeholdv", // Temporary invincibility
"idbeholdi", // Temporary invisibility
"idbeholda", // Full automap
"idbeholdr", // Anti-radiation suit
"idbeholdl", // Light amplification visor
"idclev", // Level select
"iddt", // Toggle full map; full map and objects; normal map
"idmypos", // Display coordinates and heading
"idmus", // Change music to indicated level
"fhhall", // Kill all enemies in level
"fhshh", // Invisible to enemies until attack
*/
NULL
};
char lastKeys[32];
int lastKeyIndex;
#endif
/*
===================
idKeyInput::ArgCompletion_KeyName
===================
*/
void idKeyInput::ArgCompletion_KeyName( const idCmdArgs &args, void(*callback)( const char *s ) ) {
keyname_t *kn;
int i;
for( i = 0; i < sizeof( unnamedkeys ) - 1; i++ ) {
callback( va( "%s %c", args.Argv( 0 ), unnamedkeys[ i ] ) );
}
for ( kn = keynames; kn->name; kn++ ) {
callback( va( "%s %s", args.Argv( 0 ), kn->name ) );
}
}
/*
===================
idKeyInput::GetOverstrikeMode
===================
*/
bool idKeyInput::GetOverstrikeMode( void ) {
return key_overstrikeMode;
}
/*
===================
idKeyInput::SetOverstrikeMode
===================
*/
void idKeyInput::SetOverstrikeMode( bool state ) {
key_overstrikeMode = state;
}
/*
===================
idKeyInput::IsDown
===================
*/
bool idKeyInput::IsDown( int keynum ) {
if ( keynum == -1 ) {
return false;
}
return keys[keynum].down;
}
/*
===================
idKeyInput::StringToKeyNum
Returns a key number to be used to index keys[] by looking at
the given string. Single ascii characters return themselves, while
the K_* names are matched up.
0x11 will be interpreted as raw hex, which will allow new controlers
to be configured even if they don't have defined names.
===================
*/
int idKeyInput::StringToKeyNum( const char *str ) {
keyname_t *kn;
if ( !str || !str[0] ) {
return -1;
}
if ( !str[1] ) {
return (unsigned char)(str[0]);
}
// check for hex code
if ( str[0] == '0' && str[1] == 'x' && strlen( str ) == 4 ) {
int n1, n2;
n1 = str[2];
if ( n1 >= '0' && n1 <= '9' ) {
n1 -= '0';
} else if ( n1 >= 'a' && n1 <= 'f' ) {
n1 = n1 - 'a' + 10;
} else {
n1 = 0;
}
n2 = str[3];
if ( n2 >= '0' && n2 <= '9' ) {
n2 -= '0';
} else if ( n2 >= 'a' && n2 <= 'f' ) {
n2 = n2 - 'a' + 10;
} else {
n2 = 0;
}
return n1 * 16 + n2;
}
// scan for a text match
for ( kn = keynames; kn->name; kn++ ) {
if ( !idStr::Icmp( str, kn->name ) ) {
return kn->keynum;
}
}
return -1;
}
/*
===================
idKeyInput::KeyNumToString
Returns a string (either a single ascii char, a K_* name, or a 0x11 hex string) for the
given keynum.
===================
*/
const char *idKeyInput::KeyNumToString( int keynum, bool localized ) {
keyname_t *kn;
static char tinystr[5];
int i, j;
if ( keynum == -1 ) {
return "<KEY NOT FOUND>";
}
if ( keynum < 0 || keynum > 255 ) {
return "<OUT OF RANGE>";
}
// check for printable ascii (don't use quote)
if ( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != '\'' ) {
tinystr[0] = Sys_MapCharForKey( keynum );
tinystr[1] = 0;
return tinystr;
}
// check for a key string
for ( kn = keynames; kn->name; kn++ ) {
if ( keynum == kn->keynum ) {
if ( !localized || kn->strId[0] != '#' ) {
return kn->name;
} else {
#if MACOS_X
switch ( kn->keynum ) {
case K_ENTER:
case K_BACKSPACE:
case K_ALT:
case K_INS:
case K_PRINT_SCR:
return OSX_GetLocalizedString( kn->name );
break;
default :
return common->GetLanguageDict()->GetString( kn->strId ); break;
}
#else
return common->GetLanguageDict()->GetString( kn->strId );
#endif
}
}
}
// check for European high-ASCII characters
if ( localized && keynum >= 161 && keynum <= 255 ) {
tinystr[0] = keynum;
tinystr[1] = 0;
return tinystr;
}
// make a hex string
i = keynum >> 4;
j = keynum & 15;
tinystr[0] = '0';
tinystr[1] = 'x';
tinystr[2] = i > 9 ? i - 10 + 'a' : i + '0';
tinystr[3] = j > 9 ? j - 10 + 'a' : j + '0';
tinystr[4] = 0;
return tinystr;
}
/*
===================
idKeyInput::SetBinding
===================
*/
void idKeyInput::SetBinding( int keynum, const char *binding ) {
if ( keynum == -1 ) {
return;
}
// Clear out all button states so we aren't stuck forever thinking this key is held down
usercmdGen->Clear();
// allocate memory for new binding
keys[keynum].binding = binding;
// find the action for the async command generation
keys[keynum].usercmdAction = usercmdGen->CommandStringUsercmdData( binding );
// consider this like modifying an archived cvar, so the
// file write will be triggered at the next oportunity
cvarSystem->SetModifiedFlags( CVAR_ARCHIVE );
}
/*
===================
idKeyInput::GetBinding
===================
*/
const char *idKeyInput::GetBinding( int keynum ) {
if ( keynum == -1 ) {
return "";
}
return keys[ keynum ].binding;
}
/*
===================
idKeyInput::GetUsercmdAction
===================
*/
int idKeyInput::GetUsercmdAction( int keynum ) {
return keys[ keynum ].usercmdAction;
}
/*
===================
Key_Unbind_f
===================
*/
void Key_Unbind_f( const idCmdArgs &args ) {
int b;
if ( args.Argc() != 2 ) {
common->Printf( "unbind <key> : remove commands from a key\n" );
return;
}
b = idKeyInput::StringToKeyNum( args.Argv(1) );
if ( b == -1 ) {
// If it wasn't a key, it could be a command
if ( !idKeyInput::UnbindBinding( args.Argv(1) ) ) {
common->Printf( "\"%s\" isn't a valid key\n", args.Argv(1) );
}
} else {
idKeyInput::SetBinding( b, "" );
}
}
/*
===================
Key_Unbindall_f
===================
*/
void Key_Unbindall_f( const idCmdArgs &args ) {
int i;
for ( i = 0; i < MAX_KEYS; i++ ) {
idKeyInput::SetBinding( i, "" );
}
}
/*
===================
Key_Bind_f
===================
*/
void Key_Bind_f( const idCmdArgs &args ) {
int i, c, b;
char cmd[MAX_STRING_CHARS];
c = args.Argc();
if ( c < 2 ) {
common->Printf( "bind <key> [command] : attach a command to a key\n" );
return;
}
b = idKeyInput::StringToKeyNum( args.Argv(1) );
if ( b == -1 ) {
common->Printf( "\"%s\" isn't a valid key\n", args.Argv(1) );
return;
}
if ( c == 2 ) {
if ( keys[b].binding.Length() ) {
common->Printf( "\"%s\" = \"%s\"\n", args.Argv(1), keys[b].binding.c_str() );
}
else {
common->Printf( "\"%s\" is not bound\n", args.Argv(1) );
}
return;
}
// copy the rest of the command line
cmd[0] = 0; // start out with a null string
for ( i = 2; i < c; i++ ) {
strcat( cmd, args.Argv( i ) );
if ( i != (c-1) ) {
strcat( cmd, " " );
}
}
idKeyInput::SetBinding( b, cmd );
}
/*
============
Key_BindUnBindTwo_f
binds keynum to bindcommand and unbinds if there are already two binds on the key
============
*/
void Key_BindUnBindTwo_f( const idCmdArgs &args ) {
int c = args.Argc();
if ( c < 3 ) {
common->Printf( "bindunbindtwo <keynum> [command]\n" );
return;
}
int key = atoi( args.Argv( 1 ) );
idStr bind = args.Argv( 2 );
if ( idKeyInput::NumBinds( bind ) >= 2 && !idKeyInput::KeyIsBoundTo( key, bind ) ) {
idKeyInput::UnbindBinding( bind );
}
idKeyInput::SetBinding( key, bind );
}
/*
============
idKeyInput::WriteBindings
Writes lines containing "bind key value"
============
*/
void idKeyInput::WriteBindings( idFile *f ) {
int i;
f->Printf( "unbindall\n" );
for ( i = 0; i < MAX_KEYS; i++ ) {
if ( keys[i].binding.Length() ) {
const char *name = KeyNumToString( i, false );
// handle the escape character nicely
if ( !strcmp( name, "\\" ) ) {
f->Printf( "bind \"\\\" \"%s\"\n", keys[i].binding.c_str() );
} else {
f->Printf( "bind \"%s\" \"%s\"\n", KeyNumToString( i, false ), keys[i].binding.c_str() );
}
}
}
}
/*
============
Key_ListBinds_f
============
*/
void Key_ListBinds_f( const idCmdArgs &args ) {
int i;
for ( i = 0; i < MAX_KEYS; i++ ) {
if ( keys[i].binding.Length() ) {
common->Printf( "%s \"%s\"\n", idKeyInput::KeyNumToString( i, false ), keys[i].binding.c_str() );
}
}
}
/*
============
idKeyInput::KeysFromBinding
returns the localized name of the key for the binding
============
*/
const char *idKeyInput::KeysFromBinding( const char *bind ) {
int i;
static char keyName[MAX_STRING_CHARS];
keyName[0] = '\0';
if ( bind && *bind ) {
for ( i = 0; i < MAX_KEYS; i++ ) {
if ( keys[i].binding.Icmp( bind ) == 0 ) {
if ( keyName[0] != '\0' ) {
idStr::Append( keyName, sizeof( keyName ), common->GetLanguageDict()->GetString( "#str_07183" ) );
}
idStr::Append( keyName, sizeof( keyName ), KeyNumToString( i, true ) );
}
}
}
if ( keyName[0] == '\0' ) {
idStr::Copynz( keyName, common->GetLanguageDict()->GetString( "#str_07133" ), sizeof( keyName ) );
}
idStr::ToLower( keyName );
return keyName;
}
/*
============
idKeyInput::BindingFromKey
returns the binding for the localized name of the key
============
*/
const char *idKeyInput::BindingFromKey( const char *key ) {
const int keyNum = idKeyInput::StringToKeyNum( key );
if ( keyNum<0 || keyNum >= MAX_KEYS ) {
return NULL;
}
return keys[keyNum].binding.c_str();
}
/*
============
idKeyInput::UnbindBinding
============
*/
bool idKeyInput::UnbindBinding( const char *binding ) {
bool unbound = false;
int i;
if ( binding && *binding ) {
for ( i = 0; i < MAX_KEYS; i++ ) {
if ( keys[i].binding.Icmp( binding ) == 0 ) {
SetBinding( i, "" );
unbound = true;
}
}
}
return unbound;
}
/*
============
idKeyInput::NumBinds
============
*/
int idKeyInput::NumBinds( const char *binding ) {
int i, count = 0;
if ( binding && *binding ) {
for ( i = 0; i < MAX_KEYS; i++ ) {
if ( keys[i].binding.Icmp( binding ) == 0 ) {
count++;
}
}
}
return count;
}
/*
============
idKeyInput::KeyIsBountTo
============
*/
bool idKeyInput::KeyIsBoundTo( int keynum, const char *binding ) {
if ( keynum >= 0 && keynum < MAX_KEYS ) {
return ( keys[keynum].binding.Icmp( binding ) == 0 );
}
return false;
}
/*
===================
idKeyInput::PreliminaryKeyEvent
Tracks global key up/down state
Called by the system for both key up and key down events
===================
*/
void idKeyInput::PreliminaryKeyEvent( int keynum, bool down ) {
keys[keynum].down = down;
#ifdef ID_DOOM_LEGACY
if ( down ) {
lastKeys[ 0 + ( lastKeyIndex & 15 )] = keynum;
lastKeys[16 + ( lastKeyIndex & 15 )] = keynum;
lastKeyIndex = ( lastKeyIndex + 1 ) & 15;
for ( int i = 0; cheatCodes[i] != NULL; i++ ) {
int l = strlen( cheatCodes[i] );
assert( l <= 16 );
if ( idStr::Icmpn( lastKeys + 16 + ( lastKeyIndex & 15 ) - l, cheatCodes[i], l ) == 0 ) {
common->Printf( "your memory serves you well!\n" );
break;
}
}
}
#endif
}
/*
=================
idKeyInput::ExecKeyBinding
=================
*/
bool idKeyInput::ExecKeyBinding( int keynum ) {
// commands that are used by the async thread
// don't add text
if ( keys[keynum].usercmdAction ) {
return false;
}
// send the bound action
if ( keys[keynum].binding.Length() ) {
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, keys[keynum].binding.c_str() );
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" );
}
return true;
}
/*
===================
idKeyInput::ClearStates
===================
*/
void idKeyInput::ClearStates( void ) {
int i;
for ( i = 0; i < MAX_KEYS; i++ ) {
if ( keys[i].down ) {
PreliminaryKeyEvent( i, false );
}
keys[i].down = false;
}
// clear the usercommand states
usercmdGen->Clear();
}
/*
===================
idKeyInput::Init
===================
*/
void idKeyInput::Init( void ) {
keys = new idKey[MAX_KEYS];
// register our functions
cmdSystem->AddCommand( "bind", Key_Bind_f, CMD_FL_SYSTEM, "binds a command to a key", idKeyInput::ArgCompletion_KeyName );
cmdSystem->AddCommand( "bindunbindtwo", Key_BindUnBindTwo_f, CMD_FL_SYSTEM, "binds a key but unbinds it first if there are more than two binds" );
cmdSystem->AddCommand( "unbind", Key_Unbind_f, CMD_FL_SYSTEM, "unbinds any command from a key", idKeyInput::ArgCompletion_KeyName );
cmdSystem->AddCommand( "unbindall", Key_Unbindall_f, CMD_FL_SYSTEM, "unbinds any commands from all keys" );
cmdSystem->AddCommand( "listBinds", Key_ListBinds_f, CMD_FL_SYSTEM, "lists key bindings" );
}
/*
===================
idKeyInput::Shutdown
===================
*/
void idKeyInput::Shutdown( void ) {
delete [] keys;
keys = NULL;
}

221
neo/framework/KeyInput.h Normal file
View File

@@ -0,0 +1,221 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __KEYINPUT_H__
#define __KEYINPUT_H__
/*
===============================================================================
Key Input
===============================================================================
*/
// these are the key numbers that are used by the key system
// normal keys should be passed as lowercased ascii
// Some high ascii (> 127) characters that are mapped directly to keys on
// western european keyboards are inserted in this table so that those keys
// are bindable (otherwise they get bound as one of the special keys in this
// table)
typedef enum {
K_TAB = 9,
K_ENTER = 13,
K_ESCAPE = 27,
K_SPACE = 32,
K_BACKSPACE = 127,
K_COMMAND = 128,
K_CAPSLOCK,
K_SCROLL,
K_POWER,
K_PAUSE,
K_UPARROW = 133,
K_DOWNARROW,
K_LEFTARROW,
K_RIGHTARROW,
// The 3 windows keys
K_LWIN = 137,
K_RWIN,
K_MENU,
K_ALT = 140,
K_CTRL,
K_SHIFT,
K_INS,
K_DEL,
K_PGDN,
K_PGUP,
K_HOME,
K_END,
K_F1 = 149,
K_F2,
K_F3,
K_F4,
K_F5,
K_F6,
K_F7,
K_F8,
K_F9,
K_F10,
K_F11,
K_F12,
K_INVERTED_EXCLAMATION = 161, // upside down !
K_F13,
K_F14,
K_F15,
K_KP_HOME = 165,
K_KP_UPARROW,
K_KP_PGUP,
K_KP_LEFTARROW,
K_KP_5,
K_KP_RIGHTARROW,
K_KP_END,
K_KP_DOWNARROW,
K_KP_PGDN,
K_KP_ENTER,
K_KP_INS,
K_KP_DEL,
K_KP_SLASH,
K_SUPERSCRIPT_TWO = 178, // superscript 2
K_KP_MINUS,
K_ACUTE_ACCENT = 180, // accute accent
K_KP_PLUS,
K_KP_NUMLOCK,
K_KP_STAR,
K_KP_EQUALS,
K_MASCULINE_ORDINATOR = 186,
// K_MOUSE enums must be contiguous (no char codes in the middle)
K_MOUSE1 = 187,
K_MOUSE2,
K_MOUSE3,
K_MOUSE4,
K_MOUSE5,
K_MOUSE6,
K_MOUSE7,
K_MOUSE8,
K_MWHEELDOWN = 195,
K_MWHEELUP,
K_JOY1 = 197,
K_JOY2,
K_JOY3,
K_JOY4,
K_JOY5,
K_JOY6,
K_JOY7,
K_JOY8,
K_JOY9,
K_JOY10,
K_JOY11,
K_JOY12,
K_JOY13,
K_JOY14,
K_JOY15,
K_JOY16,
K_JOY17,
K_JOY18,
K_JOY19,
K_JOY20,
K_JOY21,
K_JOY22,
K_JOY23,
K_JOY24,
K_JOY25,
K_JOY26,
K_JOY27,
K_GRAVE_A = 224, // lowercase a with grave accent
K_JOY28,
K_JOY29,
K_JOY30,
K_JOY31,
K_JOY32,
K_AUX1 = 230,
K_CEDILLA_C = 231, // lowercase c with Cedilla
K_GRAVE_E = 232, // lowercase e with grave accent
K_AUX2,
K_AUX3,
K_AUX4,
K_GRAVE_I = 236, // lowercase i with grave accent
K_AUX5,
K_AUX6,
K_AUX7,
K_AUX8,
K_TILDE_N = 241, // lowercase n with tilde
K_GRAVE_O = 242, // lowercase o with grave accent
K_AUX9,
K_AUX10,
K_AUX11,
K_AUX12,
K_AUX13,
K_AUX14,
K_GRAVE_U = 249, // lowercase u with grave accent
K_AUX15,
K_AUX16,
K_PRINT_SCR = 252, // SysRq / PrintScr
K_RIGHT_ALT = 253, // used by some languages as "Alt-Gr"
K_LAST_KEY = 254 // this better be < 256!
} keyNum_t;
class idKeyInput {
public:
static void Init( void );
static void Shutdown( void );
static void ArgCompletion_KeyName( const idCmdArgs &args, void(*callback)( const char *s ) );
static void PreliminaryKeyEvent( int keyNum, bool down );
static bool IsDown( int keyNum );
static int GetUsercmdAction( int keyNum );
static bool GetOverstrikeMode( void );
static void SetOverstrikeMode( bool state );
static void ClearStates( void );
static int StringToKeyNum( const char *str );
static const char * KeyNumToString( int keyNum, bool localized );
static void SetBinding( int keyNum, const char *binding );
static const char * GetBinding( int keyNum );
static bool UnbindBinding( const char *bind );
static int NumBinds( const char *binding );
static bool ExecKeyBinding( int keyNum );
static const char * KeysFromBinding( const char *bind );
static const char * BindingFromKey( const char *key );
static bool KeyIsBoundTo( int keyNum, const char *binding );
static void WriteBindings( idFile *f );
};
#endif /* !__KEYINPUT_H__ */

115
neo/framework/Licensee.h Normal file
View File

@@ -0,0 +1,115 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*
===============================================================================
Definitions for information that is related to a licensee's game name and location.
===============================================================================
*/
#define GAME_NAME "DOOM 3" // appears on window titles and errors
#define ENGINE_VERSION "DOOM 1.3.1" // printed in console
// paths
#define CD_BASEDIR "Doom"
#ifdef ID_DEMO_BUILD
#define BASE_GAMEDIR "demo"
#else
#define BASE_GAMEDIR "base"
#endif
// filenames
#define CD_EXE "doom.exe"
#define CONFIG_FILE "DoomConfig.cfg"
// base folder where the source code lives
#define SOURCE_CODE_BASE_FOLDER "neo"
// default idnet host address
#ifndef IDNET_HOST
#define IDNET_HOST "idnet.ua-corp.com"
#endif
// default idnet master port
#ifndef IDNET_MASTER_PORT
#define IDNET_MASTER_PORT "27650"
#endif
// default network server port
#ifndef PORT_SERVER
#define PORT_SERVER 27666
#endif
// broadcast scan this many ports after PORT_SERVER so a single machine can run multiple servers
#define NUM_SERVER_PORTS 4
// see ASYNC_PROTOCOL_VERSION
// use a different major for each game
#define ASYNC_PROTOCOL_MAJOR 1
// Savegame Version
// Update when you can no longer maintain compatibility with previous savegames
// NOTE: a seperate core savegame version and game savegame version could be useful
// 16: Doom v1.1
// 17: Doom v1.2 / D3XP. Can still read old v16 with defaults for new data
#define SAVEGAME_VERSION 17
// <= Doom v1.1: 1. no DS_VERSION token ( default )
// Doom v1.2: 2
#define RENDERDEMO_VERSION 2
// editor info
#define EDITOR_DEFAULT_PROJECT "doom.qe4"
#define EDITOR_REGISTRY_KEY "DOOMRadiant"
#define EDITOR_WINDOWTEXT "DOOMEdit"
// win32 info
#define WIN32_CONSOLE_CLASS "DOOM 3 WinConsole"
#define WIN32_WINDOW_CLASS_NAME "DOOM3"
#define WIN32_FAKE_WINDOW_CLASS_NAME "DOOM3_WGL_FAKE"
// Linux info
#ifdef ID_DEMO_BUILD
#define LINUX_DEFAULT_PATH "/usr/local/games/doom3-demo"
#else
#define LINUX_DEFAULT_PATH "/usr/local/games/doom3"
#endif
// CD Key file info
// goes into BASE_GAMEDIR whatever the fs_game is set to
// two distinct files for easier win32 installer job
#define CDKEY_FILE "doomkey"
#define XPKEY_FILE "xpkey"
#define CDKEY_TEXT "\n// Do not give this file to ANYONE.\n" \
"// id Software or Zenimax will NEVER ask you to send this file to them.\n"
#define CONFIG_SPEC "config.spec"

3324
neo/framework/Session.cpp Normal file

File diff suppressed because it is too large Load Diff

165
neo/framework/Session.h Normal file
View File

@@ -0,0 +1,165 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SESSION_H__
#define __SESSION_H__
/*
===============================================================================
The session is the glue that holds games together between levels.
===============================================================================
*/
// needed by the gui system for the load game menu
typedef struct {
short health;
short heartRate;
short stamina;
short combat;
} logStats_t;
static const int MAX_LOGGED_STATS = 60 * 120; // log every half second
typedef enum {
MSG_OK,
MSG_ABORT,
MSG_OKCANCEL,
MSG_YESNO,
MSG_PROMPT,
MSG_CDKEY,
MSG_INFO,
MSG_WAIT
} msgBoxType_t;
typedef const char * (*HandleGuiCommand_t)( const char * );
class idSession {
public:
virtual ~idSession() {}
// Called in an orderly fashion at system startup,
// so commands, cvars, files, etc are all available.
virtual void Init() = 0;
// Shut down the session.
virtual void Shutdown() = 0;
// Called on errors and game exits.
virtual void Stop() = 0;
// Redraws the screen, handling games, guis, console, etc
// during normal once-a-frame updates, outOfSequence will be false,
// but when the screen is updated in a modal manner, as with utility
// output, the mouse cursor will be released if running windowed.
virtual void UpdateScreen( bool outOfSequence = true ) = 0;
// Called when console prints happen, allowing the loading screen
// to redraw if enough time has passed.
virtual void PacifierUpdate() = 0;
// Called every frame, possibly spinning in place if we are
// above maxFps, or we haven't advanced at least one demo frame.
// Returns the number of milliseconds since the last frame.
virtual void Frame() = 0;
// Returns true if a multiplayer game is running.
// CVars and commands are checked differently in multiplayer mode.
virtual bool IsMultiplayer() = 0;
// Processes the given event.
virtual bool ProcessEvent( const sysEvent_t *event ) = 0;
// Activates the main menu
virtual void StartMenu( bool playIntro = false ) = 0;
virtual void SetGUI( idUserInterface *gui, HandleGuiCommand_t handle ) = 0;
// Updates gui and dispatched events to it
virtual void GuiFrameEvents() = 0;
// fires up the optional GUI event, also returns them if you set wait to true
// if MSG_PROMPT and wait, returns the prompt string or NULL if aborted
// if MSG_CDKEY and want, returns the cd key or NULL if aborted
// network tells wether one should still run the network loop in a wait dialog
virtual const char *MessageBox( msgBoxType_t type, const char *message, const char *title = NULL, bool wait = false, const char *fire_yes = NULL, const char *fire_no = NULL, bool network = false ) = 0;
virtual void StopBox( void ) = 0;
// monitor this download in a progress box to either abort or completion
virtual void DownloadProgressBox( backgroundDownload_t *bgl, const char *title, int progress_start = 0, int progress_end = 100 ) = 0;
virtual void SetPlayingSoundWorld() = 0;
// this is used by the sound system when an OnDemand sound is loaded, so the game action
// doesn't advance and get things out of sync
virtual void TimeHitch( int msec ) = 0;
// read and write the cd key data to files
// doesn't perform any validity checks
virtual void ReadCDKey( void ) = 0;
virtual void WriteCDKey( void ) = 0;
// returns NULL for if xp is true and xp key is not valid or not present
virtual const char *GetCDKey( bool xp ) = 0;
// check keys for validity when typed in by the user ( with checksum verification )
// store the new set of keys if they are found valid
virtual bool CheckKey( const char *key, bool netConnect, bool offline_valid[ 2 ] ) = 0;
// verify the current set of keys for validity
// strict -> keys in state CDKEY_CHECKING state are not ok
virtual bool CDKeysAreValid( bool strict ) = 0;
// wipe the key on file if the network check finds it invalid
virtual void ClearCDKey( bool valid[ 2 ] ) = 0;
// configure gui variables for mainmenu.gui and cd key state
virtual void SetCDKeyGuiVars( void ) = 0;
virtual bool WaitingForGameAuth( void ) = 0;
// got reply from master about the keys. if !valid, auth_msg given
virtual void CDKeysAuthReply( bool valid, const char *auth_msg ) = 0;
virtual const char *GetCurrentMapName( void ) = 0;
virtual int GetSaveGameVersion( void ) = 0;
// The render world and sound world used for this session.
idRenderWorld * rw;
idSoundWorld * sw;
// The renderer and sound system will write changes to writeDemo.
// Demos can be recorded and played at the same time when splicing.
idDemoFile * readDemo;
idDemoFile * writeDemo;
int renderdemoVersion;
};
extern idSession * session;
#endif /* !__SESSION_H__ */

View File

@@ -0,0 +1,363 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SESSIONLOCAL_H__
#define __SESSIONLOCAL_H__
/*
IsConnectedToServer();
IsGameLoaded();
IsGuiActive();
IsPlayingRenderDemo();
if connected to a server
if handshaking
if map loading
if in game
else if a game loaded
if in load game menu
if main menu up
else if playing render demo
else
if error dialog
full console
*/
typedef struct {
usercmd_t cmd;
int consistencyHash;
} logCmd_t;
struct fileTIME_T {
int index;
ID_TIME_T timeStamp;
operator int() const { return timeStamp; }
};
typedef struct {
idDict serverInfo;
idDict syncedCVars;
idDict userInfo[MAX_ASYNC_CLIENTS];
idDict persistentPlayerInfo[MAX_ASYNC_CLIENTS];
usercmd_t mapSpawnUsercmd[MAX_ASYNC_CLIENTS]; // needed for tracking delta angles
} mapSpawnData_t;
typedef enum {
TD_NO,
TD_YES,
TD_YES_THEN_QUIT
} timeDemo_t;
const int USERCMD_PER_DEMO_FRAME = 2;
const int CONNECT_TRANSMIT_TIME = 1000;
const int MAX_LOGGED_USERCMDS = 60*60*60; // one hour of single player, 15 minutes of four player
class idSessionLocal : public idSession {
public:
idSessionLocal();
virtual ~idSessionLocal();
virtual void Init();
virtual void Shutdown();
virtual void Stop();
virtual void UpdateScreen( bool outOfSequence = true );
virtual void PacifierUpdate();
virtual void Frame();
virtual bool IsMultiplayer();
virtual bool ProcessEvent( const sysEvent_t *event );
virtual void StartMenu( bool playIntro = false );
virtual void ExitMenu();
virtual void GuiFrameEvents();
virtual void SetGUI( idUserInterface *gui, HandleGuiCommand_t handle );
virtual const char *MessageBox( msgBoxType_t type, const char *message, const char *title = NULL, bool wait = false, const char *fire_yes = NULL, const char *fire_no = NULL, bool network = false );
virtual void StopBox( void );
virtual void DownloadProgressBox( backgroundDownload_t *bgl, const char *title, int progress_start = 0, int progress_end = 100 );
virtual void SetPlayingSoundWorld();
virtual void TimeHitch( int msec );
virtual void ReadCDKey( void );
virtual void WriteCDKey( void );
virtual const char *GetCDKey( bool xp );
virtual bool CheckKey( const char *key, bool netConnect, bool offline_valid[ 2 ] );
virtual bool CDKeysAreValid( bool strict );
virtual void ClearCDKey( bool valid[ 2 ] );
virtual void SetCDKeyGuiVars( void );
virtual bool WaitingForGameAuth( void );
virtual void CDKeysAuthReply( bool valid, const char *auth_msg );
virtual int GetSaveGameVersion( void );
virtual const char *GetCurrentMapName();
//=====================================
int GetLocalClientNum();
void MoveToNewMap( const char *mapName );
// loads a map and starts a new game on it
void StartNewGame( const char *mapName, bool devmap = false );
void PlayIntroGui();
void LoadSession( const char *name );
void SaveSession( const char *name );
// called by Draw when the scene to scene wipe is still running
void DrawWipeModel();
void StartWipe( const char *materialName, bool hold = false);
void CompleteWipe();
void ClearWipe();
void ShowLoadingGui();
void ScrubSaveGameFileName( idStr &saveFileName ) const;
idStr GetAutoSaveName( const char *mapName ) const;
bool LoadGame(const char *saveName);
bool SaveGame(const char *saveName, bool autosave = false);
const char *GetAuthMsg( void );
//=====================================
static idCVar com_showAngles;
static idCVar com_showTics;
static idCVar com_minTics;
static idCVar com_fixedTic;
static idCVar com_showDemo;
static idCVar com_skipGameDraw;
static idCVar com_aviDemoWidth;
static idCVar com_aviDemoHeight;
static idCVar com_aviDemoSamples;
static idCVar com_aviDemoTics;
static idCVar com_wipeSeconds;
static idCVar com_guid;
static idCVar gui_configServerRate;
int timeHitch;
bool menuActive;
idSoundWorld * menuSoundWorld; // so the game soundWorld can be muted
bool insideExecuteMapChange; // draw loading screen and update
// screen on prints
int bytesNeededForMapLoad; //
// we don't want to redraw the loading screen for every single
// console print that happens
int lastPacifierTime;
// this is the information required to be set before ExecuteMapChange() is called,
// which can be saved off at any time with the following commands so it can all be played back
mapSpawnData_t mapSpawnData;
idStr currentMapName; // for checking reload on same level
bool mapSpawned; // cleared on Stop()
int numClients; // from serverInfo
int logIndex;
logCmd_t loggedUsercmds[MAX_LOGGED_USERCMDS];
int statIndex;
logStats_t loggedStats[MAX_LOGGED_STATS];
int lastSaveIndex;
// each game tic, numClients usercmds will be added, until full
bool insideUpdateScreen; // true while inside ::UpdateScreen()
bool loadingSaveGame; // currently loading map from a SaveGame
idFile * savegameFile; // this is the savegame file to load from
int savegameVersion;
idFile * cmdDemoFile; // if non-zero, we are reading commands from a file
int latchedTicNumber; // set to com_ticNumber each frame
int lastGameTic; // while latchedTicNumber > lastGameTic, run game frames
int lastDemoTic;
bool syncNextGameFrame;
bool aviCaptureMode; // if true, screenshots will be taken and sound captured
idStr aviDemoShortName; //
float aviDemoFrameCount;
int aviTicStart;
timeDemo_t timeDemo;
int timeDemoStartTime;
int numDemoFrames; // for timeDemo and demoShot
int demoTimeOffset;
renderView_t currentDemoRenderView;
// the next one will be read when
// com_frameTime + demoTimeOffset > currentDemoRenderView.
// TODO: make this private (after sync networking removal and idnet tweaks)
idUserInterface * guiActive;
HandleGuiCommand_t guiHandle;
idUserInterface * guiInGame;
idUserInterface * guiMainMenu;
idListGUI * guiMainMenu_MapList; // easy map list handling
idUserInterface * guiRestartMenu;
idUserInterface * guiLoading;
idUserInterface * guiIntro;
idUserInterface * guiGameOver;
idUserInterface * guiTest;
idUserInterface * guiTakeNotes;
idUserInterface * guiMsg;
idUserInterface * guiMsgRestore; // store the calling GUI for restore
idStr msgFireBack[ 2 ];
bool msgRunning;
int msgRetIndex;
bool msgIgnoreButtons;
bool waitingOnBind;
const idMaterial * whiteMaterial;
const idMaterial * wipeMaterial;
int wipeStartTic;
int wipeStopTic;
bool wipeHold;
#if ID_CONSOLE_LOCK
int emptyDrawCount; // watchdog to force the main menu to restart
#endif
//=====================================
void Clear();
void DrawCmdGraph();
void Draw();
void WriteCmdDemo( const char *name, bool save = false);
void StartPlayingCmdDemo( const char *demoName);
void TimeCmdDemo( const char *demoName);
void SaveCmdDemoToFile(idFile *file);
void LoadCmdDemoFromFile(idFile *file);
void StartRecordingRenderDemo( const char *name );
void StopRecordingRenderDemo();
void StartPlayingRenderDemo( idStr name );
void StopPlayingRenderDemo();
void CompressDemoFile( const char *scheme, const char *name );
void TimeRenderDemo( const char *name, bool twice = false );
void AVIRenderDemo( const char *name );
void AVICmdDemo( const char *name );
void AVIGame( const char *name );
void BeginAVICapture( const char *name );
void EndAVICapture();
void AdvanceRenderDemo( bool singleFrameOnly );
void RunGameTic();
void FinishCmdLoad();
void LoadLoadingGui(const char *mapName);
void DemoShot( const char *name );
void TestGUI( const char *name );
int GetBytesNeededForMapLoad( const char *mapName );
void SetBytesNeededForMapLoad( const char *mapName, int bytesNeeded );
void ExecuteMapChange( bool noFadeWipe = false );
void UnloadMap();
// return true if we actually waiting on an auth reply
bool MaybeWaitOnCDKey( void );
//------------------
// Session_menu.cpp
idStrList loadGameList;
idStrList modsList;
idUserInterface * GetActiveMenu();
void DispatchCommand( idUserInterface *gui, const char *menuCommand, bool doIngame = true );
void MenuEvent( const sysEvent_t *event );
bool HandleSaveGameMenuCommand( idCmdArgs &args, int &icmd );
void HandleInGameCommands( const char *menuCommand );
void HandleMainMenuCommands( const char *menuCommand );
void HandleChatMenuCommands( const char *menuCommand );
void HandleIntroMenuCommands( const char *menuCommand );
void HandleRestartMenuCommands( const char *menuCommand );
void HandleMsgCommands( const char *menuCommand );
void HandleNoteCommands( const char *menuCommand );
void GetSaveGameList( idStrList &fileList, idList<fileTIME_T> &fileTimes );
void TakeNotes( const char * p, bool extended = false );
void UpdateMPLevelShot( void );
void SetSaveGameGuiVars( void );
void SetMainMenuGuiVars( void );
void SetModsMenuGuiVars( void );
void SetMainMenuSkin( void );
void SetPbMenuGuiVars( void );
private:
bool BoxDialogSanityCheck( void );
void EmitGameAuth( void );
typedef enum {
CDKEY_UNKNOWN, // need to perform checks on the key
CDKEY_INVALID, // that key is wrong
CDKEY_OK, // valid
CDKEY_CHECKING, // sent a check request ( gameAuth only )
CDKEY_NA // does not apply, xp key when xp is not present
} cdKeyState_t;
static const int CDKEY_BUF_LEN = 17;
static const int CDKEY_AUTH_TIMEOUT = 5000;
char cdkey[ CDKEY_BUF_LEN ];
cdKeyState_t cdkey_state;
char xpkey[ CDKEY_BUF_LEN ];
cdKeyState_t xpkey_state;
int authEmitTimeout;
bool authWaitBox;
idStr authMsg;
};
extern idSessionLocal sessLocal;
#endif /* !__SESSIONLOCAL_H__ */

File diff suppressed because it is too large Load Diff

4470
neo/framework/Unzip.cpp Normal file

File diff suppressed because it is too large Load Diff

346
neo/framework/Unzip.h Normal file
View File

@@ -0,0 +1,346 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __UNZIP_H__
#define __UNZIP_H__
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagunzFile__ { int unused; } unzFile__;
typedef unzFile__ *unzFile;
#else
typedef void* unzFile;
#endif
/* tm_unz contain date/time info */
typedef struct tm_unz_s
{
unsigned int tm_sec; /* seconds after the minute - [0,59] */
unsigned int tm_min; /* minutes after the hour - [0,59] */
unsigned int tm_hour; /* hours since midnight - [0,23] */
unsigned int tm_mday; /* day of the month - [1,31] */
unsigned int tm_mon; /* months since January - [0,11] */
unsigned int tm_year; /* years - [1980..2044] */
} tm_unz;
/* unz_global_info structure contain global data about the ZIPfile
These data comes from the end of central dir */
typedef struct unz_global_info_s
{
unsigned long number_entry; /* total number of entries in the central dir on this disk */
unsigned long size_comment; /* size of the global comment of the zipfile */
} unz_global_info;
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_info_s
{
unsigned long version; /* version made by 2 unsigned chars */
unsigned long version_needed; /* version needed to extract 2 unsigned chars */
unsigned long flag; /* general purpose bit flag 2 unsigned chars */
unsigned long compression_method; /* compression method 2 unsigned chars */
unsigned long dosDate; /* last mod file date in Dos fmt 4 unsigned chars */
unsigned long crc; /* crc-32 4 unsigned chars */
unsigned long compressed_size; /* compressed size 4 unsigned chars */
unsigned long uncompressed_size; /* uncompressed size 4 unsigned chars */
unsigned long size_filename; /* filename length 2 unsigned chars */
unsigned long size_file_extra; /* extra field length 2 unsigned chars */
unsigned long size_file_comment; /* file comment length 2 unsigned chars */
unsigned long disk_num_start; /* disk number start 2 unsigned chars */
unsigned long internal_fa; /* internal file attributes 2 unsigned chars */
unsigned long external_fa; /* external file attributes 4 unsigned chars */
tm_unz tmu_date;
} unz_file_info;
/* unz_file_info_interntal contain internal info about a file in zipfile*/
typedef struct unz_file_info_internal_s
{
unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
} unz_file_info_internal;
typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
typedef void (*free_func) (void* opaque, void* address);
struct internal_state;
typedef struct z_stream_s {
unsigned char *next_in; /* next input unsigned char */
unsigned int avail_in; /* number of unsigned chars available at next_in */
unsigned long total_in; /* total nb of input unsigned chars read so */
unsigned char *next_out; /* next output unsigned char should be put there */
unsigned int avail_out; /* remaining free space at next_out */
unsigned long total_out; /* total nb of unsigned chars output so */
char *msg; /* last error message, NULL if no error */
struct internal_state *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
free_func zfree; /* used to free the internal state */
unsigned char* opaque; /* private data object passed to zalloc and zfree */
int data_type; /* best guess about the data type: ascii or binary */
unsigned long adler; /* adler32 value of the uncompressed data */
unsigned long reserved; /* reserved for future use */
} z_stream;
typedef z_stream *z_streamp;
/* file_in_zip_read_info_s contain internal information about a file in zipfile,
when reading and decompress it */
typedef struct
{
char *read_buffer; /* internal buffer for compressed data */
z_stream stream; /* zLib stream structure for inflate */
unsigned long pos_in_zipfile; /* position in unsigned char on the zipfile, for fseek*/
unsigned long stream_initialised; /* flag set if stream structure is initialised*/
unsigned long offset_local_extrafield;/* offset of the static extra field */
unsigned int size_local_extrafield;/* size of the static extra field */
unsigned long pos_local_extrafield; /* position in the static extra field in read*/
unsigned long crc32; /* crc32 of all data uncompressed */
unsigned long crc32_wait; /* crc32 we must obtain after decompress all */
unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
FILE* file; /* io structore of the zipfile */
unsigned long compression_method; /* compression method (0==store) */
unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
} file_in_zip_read_info_s;
/* unz_s contain internal information about the zipfile
*/
typedef struct
{
FILE* file; /* io structore of the zipfile */
unz_global_info gi; /* public global information */
unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
unsigned long num_file; /* number of the current file in the zipfile*/
unsigned long pos_in_central_dir; /* pos of the current file in the central dir*/
unsigned long current_file_ok; /* flag about the usability of the current file*/
unsigned long central_pos; /* position of the beginning of the central dir*/
unsigned long size_central_dir; /* size of the central directory */
unsigned long offset_central_dir; /* offset of start of central directory with
respect to the starting disk number */
unz_file_info cur_file_info; /* public info about the current file in zip*/
unz_file_info_internal cur_file_info_internal; /* private info about it*/
file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
file if we are decompressing it */
} unz_s;
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO)
#define UNZ_EOF (0)
#define UNZ_PARAMERROR (-102)
#define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
#define UNZ_CRCERROR (-105)
#define UNZ_CASESENSITIVE 1
#define UNZ_NOTCASESENSITIVE 2
#define UNZ_OSDEFAULTCASE 0
extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
/*
Compare two filename (fileName1,fileName2).
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
or strcasecmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
extern unzFile unzOpen (const char *path);
extern unzFile unzReOpen (const char* path, unzFile file);
/*
Open a Zip file. path contain the full pathname (by example,
on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
"zlib/zlib111.zip".
If the zipfile cannot be opened (file don't exist or in not valid), the
return value is NULL.
Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
*/
extern int unzClose (unzFile file);
/*
Close a ZipFile opened with unzipOpen.
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */
extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
/*
Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
/*
Get the global comment string of the ZipFile, in the szComment buffer.
uSizeBuf is the size of the szComment buffer.
return the number of unsigned char copied or an error code <0
*/
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
extern int unzGoToFirstFile (unzFile file);
/*
Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
*/
extern int unzGoToNextFile (unzFile file);
/*
Set the current file of the zipfile to the next file.
return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
extern int unzGetCurrentFileInfoPosition (unzFile file, unsigned long *pos );
/*
Get the position of the info of the current file in the zip.
return UNZ_OK if there is no problem
*/
extern int unzSetCurrentFileInfoPosition (unzFile file, unsigned long pos );
/*
Set the position of the info of the current file in the zip.
return UNZ_OK if there is no problem
*/
extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
/*
Try locate the file szFileName in the zipfile.
For the iCaseSensitivity signification, see unzStringFileNameCompare
return value :
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
/*
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
the current file
if szFileName!=NULL, the filemane string will be copied in szFileName
(fileNameBufferSize is the size of the buffer)
if extraField!=NULL, the extra field information will be copied in extraField
(extraFieldBufferSize is the size of the buffer).
This is the Central-header version of the extra field
if szComment!=NULL, the comment string of the file will be copied in szComment
(commentBufferSize is the size of the buffer)
*/
/***************************************************************************/
/* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file)
*/
extern int unzOpenCurrentFile (unzFile file);
/*
Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
*/
extern int unzCloseCurrentFile (unzFile file);
/*
Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
/*
Read unsigned chars from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
len the size of buf.
return the number of unsigned char copied if somes unsigned chars are copied
return 0 if the end of file was reached
return <0 with error code if there is an error
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
extern long unztell(unzFile file);
/*
Give the current position in uncompressed data
*/
extern int unzeof (unzFile file);
/*
return 1 if the end of file was reached, 0 elsewhere
*/
extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
/*
Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
more info in the local-header version than in the central-header)
if buf==NULL, it return the size of the local extra field
if buf!=NULL, len is the size of the buffer, the extra header is copied in
buf.
the return value is the number of unsigned chars copied in buf, or (if <0)
the error code
*/
#endif /* __UNZIP_H__ */

1112
neo/framework/UsercmdGen.cpp Normal file

File diff suppressed because it is too large Load Diff

170
neo/framework/UsercmdGen.h Normal file
View File

@@ -0,0 +1,170 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __USERCMDGEN_H__
#define __USERCMDGEN_H__
/*
===============================================================================
Samples a set of user commands from player input.
===============================================================================
*/
const int USERCMD_HZ = 60; // 60 frames per second
const int USERCMD_MSEC = 1000 / USERCMD_HZ;
// usercmd_t->button bits
const int BUTTON_ATTACK = BIT(0);
const int BUTTON_RUN = BIT(1);
const int BUTTON_ZOOM = BIT(2);
const int BUTTON_SCORES = BIT(3);
const int BUTTON_MLOOK = BIT(4);
const int BUTTON_5 = BIT(5);
const int BUTTON_6 = BIT(6);
const int BUTTON_7 = BIT(7);
// usercmd_t->impulse commands
const int IMPULSE_0 = 0; // weap 0
const int IMPULSE_1 = 1; // weap 1
const int IMPULSE_2 = 2; // weap 2
const int IMPULSE_3 = 3; // weap 3
const int IMPULSE_4 = 4; // weap 4
const int IMPULSE_5 = 5; // weap 5
const int IMPULSE_6 = 6; // weap 6
const int IMPULSE_7 = 7; // weap 7
const int IMPULSE_8 = 8; // weap 8
const int IMPULSE_9 = 9; // weap 9
const int IMPULSE_10 = 10; // weap 10
const int IMPULSE_11 = 11; // weap 11
const int IMPULSE_12 = 12; // weap 12
const int IMPULSE_13 = 13; // weap reload
const int IMPULSE_14 = 14; // weap next
const int IMPULSE_15 = 15; // weap prev
const int IMPULSE_16 = 16; // <unused>
const int IMPULSE_17 = 17; // ready to play ( toggles ui_ready )
const int IMPULSE_18 = 18; // center view
const int IMPULSE_19 = 19; // show PDA/INV/MAP
const int IMPULSE_20 = 20; // toggle team ( toggles ui_team )
const int IMPULSE_21 = 21; // <unused>
const int IMPULSE_22 = 22; // spectate
const int IMPULSE_23 = 23; // <unused>
const int IMPULSE_24 = 24; // <unused>
const int IMPULSE_25 = 25; // <unused>
const int IMPULSE_26 = 26; // <unused>
const int IMPULSE_27 = 27; // <unused>
const int IMPULSE_28 = 28; // vote yes
const int IMPULSE_29 = 29; // vote no
const int IMPULSE_40 = 40; // use vehicle
// usercmd_t->flags
const int UCF_IMPULSE_SEQUENCE = 0x0001; // toggled every time an impulse command is sent
class usercmd_t {
public:
int gameFrame; // frame number
int gameTime; // game time
int duplicateCount; // duplication count for networking
byte buttons; // buttons
signed char forwardmove; // forward/backward movement
signed char rightmove; // left/right movement
signed char upmove; // up/down movement
short angles[3]; // view angles
short mx; // mouse delta x
short my; // mouse delta y
signed char impulse; // impulse command
byte flags; // additional flags
int sequence; // just for debugging
public:
void ByteSwap(); // on big endian systems, byte swap the shorts and ints
bool operator==( const usercmd_t &rhs ) const;
};
typedef enum {
INHIBIT_SESSION = 0,
INHIBIT_ASYNC
} inhibit_t;
const int MAX_BUFFERED_USERCMD = 64;
class idUsercmdGen {
public:
virtual ~idUsercmdGen( void ) {}
// Sets up all the cvars and console commands.
virtual void Init( void ) = 0;
// Prepares for a new map.
virtual void InitForNewMap( void ) = 0;
// Shut down.
virtual void Shutdown( void ) = 0;
// Clears all key states and face straight.
virtual void Clear( void ) = 0;
// Clears view angles.
virtual void ClearAngles( void ) = 0;
// When the console is down or the menu is up, only emit default usercmd, so the player isn't moving around.
// Each subsystem (session and game) may want an inhibit will OR the requests.
virtual void InhibitUsercmd( inhibit_t subsystem, bool inhibit ) = 0;
// Returns a buffered command for the given game tic.
virtual usercmd_t TicCmd( int ticNumber ) = 0;
// Called async at regular intervals.
virtual void UsercmdInterrupt( void ) = 0;
// Set a value that can safely be referenced by UsercmdInterrupt() for each key binding.
virtual int CommandStringUsercmdData( const char *cmdString ) = 0;
// Returns the number of user commands.
virtual int GetNumUserCommands( void ) = 0;
// Returns the name of a user command via index.
virtual const char *GetUserCommandName( int index ) = 0;
// Continuously modified, never reset. For full screen guis.
virtual void MouseState( int *x, int *y, int *button, bool *down ) = 0;
// Directly sample a button.
virtual int ButtonState( int key ) = 0;
// Directly sample a keystate.
virtual int KeyState( int key ) = 0;
// Directly sample a usercmd.
virtual usercmd_t GetDirectUsercmd( void ) = 0;
};
extern idUsercmdGen *usercmdGen;
#endif /* !__USERCMDGEN_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,218 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __ASYNCCLIENT_H__
#define __ASYNCCLIENT_H__
/*
===============================================================================
Network Client for asynchronous networking.
===============================================================================
*/
typedef enum {
CS_DISCONNECTED,
CS_PURERESTART,
CS_CHALLENGING,
CS_CONNECTING,
CS_CONNECTED,
CS_INGAME
} clientState_t;
typedef enum {
AUTHKEY_BADKEY,
AUTHKEY_GUID
} authKeyMsg_t;
typedef enum {
AUTHKEY_BAD_INVALID,
AUTHKEY_BAD_BANNED,
AUTHKEY_BAD_INUSE,
AUTHKEY_BAD_MSG
} authBadKeyStatus_t;
typedef enum {
UPDATE_NONE,
UPDATE_SENT,
UPDATE_READY,
UPDATE_DLING,
UPDATE_DONE
} clientUpdateState_t;
typedef struct {
idStr url;
idStr filename;
int size;
int checksum;
} pakDlEntry_t;
class idAsyncClient {
public:
idAsyncClient();
void Shutdown( void );
bool InitPort( void );
void ClosePort( void );
void ConnectToServer( const netadr_t adr );
void ConnectToServer( const char *address );
void Reconnect( void );
void DisconnectFromServer( void );
void GetServerInfo( const netadr_t adr );
void GetServerInfo( const char *address );
void GetLANServers( void );
void GetNETServers( void );
void ListServers( void );
void ClearServers( void );
void RemoteConsole( const char *command );
bool IsPortInitialized() { return clientPort.GetPort() != 0; }
bool IsActive( void ) const { return active; }
int GetLocalClientNum( void ) const { return clientNum; }
int GetPrediction( void ) const;
int GetTimeSinceLastPacket( void ) const;
int GetOutgoingRate( void ) const;
int GetIncomingRate( void ) const;
float GetOutgoingCompression( void ) const;
float GetIncomingCompression( void ) const;
float GetIncomingPacketLoss( void ) const;
int GetPredictedFrames( void ) const { return lastFrameDelta; }
void RunFrame( void );
void SendReliableGameMessage( const idBitMsg &msg );
void SendVersionCheck( bool fromMenu = false );
// pass NULL for the keys you don't care to auth for
// returns false if internet link doesn't appear to be available
bool SendAuthCheck( const char *cdkey, const char *xpkey );
void PacifierUpdate( void );
idServerScan serverList;
private:
bool active; // true if client is active
int realTime; // absolute time
int clientTime; // client local time
idPort clientPort; // UDP port
int clientId; // client identification
int clientDataChecksum; // checksum of the data used by the client
int clientNum; // client number on server
clientState_t clientState; // client state
int clientPrediction; // how far the client predicts ahead
int clientPredictTime; // prediction time used to send user commands
netadr_t serverAddress; // IP address of server
int serverId; // server identification
int serverChallenge; // challenge from server
int serverMessageSequence; // sequence number of last server message
netadr_t lastRconAddress; // last rcon address we emitted to
int lastRconTime; // when last rcon emitted
idMsgChannel channel; // message channel to server
int lastConnectTime; // last time a connect message was sent
int lastEmptyTime; // last time an empty message was sent
int lastPacketTime; // last time a packet was received from the server
int lastSnapshotTime; // last time a snapshot was received
int snapshotSequence; // sequence number of the last received snapshot
int snapshotGameFrame; // game frame number of the last received snapshot
int snapshotGameTime; // game time of the last received snapshot
int gameInitId; // game initialization identification
int gameFrame; // local game frame
int gameTime; // local game time
int gameTimeResidual; // left over time from previous frame
usercmd_t userCmds[MAX_USERCMD_BACKUP][MAX_ASYNC_CLIENTS];
idUserInterface * guiNetMenu;
clientUpdateState_t updateState;
int updateSentTime;
idStr updateMSG;
idStr updateURL;
bool updateDirectDownload;
idStr updateFile;
dlMime_t updateMime;
idStr updateFallback;
bool showUpdateMessage;
backgroundDownload_t backgroundDownload;
int dltotal;
int dlnow;
int lastFrameDelta;
int dlRequest; // randomized number to keep track of the requests
int dlChecksums[ MAX_PURE_PAKS ]; // 0-terminated, first element is the game pak checksum or 0
int dlCount; // total number of paks we request download for ( including the game pak )
idList<pakDlEntry_t>dlList; // list of paks to download, with url and name
int currentDlSize;
int totalDlSize; // for partial progress stuff
void Clear( void );
void ClearPendingPackets( void );
void DuplicateUsercmds( int frame, int time );
void SendUserInfoToServer( void );
void SendEmptyToServer( bool force = false, bool mapLoad = false );
void SendPingResponseToServer( int time );
void SendUsercmdsToServer( void );
void InitGame( int serverGameInitId, int serverGameFrame, int serverGameTime, const idDict &serverSI );
void ProcessUnreliableServerMessage( const idBitMsg &msg );
void ProcessReliableServerMessages( void );
void ProcessChallengeResponseMessage( const netadr_t from, const idBitMsg &msg );
void ProcessConnectResponseMessage( const netadr_t from, const idBitMsg &msg );
void ProcessDisconnectMessage( const netadr_t from, const idBitMsg &msg );
void ProcessInfoResponseMessage( const netadr_t from, const idBitMsg &msg );
void ProcessPrintMessage( const netadr_t from, const idBitMsg &msg );
void ProcessServersListMessage( const netadr_t from, const idBitMsg &msg );
void ProcessAuthKeyMessage( const netadr_t from, const idBitMsg &msg );
void ProcessVersionMessage( const netadr_t from, const idBitMsg &msg );
void ConnectionlessMessage( const netadr_t from, const idBitMsg &msg );
void ProcessMessage( const netadr_t from, idBitMsg &msg );
void SetupConnection( void );
void ProcessPureMessage( const netadr_t from, const idBitMsg &msg );
bool ValidatePureServerChecksums( const netadr_t from, const idBitMsg &msg );
void ProcessReliableMessagePure( const idBitMsg &msg );
static const char* HandleGuiCommand( const char *cmd );
const char* HandleGuiCommandInternal( const char *cmd );
void SendVersionDLUpdate( int state );
void HandleDownloads( void );
void Idle( void );
int UpdateTime( int clamp );
void ReadLocalizedServerString( const idBitMsg &msg, char* out, int maxLen );
bool CheckTimeout( void );
void ProcessDownloadInfoMessage( const netadr_t from, const idBitMsg &msg );
int GetDownloadRequest( const int checksums[ MAX_PURE_PAKS ], int count, int gamePakChecksum );
};
#endif /* !__ASYNCCLIENT_H__ */

View File

@@ -0,0 +1,513 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "AsyncNetwork.h"
idAsyncServer idAsyncNetwork::server;
idAsyncClient idAsyncNetwork::client;
idCVar idAsyncNetwork::verbose( "net_verbose", "0", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "1 = verbose output, 2 = even more verbose output", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
idCVar idAsyncNetwork::allowCheats( "net_allowCheats", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_NETWORKSYNC, "Allow cheats in network game" );
#ifdef ID_DEDICATED
// dedicated executable can only have a value of 1 for net_serverDedicated
idCVar idAsyncNetwork::serverDedicated( "net_serverDedicated", "1", CVAR_SERVERINFO | CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT | CVAR_ROM, "" );
#else
idCVar idAsyncNetwork::serverDedicated( "net_serverDedicated", "0", CVAR_SERVERINFO | CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "1 = text console dedicated server, 2 = graphical dedicated server", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
#endif
idCVar idAsyncNetwork::serverSnapshotDelay( "net_serverSnapshotDelay", "50", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "delay between snapshots in milliseconds" );
idCVar idAsyncNetwork::serverMaxClientRate( "net_serverMaxClientRate", "16000", CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE | CVAR_NOCHEAT, "maximum rate to a client in bytes/sec" );
idCVar idAsyncNetwork::clientMaxRate( "net_clientMaxRate", "16000", CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE | CVAR_NOCHEAT, "maximum rate requested by client from server in bytes/sec" );
idCVar idAsyncNetwork::serverMaxUsercmdRelay( "net_serverMaxUsercmdRelay", "5", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "maximum number of usercmds from other clients the server relays to a client", 1, MAX_USERCMD_RELAY, idCmdSystem::ArgCompletion_Integer<1,MAX_USERCMD_RELAY> );
idCVar idAsyncNetwork::serverZombieTimeout( "net_serverZombieTimeout", "5", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "disconnected client timeout in seconds" );
idCVar idAsyncNetwork::serverClientTimeout( "net_serverClientTimeout", "40", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "client time out in seconds" );
idCVar idAsyncNetwork::clientServerTimeout( "net_clientServerTimeout", "40", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "server time out in seconds" );
idCVar idAsyncNetwork::serverDrawClient( "net_serverDrawClient", "-1", CVAR_SYSTEM | CVAR_INTEGER, "number of client for which to draw view on server" );
idCVar idAsyncNetwork::serverRemoteConsolePassword( "net_serverRemoteConsolePassword", "", CVAR_SYSTEM | CVAR_NOCHEAT, "remote console password" );
idCVar idAsyncNetwork::clientPrediction( "net_clientPrediction", "16", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "additional client side prediction in milliseconds" );
idCVar idAsyncNetwork::clientMaxPrediction( "net_clientMaxPrediction", "1000", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "maximum number of milliseconds a client can predict ahead of server." );
idCVar idAsyncNetwork::clientUsercmdBackup( "net_clientUsercmdBackup", "5", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "number of usercmds to resend" );
idCVar idAsyncNetwork::clientRemoteConsoleAddress( "net_clientRemoteConsoleAddress", "localhost", CVAR_SYSTEM | CVAR_NOCHEAT, "remote console address" );
idCVar idAsyncNetwork::clientRemoteConsolePassword( "net_clientRemoteConsolePassword", "", CVAR_SYSTEM | CVAR_NOCHEAT, "remote console password" );
idCVar idAsyncNetwork::master0( "net_master0", IDNET_HOST ":" IDNET_MASTER_PORT, CVAR_SYSTEM | CVAR_ROM, "idnet master server address" );
idCVar idAsyncNetwork::master1( "net_master1", "", CVAR_SYSTEM | CVAR_ARCHIVE, "1st master server address" );
idCVar idAsyncNetwork::master2( "net_master2", "", CVAR_SYSTEM | CVAR_ARCHIVE, "2nd master server address" );
idCVar idAsyncNetwork::master3( "net_master3", "", CVAR_SYSTEM | CVAR_ARCHIVE, "3rd master server address" );
idCVar idAsyncNetwork::master4( "net_master4", "", CVAR_SYSTEM | CVAR_ARCHIVE, "4th master server address" );
idCVar idAsyncNetwork::LANServer( "net_LANServer", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_NOCHEAT, "config LAN games only - affects clients and servers" );
idCVar idAsyncNetwork::serverReloadEngine( "net_serverReloadEngine", "0", CVAR_SYSTEM | CVAR_INTEGER | CVAR_NOCHEAT, "perform a full reload on next map restart (including flushing referenced pak files) - decreased if > 0" );
idCVar idAsyncNetwork::serverAllowServerMod( "net_serverAllowServerMod", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_NOCHEAT, "allow server-side mods" );
idCVar idAsyncNetwork::idleServer( "si_idleServer", "0", CVAR_SYSTEM | CVAR_BOOL | CVAR_INIT | CVAR_SERVERINFO, "game clients are idle" );
idCVar idAsyncNetwork::clientDownload( "net_clientDownload", "1", CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE, "client pk4 downloads policy: 0 - never, 1 - ask, 2 - always (will still prompt for binary code)" );
int idAsyncNetwork::realTime;
master_t idAsyncNetwork::masters[ MAX_MASTER_SERVERS ];
/*
==================
idAsyncNetwork::idAsyncNetwork
==================
*/
idAsyncNetwork::idAsyncNetwork( void ) {
}
/*
==================
idAsyncNetwork::Init
==================
*/
void idAsyncNetwork::Init( void ) {
realTime = 0;
memset( masters, 0, sizeof( masters ) );
masters[0].var = &master0;
masters[1].var = &master1;
masters[2].var = &master2;
masters[3].var = &master3;
masters[4].var = &master4;
#ifndef ID_DEMO_BUILD
cmdSystem->AddCommand( "spawnServer", SpawnServer_f, CMD_FL_SYSTEM, "spawns a server", idCmdSystem::ArgCompletion_MapName );
cmdSystem->AddCommand( "nextMap", NextMap_f, CMD_FL_SYSTEM, "loads the next map on the server" );
cmdSystem->AddCommand( "connect", Connect_f, CMD_FL_SYSTEM, "connects to a server" );
cmdSystem->AddCommand( "reconnect", Reconnect_f, CMD_FL_SYSTEM, "reconnect to the last server we tried to connect to" );
cmdSystem->AddCommand( "serverInfo", GetServerInfo_f, CMD_FL_SYSTEM, "shows server info" );
cmdSystem->AddCommand( "LANScan", GetLANServers_f, CMD_FL_SYSTEM, "scans LAN for servers" );
cmdSystem->AddCommand( "listServers", ListServers_f, CMD_FL_SYSTEM, "lists scanned servers" );
cmdSystem->AddCommand( "rcon", RemoteConsole_f, CMD_FL_SYSTEM, "sends remote console command to server" );
cmdSystem->AddCommand( "heartbeat", Heartbeat_f, CMD_FL_SYSTEM, "send a heartbeat to the the master servers" );
cmdSystem->AddCommand( "kick", Kick_f, CMD_FL_SYSTEM, "kick a client by connection number" );
cmdSystem->AddCommand( "checkNewVersion", CheckNewVersion_f, CMD_FL_SYSTEM, "check if a new version of the game is available" );
cmdSystem->AddCommand( "updateUI", UpdateUI_f, CMD_FL_SYSTEM, "internal - cause a sync down of game-modified userinfo" );
#endif
}
/*
==================
idAsyncNetwork::GetMasterAddress
==================
*/
netadr_t idAsyncNetwork::GetMasterAddress( void ) {
netadr_t ret;
GetMasterAddress( 0, ret );
return masters[ 0 ].address;
}
/*
==================
idAsyncNetwork::GetMasterAddress
==================
*/
bool idAsyncNetwork::GetMasterAddress( int index, netadr_t &adr ) {
if ( !masters[ index ].var ) {
return false;
}
if ( masters[ index ].var->GetString()[0] == '\0' ) {
return false;
}
if ( !masters[ index ].resolved || masters[ index ].var->IsModified() ) {
masters[ index ].var->ClearModified();
if ( !Sys_StringToNetAdr( masters[ index ].var->GetString(), &masters[ index ].address, true ) ) {
common->Printf( "Failed to resolve master%d: %s\n", index, masters[ index ].var->GetString() );
memset( &masters[ index ].address, 0, sizeof( netadr_t ) );
masters[ index ].resolved = true;
return false;
}
if ( masters[ index ].address.port == 0 ) {
masters[ index ].address.port = atoi( IDNET_MASTER_PORT );
}
masters[ index ].resolved = true;
}
adr = masters[ index ].address;
return true;
}
/*
==================
idAsyncNetwork::Shutdown
==================
*/
void idAsyncNetwork::Shutdown( void ) {
client.serverList.Shutdown();
client.DisconnectFromServer();
client.ClearServers();
client.ClosePort();
server.Kill();
server.ClosePort();
}
/*
==================
idAsyncNetwork::RunFrame
==================
*/
void idAsyncNetwork::RunFrame( void ) {
if ( console->Active() ) {
Sys_GrabMouseCursor( false );
usercmdGen->InhibitUsercmd( INHIBIT_ASYNC, true );
} else {
Sys_GrabMouseCursor( true );
usercmdGen->InhibitUsercmd( INHIBIT_ASYNC, false );
}
client.RunFrame();
server.RunFrame();
}
/*
==================
idAsyncNetwork::WriteUserCmdDelta
==================
*/
void idAsyncNetwork::WriteUserCmdDelta( idBitMsg &msg, const usercmd_t &cmd, const usercmd_t *base ) {
if ( base ) {
msg.WriteDeltaLongCounter( base->gameTime, cmd.gameTime );
msg.WriteDeltaByte( base->buttons, cmd.buttons );
msg.WriteDeltaShort( base->mx, cmd.mx );
msg.WriteDeltaShort( base->my, cmd.my );
msg.WriteDeltaChar( base->forwardmove, cmd.forwardmove );
msg.WriteDeltaChar( base->rightmove, cmd.rightmove );
msg.WriteDeltaChar( base->upmove, cmd.upmove );
msg.WriteDeltaShort( base->angles[0], cmd.angles[0] );
msg.WriteDeltaShort( base->angles[1], cmd.angles[1] );
msg.WriteDeltaShort( base->angles[2], cmd.angles[2] );
return;
}
msg.WriteLong( cmd.gameTime );
msg.WriteByte( cmd.buttons );
msg.WriteShort( cmd.mx );
msg.WriteShort( cmd.my );
msg.WriteChar( cmd.forwardmove );
msg.WriteChar( cmd.rightmove );
msg.WriteChar( cmd.upmove );
msg.WriteShort( cmd.angles[0] );
msg.WriteShort( cmd.angles[1] );
msg.WriteShort( cmd.angles[2] );
}
/*
==================
idAsyncNetwork::ReadUserCmdDelta
==================
*/
void idAsyncNetwork::ReadUserCmdDelta( const idBitMsg &msg, usercmd_t &cmd, const usercmd_t *base ) {
memset( &cmd, 0, sizeof( cmd ) );
if ( base ) {
cmd.gameTime = msg.ReadDeltaLongCounter( base->gameTime );
cmd.buttons = msg.ReadDeltaByte( base->buttons );
cmd.mx = msg.ReadDeltaShort( base->mx );
cmd.my = msg.ReadDeltaShort( base->my );
cmd.forwardmove = msg.ReadDeltaChar( base->forwardmove );
cmd.rightmove = msg.ReadDeltaChar( base->rightmove );
cmd.upmove = msg.ReadDeltaChar( base->upmove );
cmd.angles[0] = msg.ReadDeltaShort( base->angles[0] );
cmd.angles[1] = msg.ReadDeltaShort( base->angles[1] );
cmd.angles[2] = msg.ReadDeltaShort( base->angles[2] );
return;
}
cmd.gameTime = msg.ReadLong();
cmd.buttons = msg.ReadByte();
cmd.mx = msg.ReadShort();
cmd.my = msg.ReadShort();
cmd.forwardmove = msg.ReadChar();
cmd.rightmove = msg.ReadChar();
cmd.upmove = msg.ReadChar();
cmd.angles[0] = msg.ReadShort();
cmd.angles[1] = msg.ReadShort();
cmd.angles[2] = msg.ReadShort();
}
/*
==================
idAsyncNetwork::DuplicateUsercmd
==================
*/
bool idAsyncNetwork::DuplicateUsercmd( const usercmd_t &previousUserCmd, usercmd_t &currentUserCmd, int frame, int time ) {
if ( currentUserCmd.gameTime <= previousUserCmd.gameTime ) {
currentUserCmd = previousUserCmd;
currentUserCmd.gameFrame = frame;
currentUserCmd.gameTime = time;
currentUserCmd.duplicateCount++;
if ( currentUserCmd.duplicateCount > MAX_USERCMD_DUPLICATION ) {
currentUserCmd.buttons &= ~BUTTON_ATTACK;
if ( abs( currentUserCmd.forwardmove ) > 2 ) currentUserCmd.forwardmove >>= 1;
if ( abs( currentUserCmd.rightmove ) > 2 ) currentUserCmd.rightmove >>= 1;
if ( abs( currentUserCmd.upmove ) > 2 ) currentUserCmd.upmove >>= 1;
}
return true;
}
return false;
}
/*
==================
idAsyncNetwork::UsercmdInputChanged
==================
*/
bool idAsyncNetwork::UsercmdInputChanged( const usercmd_t &previousUserCmd, const usercmd_t &currentUserCmd ) {
return previousUserCmd.buttons != currentUserCmd.buttons ||
previousUserCmd.forwardmove != currentUserCmd.forwardmove ||
previousUserCmd.rightmove != currentUserCmd.rightmove ||
previousUserCmd.upmove != currentUserCmd.upmove ||
previousUserCmd.angles[0] != currentUserCmd.angles[0] ||
previousUserCmd.angles[1] != currentUserCmd.angles[1] ||
previousUserCmd.angles[2] != currentUserCmd.angles[2];
}
/*
==================
idAsyncNetwork::SpawnServer_f
==================
*/
void idAsyncNetwork::SpawnServer_f( const idCmdArgs &args ) {
if(args.Argc() > 1) {
cvarSystem->SetCVarString("si_map", args.Argv(1));
}
// don't let a server spawn with singleplayer game type - it will crash
if ( idStr::Icmp( cvarSystem->GetCVarString( "si_gameType" ), "singleplayer" ) == 0 ) {
cvarSystem->SetCVarString( "si_gameType", "deathmatch" );
}
com_asyncInput.SetBool( false );
// make sure the current system state is compatible with net_serverDedicated
switch ( cvarSystem->GetCVarInteger( "net_serverDedicated" ) ) {
case 0:
case 2:
if ( !renderSystem->IsOpenGLRunning() ) {
common->Warning( "OpenGL is not running, net_serverDedicated == %d", cvarSystem->GetCVarInteger( "net_serverDedicated" ) );
}
break;
case 1:
if ( renderSystem->IsOpenGLRunning() ) {
Sys_ShowConsole( 1, false );
renderSystem->ShutdownOpenGL();
}
soundSystem->SetMute( true );
soundSystem->ShutdownHW();
break;
}
// use serverMapRestart if we already have a running server
if ( server.IsActive() ) {
cmdSystem->BufferCommandText( CMD_EXEC_NOW, "serverMapRestart" );
} else {
server.Spawn();
}
}
/*
==================
idAsyncNetwork::NextMap_f
==================
*/
void idAsyncNetwork::NextMap_f( const idCmdArgs &args ) {
server.ExecuteMapChange();
}
/*
==================
idAsyncNetwork::Connect_f
==================
*/
void idAsyncNetwork::Connect_f( const idCmdArgs &args ) {
if ( server.IsActive() ) {
common->Printf( "already running a server\n" );
return;
}
if ( args.Argc() != 2 ) {
common->Printf( "USAGE: connect <serverName>\n" );
return;
}
com_asyncInput.SetBool( false );
client.ConnectToServer( args.Argv( 1 ) );
}
/*
==================
idAsyncNetwork::Reconnect_f
==================
*/
void idAsyncNetwork::Reconnect_f( const idCmdArgs &args ) {
client.Reconnect();
}
/*
==================
idAsyncNetwork::GetServerInfo_f
==================
*/
void idAsyncNetwork::GetServerInfo_f( const idCmdArgs &args ) {
client.GetServerInfo( args.Argv( 1 ) );
}
/*
==================
idAsyncNetwork::GetLANServers_f
==================
*/
void idAsyncNetwork::GetLANServers_f( const idCmdArgs &args ) {
client.GetLANServers();
}
/*
==================
idAsyncNetwork::ListServers_f
==================
*/
void idAsyncNetwork::ListServers_f( const idCmdArgs &args ) {
client.ListServers();
}
/*
==================
idAsyncNetwork::RemoteConsole_f
==================
*/
void idAsyncNetwork::RemoteConsole_f( const idCmdArgs &args ) {
client.RemoteConsole( args.Args() );
}
/*
==================
idAsyncNetwork::Heartbeat_f
==================
*/
void idAsyncNetwork::Heartbeat_f( const idCmdArgs &args ) {
if ( !server.IsActive() ) {
common->Printf( "server is not running\n" );
return;
}
server.MasterHeartbeat( true );
}
/*
==================
idAsyncNetwork::Kick_f
==================
*/
void idAsyncNetwork::Kick_f( const idCmdArgs &args ) {
idStr clientId;
int iclient;
if ( !server.IsActive() ) {
common->Printf( "server is not running\n" );
return;
}
clientId = args.Argv( 1 );
if ( !clientId.IsNumeric() ) {
common->Printf( "usage: kick <client number>\n" );
return;
}
iclient = atoi( clientId );
if ( server.GetLocalClientNum() == iclient ) {
common->Printf( "can't kick the host\n" );
return;
}
server.DropClient( iclient, "#str_07134" );
}
/*
==================
idAsyncNetwork::GetNETServers
==================
*/
void idAsyncNetwork::GetNETServers( ) {
client.GetNETServers();
}
/*
==================
idAsyncNetwork::CheckNewVersion_f
==================
*/
void idAsyncNetwork::CheckNewVersion_f( const idCmdArgs &args ) {
client.SendVersionCheck();
}
/*
==================
idAsyncNetwork::ExecuteSessionCommand
==================
*/
void idAsyncNetwork::ExecuteSessionCommand( const char *sessCmd ) {
if ( sessCmd[ 0 ] ) {
if ( !idStr::Icmp( sessCmd, "game_startmenu" ) ) {
session->SetGUI( game->StartMenu(), NULL );
}
}
}
/*
=================
idAsyncNetwork::UpdateUI_f
=================
*/
void idAsyncNetwork::UpdateUI_f( const idCmdArgs &args ) {
if ( args.Argc() != 2 ) {
common->Warning( "idAsyncNetwork::UpdateUI_f: wrong arguments\n" );
return;
}
if ( !server.IsActive() ) {
common->Warning( "idAsyncNetwork::UpdateUI_f: server is not active\n" );
return;
}
int clientNum = atoi( args.Args( 1 ) );
server.UpdateUI( clientNum );
}
/*
===============
idAsyncNetwork::BuildInvalidKeyMsg
===============
*/
void idAsyncNetwork::BuildInvalidKeyMsg( idStr &msg, bool valid[ 2 ] ) {
if ( !valid[ 0 ] ) {
msg += common->GetLanguageDict()->GetString( "#str_07194" );
}
if ( fileSystem->HasD3XP() && !valid[ 1 ] ) {
if ( msg.Length() ) {
msg += "\n";
}
msg += common->GetLanguageDict()->GetString( "#str_07195" );
}
msg += "\n";
msg += common->GetLanguageDict()->GetString( "#str_04304" );
}

View File

@@ -0,0 +1,219 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __ASYNCNETWORK_H__
#define __ASYNCNETWORK_H__
/*
DOOM III gold: 33
1.1 beta patch: 34
1.1 patch: 35
1.2 XP: 36-39
1.3 patch: 40
1.3.1: 41
*/
const int ASYNC_PROTOCOL_MINOR = 41;
const int ASYNC_PROTOCOL_VERSION = ( ASYNC_PROTOCOL_MAJOR << 16 ) + ASYNC_PROTOCOL_MINOR;
#define MAJOR_VERSION(v) ( v >> 16 )
const int MAX_ASYNC_CLIENTS = 32;
const int MAX_USERCMD_BACKUP = 256;
const int MAX_USERCMD_DUPLICATION = 25;
const int MAX_USERCMD_RELAY = 10;
// index 0 is hardcoded to be the idnet master
// which leaves 4 to user customization
const int MAX_MASTER_SERVERS = 5;
const int MAX_NICKLEN = 32;
// max number of servers that will be scanned for at a single IP address
const int MAX_SERVER_PORTS = 8;
// special game init ids
const int GAME_INIT_ID_INVALID = -1;
const int GAME_INIT_ID_MAP_LOAD = -2;
#include "MsgChannel.h"
#include "AsyncServer.h"
#include "ServerScan.h"
#include "AsyncClient.h"
/*
===============================================================================
Asynchronous Networking.
===============================================================================
*/
// unreliable server -> client messages
enum {
SERVER_UNRELIABLE_MESSAGE_EMPTY = 0,
SERVER_UNRELIABLE_MESSAGE_PING,
SERVER_UNRELIABLE_MESSAGE_GAMEINIT,
SERVER_UNRELIABLE_MESSAGE_SNAPSHOT
};
// reliable server -> client messages
enum {
SERVER_RELIABLE_MESSAGE_PURE = 0,
SERVER_RELIABLE_MESSAGE_RELOAD,
SERVER_RELIABLE_MESSAGE_CLIENTINFO,
SERVER_RELIABLE_MESSAGE_SYNCEDCVARS,
SERVER_RELIABLE_MESSAGE_PRINT,
SERVER_RELIABLE_MESSAGE_DISCONNECT,
SERVER_RELIABLE_MESSAGE_APPLYSNAPSHOT,
SERVER_RELIABLE_MESSAGE_GAME,
SERVER_RELIABLE_MESSAGE_ENTERGAME
};
// unreliable client -> server messages
enum {
CLIENT_UNRELIABLE_MESSAGE_EMPTY = 0,
CLIENT_UNRELIABLE_MESSAGE_PINGRESPONSE,
CLIENT_UNRELIABLE_MESSAGE_USERCMD
};
// reliable client -> server messages
enum {
CLIENT_RELIABLE_MESSAGE_PURE = 0,
CLIENT_RELIABLE_MESSAGE_CLIENTINFO,
CLIENT_RELIABLE_MESSAGE_PRINT,
CLIENT_RELIABLE_MESSAGE_DISCONNECT,
CLIENT_RELIABLE_MESSAGE_GAME
};
// server print messages
enum {
SERVER_PRINT_MISC = 0,
SERVER_PRINT_BADPROTOCOL,
SERVER_PRINT_RCON,
SERVER_PRINT_GAMEDENY,
SERVER_PRINT_BADCHALLENGE
};
enum {
SERVER_DL_REDIRECT = 1,
SERVER_DL_LIST,
SERVER_DL_NONE
};
enum {
SERVER_PAK_NO = 0,
SERVER_PAK_YES,
SERVER_PAK_END
};
typedef struct master_s {
idCVar * var;
netadr_t address;
bool resolved;
} master_t;
class idAsyncNetwork {
public:
idAsyncNetwork();
static void Init( void );
static void Shutdown( void );
static bool IsActive( void ) { return ( server.IsActive() || client.IsActive() ); }
static void RunFrame( void );
static void WriteUserCmdDelta( idBitMsg &msg, const usercmd_t &cmd, const usercmd_t *base );
static void ReadUserCmdDelta( const idBitMsg &msg, usercmd_t &cmd, const usercmd_t *base );
static bool DuplicateUsercmd( const usercmd_t &previousUserCmd, usercmd_t &currentUserCmd, int frame, int time );
static bool UsercmdInputChanged( const usercmd_t &previousUserCmd, const usercmd_t &currentUserCmd );
// returns true if the corresponding master is set to something (and could be resolved)
static bool GetMasterAddress( int index, netadr_t &adr );
// get the hardcoded idnet master, equivalent to GetMasterAddress( 0, .. )
static netadr_t GetMasterAddress( void );
static void GetNETServers( );
static void ExecuteSessionCommand( const char *sessCmd );
static idAsyncServer server;
static idAsyncClient client;
static idCVar verbose; // verbose output
static idCVar allowCheats; // allow cheats
static idCVar serverDedicated; // if set run a dedicated server
static idCVar serverSnapshotDelay; // number of milliseconds between snapshots
static idCVar serverMaxClientRate; // maximum outgoing rate to clients
static idCVar clientMaxRate; // maximum rate from server requested by client
static idCVar serverMaxUsercmdRelay; // maximum number of usercmds relayed to other clients
static idCVar serverZombieTimeout; // time out in seconds for zombie clients
static idCVar serverClientTimeout; // time out in seconds for connected clients
static idCVar clientServerTimeout; // time out in seconds for server
static idCVar serverDrawClient; // the server draws the view of this client
static idCVar serverRemoteConsolePassword; // remote console password
static idCVar clientPrediction; // how many additional milliseconds the clients runs ahead
static idCVar clientMaxPrediction; // max milliseconds into the future a client can run prediction
static idCVar clientUsercmdBackup; // how many usercmds the client sends from previous frames
static idCVar clientRemoteConsoleAddress; // remote console address
static idCVar clientRemoteConsolePassword; // remote console password
static idCVar master0; // idnet master server
static idCVar master1; // 1st master server
static idCVar master2; // 2nd master server
static idCVar master3; // 3rd master server
static idCVar master4; // 4th master server
static idCVar LANServer; // LAN mode
static idCVar serverReloadEngine; // reload engine on map change instead of growing the referenced paks
static idCVar serverAllowServerMod; // let a pure server start with a different game code than what is referenced in game code
static idCVar idleServer; // serverinfo reply, indicates all clients are idle
static idCVar clientDownload; // preferred download policy
// same message used for offline check and network reply
static void BuildInvalidKeyMsg( idStr &msg, bool valid[ 2 ] );
private:
static int realTime;
static master_t masters[ MAX_MASTER_SERVERS]; // master1 etc.
static void SpawnServer_f( const idCmdArgs &args );
static void NextMap_f( const idCmdArgs &args );
static void Connect_f( const idCmdArgs &args );
static void Reconnect_f( const idCmdArgs &args );
static void GetServerInfo_f( const idCmdArgs &args );
static void GetLANServers_f( const idCmdArgs &args );
static void ListServers_f( const idCmdArgs &args );
static void RemoteConsole_f( const idCmdArgs &args );
static void Heartbeat_f( const idCmdArgs &args );
static void Kick_f( const idCmdArgs &args );
static void CheckNewVersion_f( const idCmdArgs &args );
static void UpdateUI_f( const idCmdArgs &args );
};
#endif /* !__ASYNCNETWORK_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,259 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __ASYNCSERVER_H__
#define __ASYNCSERVER_H__
/*
===============================================================================
Network Server for asynchronous networking.
===============================================================================
*/
// MAX_CHALLENGES is made large to prevent a denial of service attack that could cycle
// all of them out before legitimate users connected
const int MAX_CHALLENGES = 1024;
// if we don't hear from authorize server, assume it is down
const int AUTHORIZE_TIMEOUT = 5000;
// states for the server's authorization process
typedef enum {
CDK_WAIT = 0, // we are waiting for a confirm/deny from auth
// this is subject to timeout if we don't hear from auth
// or a permanent wait if auth said so
CDK_OK,
CDK_ONLYLAN,
CDK_PUREWAIT,
CDK_PUREOK,
CDK_MAXSTATES
} authState_t;
// states from the auth server, while the client is in CDK_WAIT
typedef enum {
AUTH_NONE = 0, // no reply yet
AUTH_OK, // this client is good
AUTH_WAIT, // wait - keep sending me srvAuth though
AUTH_DENY, // denied - don't send me anything about this client anymore
AUTH_MAXSTATES
} authReply_t;
// message from auth to be forwarded back to the client
// some are locally hardcoded to save space, auth has the possibility to send a custom reply
typedef enum {
AUTH_REPLY_WAITING = 0, // waiting on an initial reply from auth
AUTH_REPLY_UNKNOWN, // client unknown to auth
AUTH_REPLY_DENIED, // access denied
AUTH_REPLY_PRINT, // custom message
AUTH_REPLY_SRVWAIT, // auth server replied and tells us he's working on it
AUTH_REPLY_MAXSTATES
} authReplyMsg_t;
typedef struct challenge_s {
netadr_t address; // client address
int clientId; // client identification
int challenge; // challenge code
int time; // time the challenge was created
int pingTime; // time the challenge response was sent to client
bool connected; // true if the client is connected
authState_t authState; // local state regarding the client
authReply_t authReply; // cd key check replies
authReplyMsg_t authReplyMsg; // default auth messages
idStr authReplyPrint; // custom msg
char guid[12]; // guid
int OS;
} challenge_t;
typedef enum {
SCS_FREE, // can be reused for a new connection
SCS_ZOMBIE, // client has been disconnected, but don't reuse connection for a couple seconds
SCS_PUREWAIT, // client needs to update it's pure checksums before we can go further
SCS_CONNECTED, // client is connected
SCS_INGAME // client is in the game
} serverClientState_t;
typedef struct serverClient_s {
int OS;
int clientId;
serverClientState_t clientState;
int clientPrediction;
int clientAheadTime;
int clientRate;
int clientPing;
int gameInitSequence;
int gameFrame;
int gameTime;
idMsgChannel channel;
int lastConnectTime;
int lastEmptyTime;
int lastPingTime;
int lastSnapshotTime;
int lastPacketTime;
int lastInputTime;
int snapshotSequence;
int acknowledgeSnapshotSequence;
int numDuplicatedUsercmds;
char guid[12]; // Even Balance - M. Quinn
} serverClient_t;
class idAsyncServer {
public:
idAsyncServer();
bool InitPort( void );
void ClosePort( void );
void Spawn( void );
void Kill( void );
void ExecuteMapChange( void );
int GetPort( void ) const;
netadr_t GetBoundAdr( void ) const;
bool IsActive( void ) const { return active; }
int GetDelay( void ) const { return gameTimeResidual; }
int GetOutgoingRate( void ) const;
int GetIncomingRate( void ) const;
bool IsClientInGame( int clientNum ) const;
int GetClientPing( int clientNum ) const;
int GetClientPrediction( int clientNum ) const;
int GetClientTimeSinceLastPacket( int clientNum ) const;
int GetClientTimeSinceLastInput( int clientNum ) const;
int GetClientOutgoingRate( int clientNum ) const;
int GetClientIncomingRate( int clientNum ) const;
float GetClientOutgoingCompression( int clientNum ) const;
float GetClientIncomingCompression( int clientNum ) const;
float GetClientIncomingPacketLoss( int clientNum ) const;
int GetNumClients( void ) const;
int GetNumIdleClients( void ) const;
int GetLocalClientNum( void ) const { return localClientNum; }
void RunFrame( void );
void ProcessConnectionLessMessages( void );
void RemoteConsoleOutput( const char *string );
void SendReliableGameMessage( int clientNum, const idBitMsg &msg );
void SendReliableGameMessageExcluding( int clientNum, const idBitMsg &msg );
void LocalClientSendReliableMessage( const idBitMsg &msg );
void MasterHeartbeat( bool force = false );
void DropClient( int clientNum, const char *reason );
void PacifierUpdate( void );
void UpdateUI( int clientNum );
void UpdateAsyncStatsAvg( void );
void GetAsyncStatsAvgMsg( idStr &msg );
void PrintLocalServerInfo( void );
private:
bool active; // true if server is active
int realTime; // absolute time
int serverTime; // local server time
idPort serverPort; // UDP port
int serverId; // server identification
int serverDataChecksum; // checksum of the data used by the server
int localClientNum; // local client on listen server
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
serverClient_t clients[MAX_ASYNC_CLIENTS]; // clients
usercmd_t userCmds[MAX_USERCMD_BACKUP][MAX_ASYNC_CLIENTS];
int gameInitId; // game initialization identification
int gameFrame; // local game frame
int gameTime; // local game time
int gameTimeResidual; // left over time from previous frame
netadr_t rconAddress;
int nextHeartbeatTime;
int nextAsyncStatsTime;
bool serverReloadingEngine; // flip-flop to not loop over when net_serverReloadEngine is on
bool noRconOutput; // for default rcon response when command is silent
int lastAuthTime; // global for auth server timeout
// track the max outgoing rate over the last few secs to watch for spikes
// dependent on net_serverSnapshotDelay. 50ms, for a 3 seconds backlog -> 60 samples
static const int stats_numsamples = 60;
int stats_outrate[ stats_numsamples ];
int stats_current;
int stats_average_sum;
int stats_max;
int stats_max_index;
void PrintOOB( const netadr_t to, int opcode, const char *string );
void DuplicateUsercmds( int frame, int time );
void ClearClient( int clientNum );
void InitClient( int clientNum, int clientId, int clientRate );
void InitLocalClient( int clientNum );
void BeginLocalClient( void );
void LocalClientInput( void );
void CheckClientTimeouts( void );
void SendPrintBroadcast( const char *string );
void SendPrintToClient( int clientNum, const char *string );
void SendUserInfoBroadcast( int userInfoNum, const idDict &info, bool sendToAll = false );
void SendUserInfoToClient( int clientNum, int userInfoNum, const idDict &info );
void SendSyncedCvarsBroadcast( const idDict &cvars );
void SendSyncedCvarsToClient( int clientNum, const idDict &cvars );
void SendApplySnapshotToClient( int clientNum, int sequence );
bool SendEmptyToClient( int clientNum, bool force = false );
bool SendPingToClient( int clientNum );
void SendGameInitToClient( int clientNum );
bool SendSnapshotToClient( int clientNum );
void ProcessUnreliableClientMessage( int clientNum, const idBitMsg &msg );
void ProcessReliableClientMessages( int clientNum );
void ProcessChallengeMessage( const netadr_t from, const idBitMsg &msg );
void ProcessConnectMessage( const netadr_t from, const idBitMsg &msg );
void ProcessRemoteConsoleMessage( const netadr_t from, const idBitMsg &msg );
void ProcessGetInfoMessage( const netadr_t from, const idBitMsg &msg );
bool ConnectionlessMessage( const netadr_t from, const idBitMsg &msg );
bool ProcessMessage( const netadr_t from, idBitMsg &msg );
void ProcessAuthMessage( const idBitMsg &msg );
bool SendPureServerMessage( const netadr_t to, int OS ); // returns false if no pure paks on the list
void ProcessPureMessage( const netadr_t from, const idBitMsg &msg );
int ValidateChallenge( const netadr_t from, int challenge, int clientId ); // returns -1 if validate failed
bool SendReliablePureToClient( int clientNum );
void ProcessReliablePure( int clientNum, const idBitMsg &msg );
bool VerifyChecksumMessage( int clientNum, const netadr_t *from, const idBitMsg &msg, idStr &reply, int OS ); // if from is NULL, clientNum is used for error messages
void SendReliableMessage( int clientNum, const idBitMsg &msg ); // checks for overflow and disconnects the faulty client
int UpdateTime( int clamp );
void SendEnterGameToClient( int clientNum );
void ProcessDownloadRequestMessage( const netadr_t from, const idBitMsg &msg );
};
#endif /* !__ASYNCSERVER_H__ */

View File

@@ -0,0 +1,790 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "MsgChannel.h"
/*
packet header
-------------
2 bytes id
4 bytes outgoing sequence. high bit will be set if this is a fragmented message.
2 bytes optional fragment start byte if fragment bit is set.
2 bytes optional fragment length if fragment bit is set. if < FRAGMENT_SIZE, this is the last fragment.
If the id is -1, the packet should be handled as an out-of-band
message instead of as part of the message channel.
All fragments will have the same sequence numbers.
*/
#define MAX_PACKETLEN 1400 // max size of a network packet
#define FRAGMENT_SIZE (MAX_PACKETLEN - 100)
#define FRAGMENT_BIT (1<<31)
idCVar net_channelShowPackets( "net_channelShowPackets", "0", CVAR_SYSTEM | CVAR_BOOL, "show all packets" );
idCVar net_channelShowDrop( "net_channelShowDrop", "0", CVAR_SYSTEM | CVAR_BOOL, "show dropped packets" );
/*
===============
idMsgQueue::idMsgQueue
===============
*/
idMsgQueue::idMsgQueue( void ) {
Init( 0 );
}
/*
===============
idMsgQueue::Init
===============
*/
void idMsgQueue::Init( int sequence ) {
first = last = sequence;
startIndex = endIndex = 0;
}
/*
===============
idMsgQueue::Add
===============
*/
bool idMsgQueue::Add( const byte *data, const int size ) {
if ( GetSpaceLeft() < size + 8 ) {
return false;
}
int sequence = last;
WriteShort( size );
WriteLong( sequence );
WriteData( data, size );
last++;
return true;
}
/*
===============
idMsgQueue::Get
===============
*/
bool idMsgQueue::Get( byte *data, int &size ) {
if ( first == last ) {
size = 0;
return false;
}
int sequence;
size = ReadShort();
sequence = ReadLong();
ReadData( data, size );
assert( sequence == first );
first++;
return true;
}
/*
===============
idMsgQueue::GetTotalSize
===============
*/
int idMsgQueue::GetTotalSize( void ) const {
if ( startIndex <= endIndex ) {
return ( endIndex - startIndex );
} else {
return ( sizeof( buffer ) - startIndex + endIndex );
}
}
/*
===============
idMsgQueue::GetSpaceLeft
===============
*/
int idMsgQueue::GetSpaceLeft( void ) const {
if ( startIndex <= endIndex ) {
return sizeof( buffer ) - ( endIndex - startIndex ) - 1;
} else {
return ( startIndex - endIndex ) - 1;
}
}
/*
===============
idMsgQueue::CopyToBuffer
===============
*/
void idMsgQueue::CopyToBuffer( byte *buf ) const {
if ( startIndex <= endIndex ) {
memcpy( buf, buffer + startIndex, endIndex - startIndex );
} else {
memcpy( buf, buffer + startIndex, sizeof( buffer ) - startIndex );
memcpy( buf + sizeof( buffer ) - startIndex, buffer, endIndex );
}
}
/*
===============
idMsgQueue::WriteByte
===============
*/
void idMsgQueue::WriteByte( byte b ) {
buffer[endIndex] = b;
endIndex = ( endIndex + 1 ) & ( MAX_MSG_QUEUE_SIZE - 1 );
}
/*
===============
idMsgQueue::ReadByte
===============
*/
byte idMsgQueue::ReadByte( void ) {
byte b = buffer[startIndex];
startIndex = ( startIndex + 1 ) & ( MAX_MSG_QUEUE_SIZE - 1 );
return b;
}
/*
===============
idMsgQueue::WriteShort
===============
*/
void idMsgQueue::WriteShort( int s ) {
WriteByte( ( s >> 0 ) & 255 );
WriteByte( ( s >> 8 ) & 255 );
}
/*
===============
idMsgQueue::ReadShort
===============
*/
int idMsgQueue::ReadShort( void ) {
return ReadByte() | ( ReadByte() << 8 );
}
/*
===============
idMsgQueue::WriteLong
===============
*/
void idMsgQueue::WriteLong( int l ) {
WriteByte( ( l >> 0 ) & 255 );
WriteByte( ( l >> 8 ) & 255 );
WriteByte( ( l >> 16 ) & 255 );
WriteByte( ( l >> 24 ) & 255 );
}
/*
===============
idMsgQueue::ReadLong
===============
*/
int idMsgQueue::ReadLong( void ) {
return ReadByte() | ( ReadByte() << 8 ) | ( ReadByte() << 16 ) | ( ReadByte() << 24 );
}
/*
===============
idMsgQueue::WriteData
===============
*/
void idMsgQueue::WriteData( const byte *data, const int size ) {
for ( int i = 0; i < size; i++ ) {
WriteByte( data[i] );
}
}
/*
===============
idMsgQueue::ReadData
===============
*/
void idMsgQueue::ReadData( byte *data, const int size ) {
if ( data ) {
for ( int i = 0; i < size; i++ ) {
data[i] = ReadByte();
}
} else {
for ( int i = 0; i < size; i++ ) {
ReadByte();
}
}
}
/*
===============
idMsgChannel::idMsgChannel
===============
*/
idMsgChannel::idMsgChannel() {
id = -1;
}
/*
==============
idMsgChannel::Init
Opens a channel to a remote system.
==============
*/
void idMsgChannel::Init( const netadr_t adr, const int id ) {
this->remoteAddress = adr;
this->id = id;
this->maxRate = 50000;
this->compressor = idCompressor::AllocRunLength_ZeroBased();
lastSendTime = 0;
lastDataBytes = 0;
outgoingRateTime = 0;
outgoingRateBytes = 0;
incomingRateTime = 0;
incomingRateBytes = 0;
incomingReceivedPackets = 0.0f;
incomingDroppedPackets = 0.0f;
incomingPacketLossTime = 0;
outgoingCompression = 0.0f;
incomingCompression = 0.0f;
outgoingSequence = 1;
incomingSequence = 0;
unsentFragments = false;
unsentFragmentStart = 0;
fragmentSequence = 0;
fragmentLength = 0;
reliableSend.Init( 1 );
reliableReceive.Init( 0 );
}
/*
===============
idMsgChannel::Shutdown
================
*/
void idMsgChannel::Shutdown( void ) {
delete compressor;
compressor = NULL;
}
/*
=================
idMsgChannel::ResetRate
=================
*/
void idMsgChannel::ResetRate( void ) {
lastSendTime = 0;
lastDataBytes = 0;
outgoingRateTime = 0;
outgoingRateBytes = 0;
incomingRateTime = 0;
incomingRateBytes = 0;
}
/*
=================
idMsgChannel::ReadyToSend
=================
*/
bool idMsgChannel::ReadyToSend( const int time ) const {
int deltaTime;
if ( !maxRate ) {
return true;
}
deltaTime = time - lastSendTime;
if ( deltaTime > 1000 ) {
return true;
}
return ( ( lastDataBytes - ( deltaTime * maxRate ) / 1000 ) <= 0 );
}
/*
===============
idMsgChannel::WriteMessageData
================
*/
void idMsgChannel::WriteMessageData( idBitMsg &out, const idBitMsg &msg ) {
idBitMsg tmp;
byte tmpBuf[MAX_MESSAGE_SIZE];
tmp.Init( tmpBuf, sizeof( tmpBuf ) );
// write acknowledgement of last received reliable message
tmp.WriteLong( reliableReceive.GetLast() );
// write reliable messages
reliableSend.CopyToBuffer( tmp.GetData() + tmp.GetSize() );
tmp.SetSize( tmp.GetSize() + reliableSend.GetTotalSize() );
tmp.WriteShort( 0 );
// write data
tmp.WriteData( msg.GetData(), msg.GetSize() );
// write message size
out.WriteShort( tmp.GetSize() );
// compress message
idFile_BitMsg file( out );
compressor->Init( &file, true, 3 );
compressor->Write( tmp.GetData(), tmp.GetSize() );
compressor->FinishCompress();
outgoingCompression = compressor->GetCompressionRatio();
}
/*
===============
idMsgChannel::ReadMessageData
================
*/
bool idMsgChannel::ReadMessageData( idBitMsg &out, const idBitMsg &msg ) {
int reliableAcknowledge, reliableMessageSize, reliableSequence;
// read message size
out.SetSize( msg.ReadShort() );
// decompress message
idFile_BitMsg file( msg );
compressor->Init( &file, false, 3 );
compressor->Read( out.GetData(), out.GetSize() );
incomingCompression = compressor->GetCompressionRatio();
out.BeginReading();
// read acknowledgement of sent reliable messages
reliableAcknowledge = out.ReadLong();
// remove acknowledged reliable messages
while( reliableSend.GetFirst() <= reliableAcknowledge ) {
if ( !reliableSend.Get( NULL, reliableMessageSize ) ) {
break;
}
}
// read reliable messages
reliableMessageSize = out.ReadShort();
while( reliableMessageSize != 0 ) {
if ( reliableMessageSize <= 0 || reliableMessageSize > out.GetSize() - out.GetReadCount() ) {
common->Printf( "%s: bad reliable message\n", Sys_NetAdrToString( remoteAddress ) );
return false;
}
reliableSequence = out.ReadLong();
if ( reliableSequence == reliableReceive.GetLast() + 1 ) {
reliableReceive.Add( out.GetData() + out.GetReadCount(), reliableMessageSize );
}
out.ReadData( NULL, reliableMessageSize );
reliableMessageSize = out.ReadShort();
}
return true;
}
/*
=================
idMsgChannel::SendNextFragment
Sends one fragment of the current message.
=================
*/
void idMsgChannel::SendNextFragment( idPort &port, const int time ) {
idBitMsg msg;
byte msgBuf[MAX_PACKETLEN];
int fragLength;
if ( remoteAddress.type == NA_BAD ) {
return;
}
if ( !unsentFragments ) {
return;
}
// write the packet
msg.Init( msgBuf, sizeof( msgBuf ) );
msg.WriteShort( id );
msg.WriteLong( outgoingSequence | FRAGMENT_BIT );
fragLength = FRAGMENT_SIZE;
if ( unsentFragmentStart + fragLength > unsentMsg.GetSize() ) {
fragLength = unsentMsg.GetSize() - unsentFragmentStart;
}
msg.WriteShort( unsentFragmentStart );
msg.WriteShort( fragLength );
msg.WriteData( unsentMsg.GetData() + unsentFragmentStart, fragLength );
// send the packet
port.SendPacket( remoteAddress, msg.GetData(), msg.GetSize() );
// update rate control variables
UpdateOutgoingRate( time, msg.GetSize() );
if ( net_channelShowPackets.GetBool() ) {
common->Printf( "%d send %4i : s = %i fragment = %i,%i\n", id, msg.GetSize(), outgoingSequence - 1, unsentFragmentStart, fragLength );
}
unsentFragmentStart += fragLength;
// this exit condition is a little tricky, because a packet
// that is exactly the fragment length still needs to send
// a second packet of zero length so that the other side
// can tell there aren't more to follow
if ( unsentFragmentStart == unsentMsg.GetSize() && fragLength != FRAGMENT_SIZE ) {
outgoingSequence++;
unsentFragments = false;
}
}
/*
===============
idMsgChannel::SendMessage
Sends a message to a connection, fragmenting if necessary
A 0 length will still generate a packet.
================
*/
int idMsgChannel::SendMessage( idPort &port, const int time, const idBitMsg &msg ) {
int totalLength;
if ( remoteAddress.type == NA_BAD ) {
return -1;
}
if ( unsentFragments ) {
common->Error( "idMsgChannel::SendMessage: called with unsent fragments left" );
return -1;
}
totalLength = 4 + reliableSend.GetTotalSize() + 4 + msg.GetSize();
if ( totalLength > MAX_MESSAGE_SIZE ) {
common->Printf( "idMsgChannel::SendMessage: message too large, length = %i\n", totalLength );
return -1;
}
unsentMsg.Init( unsentBuffer, sizeof( unsentBuffer ) );
unsentMsg.BeginWriting();
// fragment large messages
if ( totalLength >= FRAGMENT_SIZE ) {
unsentFragments = true;
unsentFragmentStart = 0;
// write out the message data
WriteMessageData( unsentMsg, msg );
// send the first fragment now
SendNextFragment( port, time );
return outgoingSequence;
}
// write the header
unsentMsg.WriteShort( id );
unsentMsg.WriteLong( outgoingSequence );
// write out the message data
WriteMessageData( unsentMsg, msg );
// send the packet
port.SendPacket( remoteAddress, unsentMsg.GetData(), unsentMsg.GetSize() );
// update rate control variables
UpdateOutgoingRate( time, unsentMsg.GetSize() );
if ( net_channelShowPackets.GetBool() ) {
common->Printf( "%d send %4i : s = %i ack = %i\n", id, unsentMsg.GetSize(), outgoingSequence - 1, incomingSequence );
}
outgoingSequence++;
return ( outgoingSequence - 1 );
}
/*
=================
idMsgChannel::Process
Returns false if the message should not be processed due to being out of order or a fragment.
msg must be large enough to hold MAX_MESSAGE_SIZE, because if this is the final
fragment of a multi-part message, the entire thing will be copied out.
=================
*/
bool idMsgChannel::Process( const netadr_t from, int time, idBitMsg &msg, int &sequence ) {
int fragStart, fragLength, dropped;
bool fragmented;
idBitMsg fragMsg;
// the IP port can't be used to differentiate them, because
// some address translating routers periodically change UDP
// port assignments
if ( remoteAddress.port != from.port ) {
common->Printf( "idMsgChannel::Process: fixing up a translated port\n" );
remoteAddress.port = from.port;
}
// update incoming rate
UpdateIncomingRate( time, msg.GetSize() );
// get sequence numbers
sequence = msg.ReadLong();
// check for fragment information
if ( sequence & FRAGMENT_BIT ) {
sequence &= ~FRAGMENT_BIT;
fragmented = true;
} else {
fragmented = false;
}
// read the fragment information
if ( fragmented ) {
fragStart = msg.ReadShort();
fragLength = msg.ReadShort();
} else {
fragStart = 0; // stop warning message
fragLength = 0;
}
if ( net_channelShowPackets.GetBool() ) {
if ( fragmented ) {
common->Printf( "%d recv %4i : s = %i fragment = %i,%i\n", id, msg.GetSize(), sequence, fragStart, fragLength );
} else {
common->Printf( "%d recv %4i : s = %i\n", id, msg.GetSize(), sequence );
}
}
//
// discard out of order or duplicated packets
//
if ( sequence <= incomingSequence ) {
if ( net_channelShowDrop.GetBool() || net_channelShowPackets.GetBool() ) {
common->Printf( "%s: out of order packet %i at %i\n", Sys_NetAdrToString( remoteAddress ), sequence, incomingSequence );
}
return false;
}
//
// dropped packets don't keep this message from being used
//
dropped = sequence - (incomingSequence+1);
if ( dropped > 0 ) {
if ( net_channelShowDrop.GetBool() || net_channelShowPackets.GetBool() ) {
common->Printf( "%s: dropped %i packets at %i\n", Sys_NetAdrToString( remoteAddress ), dropped, sequence );
}
UpdatePacketLoss( time, 0, dropped );
}
//
// if the message is fragmented
//
if ( fragmented ) {
// make sure we have the correct sequence number
if ( sequence != fragmentSequence ) {
fragmentSequence = sequence;
fragmentLength = 0;
}
// if we missed a fragment, dump the message
if ( fragStart != fragmentLength ) {
if ( net_channelShowDrop.GetBool() || net_channelShowPackets.GetBool() ) {
common->Printf( "%s: dropped a message fragment at seq %d\n", Sys_NetAdrToString( remoteAddress ), sequence );
}
// we can still keep the part that we have so far,
// so we don't need to clear fragmentLength
UpdatePacketLoss( time, 0, 1 );
return false;
}
// copy the fragment to the fragment buffer
if ( fragLength < 0 || fragLength > msg.GetRemaingData() || fragmentLength + fragLength > sizeof( fragmentBuffer ) ) {
if ( net_channelShowDrop.GetBool() || net_channelShowPackets.GetBool() ) {
common->Printf( "%s: illegal fragment length\n", Sys_NetAdrToString( remoteAddress ) );
}
UpdatePacketLoss( time, 0, 1 );
return false;
}
memcpy( fragmentBuffer + fragmentLength, msg.GetData() + msg.GetReadCount(), fragLength );
fragmentLength += fragLength;
UpdatePacketLoss( time, 1, 0 );
// if this wasn't the last fragment, don't process anything
if ( fragLength == FRAGMENT_SIZE ) {
return false;
}
} else {
memcpy( fragmentBuffer, msg.GetData() + msg.GetReadCount(), msg.GetRemaingData() );
fragmentLength = msg.GetRemaingData();
UpdatePacketLoss( time, 1, 0 );
}
fragMsg.Init( fragmentBuffer, fragmentLength );
fragMsg.SetSize( fragmentLength );
fragMsg.BeginReading();
incomingSequence = sequence;
// read the message data
if ( !ReadMessageData( msg, fragMsg ) ) {
return false;
}
return true;
}
/*
=================
idMsgChannel::SendReliableMessage
=================
*/
bool idMsgChannel::SendReliableMessage( const idBitMsg &msg ) {
bool result;
assert( remoteAddress.type != NA_BAD );
if ( remoteAddress.type == NA_BAD ) {
return false;
}
result = reliableSend.Add( msg.GetData(), msg.GetSize() );
if ( !result ) {
common->Warning( "idMsgChannel::SendReliableMessage: overflowed" );
return false;
}
return result;
}
/*
=================
idMsgChannel::GetReliableMessage
=================
*/
bool idMsgChannel::GetReliableMessage( idBitMsg &msg ) {
int size;
bool result;
result = reliableReceive.Get( msg.GetData(), size );
msg.SetSize( size );
msg.BeginReading();
return result;
}
/*
===============
idMsgChannel::ClearReliableMessages
================
*/
void idMsgChannel::ClearReliableMessages( void ) {
reliableSend.Init( 1 );
reliableReceive.Init( 0 );
}
/*
=================
idMsgChannel::UpdateOutgoingRate
=================
*/
void idMsgChannel::UpdateOutgoingRate( const int time, const int size ) {
// update the outgoing rate control variables
int deltaTime = time - lastSendTime;
if ( deltaTime > 1000 ) {
lastDataBytes = 0;
} else {
lastDataBytes -= ( deltaTime * maxRate ) / 1000;
if ( lastDataBytes < 0 ) {
lastDataBytes = 0;
}
}
lastDataBytes += size;
lastSendTime = time;
// update outgoing rate variables
if ( time - outgoingRateTime > 1000 ) {
outgoingRateBytes -= outgoingRateBytes * ( time - outgoingRateTime - 1000 ) / 1000;
if ( outgoingRateBytes < 0 ) {
outgoingRateBytes = 0;
}
}
outgoingRateTime = time - 1000;
outgoingRateBytes += size;
}
/*
=================
idMsgChannel::UpdateIncomingRate
=================
*/
void idMsgChannel::UpdateIncomingRate( const int time, const int size ) {
// update incoming rate variables
if ( time - incomingRateTime > 1000 ) {
incomingRateBytes -= incomingRateBytes * ( time - incomingRateTime - 1000 ) / 1000;
if ( incomingRateBytes < 0 ) {
incomingRateBytes = 0;
}
}
incomingRateTime = time - 1000;
incomingRateBytes += size;
}
/*
=================
idMsgChannel::UpdatePacketLoss
=================
*/
void idMsgChannel::UpdatePacketLoss( const int time, const int numReceived, const int numDropped ) {
// update incoming packet loss variables
if ( time - incomingPacketLossTime > 5000 ) {
float scale = ( time - incomingPacketLossTime - 5000 ) * ( 1.0f / 5000.0f );
incomingReceivedPackets -= incomingReceivedPackets * scale;
if ( incomingReceivedPackets < 0.0f ) {
incomingReceivedPackets = 0.0f;
}
incomingDroppedPackets -= incomingDroppedPackets * scale;
if ( incomingDroppedPackets < 0.0f ) {
incomingDroppedPackets = 0.0f;
}
}
incomingPacketLossTime = time - 5000;
incomingReceivedPackets += numReceived;
incomingDroppedPackets += numDropped;
}
/*
=================
idMsgChannel::GetIncomingPacketLoss
=================
*/
float idMsgChannel::GetIncomingPacketLoss( void ) const {
if ( incomingReceivedPackets == 0.0f && incomingDroppedPackets == 0.0f ) {
return 0.0f;
}
return incomingDroppedPackets * 100.0f / ( incomingReceivedPackets + incomingDroppedPackets );
}

View File

@@ -0,0 +1,201 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __MSGCHANNEL_H__
#define __MSGCHANNEL_H__
/*
===============================================================================
Network channel.
Handles message fragmentation and out of order / duplicate suppression.
Unreliable messages are not garrenteed to arrive but when they do, they
arrive in order and without duplicates. Reliable messages always arrive,
and they also arrive in order without duplicates. Reliable messages piggy
back on unreliable messages. As such an unreliable message stream is
required for the reliable messages to be delivered.
===============================================================================
*/
#define MAX_MESSAGE_SIZE 16384 // max length of a message, which may
// be fragmented into multiple packets
#define CONNECTIONLESS_MESSAGE_ID -1 // id for connectionless messages
#define CONNECTIONLESS_MESSAGE_ID_MASK 0x7FFF // value to mask away connectionless message id
#define MAX_MSG_QUEUE_SIZE 16384 // must be a power of 2
class idMsgQueue {
public:
idMsgQueue();
void Init( int sequence );
bool Add( const byte *data, const int size );
bool Get( byte *data, int &size );
int GetTotalSize( void ) const;
int GetSpaceLeft( void ) const;
int GetFirst( void ) const { return first; }
int GetLast( void ) const { return last; }
void CopyToBuffer( byte *buf ) const;
private:
byte buffer[MAX_MSG_QUEUE_SIZE];
int first; // sequence number of first message in queue
int last; // sequence number of last message in queue
int startIndex; // index pointing to the first byte of the first message
int endIndex; // index pointing to the first byte after the last message
void WriteByte( byte b );
byte ReadByte( void );
void WriteShort( int s );
int ReadShort( void );
void WriteLong( int l );
int ReadLong( void );
void WriteData( const byte *data, const int size );
void ReadData( byte *data, const int size );
};
class idMsgChannel {
public:
idMsgChannel();
void Init( const netadr_t adr, const int id );
void Shutdown( void );
void ResetRate( void );
// Sets the maximum outgoing rate.
void SetMaxOutgoingRate( int rate ) { maxRate = rate; }
// Gets the maximum outgoing rate.
int GetMaxOutgoingRate( void ) { return maxRate; }
// Returns the address of the entity at the other side of the channel.
netadr_t GetRemoteAddress( void ) const { return remoteAddress; }
// Returns the average outgoing rate over the last second.
int GetOutgoingRate( void ) const { return outgoingRateBytes; }
// Returns the average incoming rate over the last second.
int GetIncomingRate( void ) const { return incomingRateBytes; }
// Returns the average outgoing compression ratio over the last second.
float GetOutgoingCompression( void ) const { return outgoingCompression; }
// Returns the average incoming compression ratio over the last second.
float GetIncomingCompression( void ) const { return incomingCompression; }
// Returns the average incoming packet loss over the last 5 seconds.
float GetIncomingPacketLoss( void ) const;
// Returns true if the channel is ready to send new data based on the maximum rate.
bool ReadyToSend( const int time ) const;
// Sends an unreliable message, in order and without duplicates.
int SendMessage( idPort &port, const int time, const idBitMsg &msg );
// Sends the next fragment if the last message was too large to send at once.
void SendNextFragment( idPort &port, const int time );
// Returns true if there are unsent fragments left.
bool UnsentFragmentsLeft( void ) const { return unsentFragments; }
// Processes the incoming message. Returns true when a complete message
// is ready for further processing. In that case the read pointer of msg
// points to the first byte ready for reading, and sequence is set to
// the sequence number of the message.
bool Process( const netadr_t from, int time, idBitMsg &msg, int &sequence );
// Sends a reliable message, in order and without duplicates.
bool SendReliableMessage( const idBitMsg &msg );
// Returns true if a new reliable message is available and stores the message.
bool GetReliableMessage( idBitMsg &msg );
// Removes any pending outgoing or incoming reliable messages.
void ClearReliableMessages( void );
private:
netadr_t remoteAddress; // address of remote host
int id; // our identification used instead of port number
int maxRate; // maximum number of bytes that may go out per second
idCompressor * compressor; // compressor used for data compression
// variables to control the outgoing rate
int lastSendTime; // last time data was sent out
int lastDataBytes; // bytes left to send at last send time
// variables to keep track of the rate
int outgoingRateTime;
int outgoingRateBytes;
int incomingRateTime;
int incomingRateBytes;
// variables to keep track of the compression ratio
float outgoingCompression;
float incomingCompression;
// variables to keep track of the incoming packet loss
float incomingReceivedPackets;
float incomingDroppedPackets;
int incomingPacketLossTime;
// sequencing variables
int outgoingSequence;
int incomingSequence;
// outgoing fragment buffer
bool unsentFragments;
int unsentFragmentStart;
byte unsentBuffer[MAX_MESSAGE_SIZE];
idBitMsg unsentMsg;
// incoming fragment assembly buffer
int fragmentSequence;
int fragmentLength;
byte fragmentBuffer[MAX_MESSAGE_SIZE];
// reliable messages
idMsgQueue reliableSend;
idMsgQueue reliableReceive;
private:
void WriteMessageData( idBitMsg &out, const idBitMsg &msg );
bool ReadMessageData( idBitMsg &out, const idBitMsg &msg );
void UpdateOutgoingRate( const int time, const int size );
void UpdateIncomingRate( const int time, const int size );
void UpdatePacketLoss( const int time, const int numReceived, const int numDropped );
};
#endif /* !__MSGCHANNEL_H__ */

View File

@@ -0,0 +1,215 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "NetworkSystem.h"
idNetworkSystem networkSystemLocal;
idNetworkSystem * networkSystem = &networkSystemLocal;
/*
==================
idNetworkSystem::ServerSendReliableMessage
==================
*/
void idNetworkSystem::ServerSendReliableMessage( int clientNum, const idBitMsg &msg ) {
if ( idAsyncNetwork::server.IsActive() ) {
idAsyncNetwork::server.SendReliableGameMessage( clientNum, msg );
}
}
/*
==================
idNetworkSystem::ServerSendReliableMessageExcluding
==================
*/
void idNetworkSystem::ServerSendReliableMessageExcluding( int clientNum, const idBitMsg &msg ) {
if ( idAsyncNetwork::server.IsActive() ) {
idAsyncNetwork::server.SendReliableGameMessageExcluding( clientNum, msg );
}
}
/*
==================
idNetworkSystem::ServerGetClientPing
==================
*/
int idNetworkSystem::ServerGetClientPing( int clientNum ) {
if ( idAsyncNetwork::server.IsActive() ) {
return idAsyncNetwork::server.GetClientPing( clientNum );
}
return 0;
}
/*
==================
idNetworkSystem::ServerGetClientPrediction
==================
*/
int idNetworkSystem::ServerGetClientPrediction( int clientNum ) {
if ( idAsyncNetwork::server.IsActive() ) {
return idAsyncNetwork::server.GetClientPrediction( clientNum );
}
return 0;
}
/*
==================
idNetworkSystem::ServerGetClientTimeSinceLastPacket
==================
*/
int idNetworkSystem::ServerGetClientTimeSinceLastPacket( int clientNum ) {
if ( idAsyncNetwork::server.IsActive() ) {
return idAsyncNetwork::server.GetClientTimeSinceLastPacket( clientNum );
}
return 0;
}
/*
==================
idNetworkSystem::ServerGetClientTimeSinceLastInput
==================
*/
int idNetworkSystem::ServerGetClientTimeSinceLastInput( int clientNum ) {
if ( idAsyncNetwork::server.IsActive() ) {
return idAsyncNetwork::server.GetClientTimeSinceLastInput( clientNum );
}
return 0;
}
/*
==================
idNetworkSystem::ServerGetClientOutgoingRate
==================
*/
int idNetworkSystem::ServerGetClientOutgoingRate( int clientNum ) {
if ( idAsyncNetwork::server.IsActive() ) {
return idAsyncNetwork::server.GetClientOutgoingRate( clientNum );
}
return 0;
}
/*
==================
idNetworkSystem::ServerGetClientIncomingRate
==================
*/
int idNetworkSystem::ServerGetClientIncomingRate( int clientNum ) {
if ( idAsyncNetwork::server.IsActive() ) {
return idAsyncNetwork::server.GetClientIncomingRate( clientNum );
}
return 0;
}
/*
==================
idNetworkSystem::ServerGetClientIncomingPacketLoss
==================
*/
float idNetworkSystem::ServerGetClientIncomingPacketLoss( int clientNum ) {
if ( idAsyncNetwork::server.IsActive() ) {
return idAsyncNetwork::server.GetClientIncomingPacketLoss( clientNum );
}
return 0.0f;
}
/*
==================
idNetworkSystem::ClientSendReliableMessage
==================
*/
void idNetworkSystem::ClientSendReliableMessage( const idBitMsg &msg ) {
if ( idAsyncNetwork::client.IsActive() ) {
idAsyncNetwork::client.SendReliableGameMessage( msg );
} else if ( idAsyncNetwork::server.IsActive() ) {
idAsyncNetwork::server.LocalClientSendReliableMessage( msg );
}
}
/*
==================
idNetworkSystem::ClientGetPrediction
==================
*/
int idNetworkSystem::ClientGetPrediction( void ) {
if ( idAsyncNetwork::client.IsActive() ) {
return idAsyncNetwork::client.GetPrediction();
}
return 0;
}
/*
==================
idNetworkSystem::ClientGetTimeSinceLastPacket
==================
*/
int idNetworkSystem::ClientGetTimeSinceLastPacket( void ) {
if ( idAsyncNetwork::client.IsActive() ) {
return idAsyncNetwork::client.GetTimeSinceLastPacket();
}
return 0;
}
/*
==================
idNetworkSystem::ClientGetOutgoingRate
==================
*/
int idNetworkSystem::ClientGetOutgoingRate( void ) {
if ( idAsyncNetwork::client.IsActive() ) {
return idAsyncNetwork::client.GetOutgoingRate();
}
return 0;
}
/*
==================
idNetworkSystem::ClientGetIncomingRate
==================
*/
int idNetworkSystem::ClientGetIncomingRate( void ) {
if ( idAsyncNetwork::client.IsActive() ) {
return idAsyncNetwork::client.GetIncomingRate();
}
return 0;
}
/*
==================
idNetworkSystem::ClientGetIncomingPacketLoss
==================
*/
float idNetworkSystem::ClientGetIncomingPacketLoss( void ) {
if ( idAsyncNetwork::client.IsActive() ) {
return idAsyncNetwork::client.GetIncomingPacketLoss();
}
return 0.0f;
}

View File

@@ -0,0 +1,65 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __NETWORKSYSTEM_H__
#define __NETWORKSYSTEM_H__
/*
===============================================================================
Network System.
===============================================================================
*/
class idNetworkSystem {
public:
virtual ~idNetworkSystem( void ) {}
virtual void ServerSendReliableMessage( int clientNum, const idBitMsg &msg );
virtual void ServerSendReliableMessageExcluding( int clientNum, const idBitMsg &msg );
virtual int ServerGetClientPing( int clientNum );
virtual int ServerGetClientPrediction( int clientNum );
virtual int ServerGetClientTimeSinceLastPacket( int clientNum );
virtual int ServerGetClientTimeSinceLastInput( int clientNum );
virtual int ServerGetClientOutgoingRate( int clientNum );
virtual int ServerGetClientIncomingRate( int clientNum );
virtual float ServerGetClientIncomingPacketLoss( int clientNum );
virtual void ClientSendReliableMessage( const idBitMsg &msg );
virtual int ClientGetPrediction( void );
virtual int ClientGetTimeSinceLastPacket( void );
virtual int ClientGetOutgoingRate( void );
virtual int ClientGetIncomingRate( void );
virtual float ClientGetIncomingPacketLoss( void );
};
extern idNetworkSystem * networkSystem;
#endif /* !__NETWORKSYSTEM_H__ */

View File

@@ -0,0 +1,639 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
idCVar gui_filter_password( "gui_filter_password", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Password filter" );
idCVar gui_filter_players( "gui_filter_players", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Players filter" );
idCVar gui_filter_gameType( "gui_filter_gameType", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Gametype filter" );
idCVar gui_filter_idle( "gui_filter_idle", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Idle servers filter" );
idCVar gui_filter_game( "gui_filter_game", "0", CVAR_GUI | CVAR_INTEGER | CVAR_ARCHIVE, "Game filter" );
const char* l_gameTypes[] = {
"Deathmatch",
"Tourney",
"Team DM",
"Last Man",
"CTF",
NULL
};
static idServerScan *l_serverScan = NULL;
/*
================
idServerScan::idServerScan
================
*/
idServerScan::idServerScan( ) {
m_pGUI = NULL;
m_sort = SORT_PING;
m_sortAscending = true;
challenge = 0;
LocalClear();
}
/*
================
idServerScan::LocalClear
================
*/
void idServerScan::LocalClear( ) {
scan_state = IDLE;
incoming_net = false;
lan_pingtime = -1;
net_info.Clear();
net_servers.Clear();
cur_info = 0;
if ( listGUI ) {
listGUI->Clear();
}
incoming_useTimeout = false;
m_sortedServers.Clear();
}
/*
================
idServerScan::Clear
================
*/
void idServerScan::Clear( ) {
LocalClear();
idList<networkServer_t>::Clear();
}
/*
================
idServerScan::Shutdown
================
*/
void idServerScan::Shutdown( ) {
m_pGUI = NULL;
if ( listGUI ) {
listGUI->Config( NULL, NULL );
uiManager->FreeListGUI( listGUI );
listGUI = NULL;
}
screenshot.Clear();
}
/*
================
idServerScan::SetupLANScan
================
*/
void idServerScan::SetupLANScan( ) {
Clear();
GUIUpdateSelected();
scan_state = LAN_SCAN;
challenge++;
lan_pingtime = Sys_Milliseconds();
common->DPrintf( "SetupLANScan with challenge %d\n", challenge );
}
/*
================
idServerScan::InfoResponse
================
*/
int idServerScan::InfoResponse( networkServer_t &server ) {
if ( scan_state == IDLE ) {
return false;
}
idStr serv = Sys_NetAdrToString( server.adr );
if ( server.challenge != challenge ) {
common->DPrintf( "idServerScan::InfoResponse - ignoring response from %s, wrong challenge %d.", serv.c_str(), server.challenge );
return false;
}
if ( scan_state == NET_SCAN ) {
const idKeyValue *info = net_info.FindKey( serv.c_str() );
if ( !info ) {
common->DPrintf( "idServerScan::InfoResponse NET_SCAN: reply from unknown %s\n", serv.c_str() );
return false;
}
int id = atoi( info->GetValue() );
net_info.Delete( serv.c_str() );
inServer_t iserv = net_servers[ id ];
server.ping = Sys_Milliseconds() - iserv.time;
server.id = iserv.id;
} else {
server.ping = Sys_Milliseconds() - lan_pingtime;
server.id = 0;
// check for duplicate servers
for ( int i = 0; i < Num() ; i++ ) {
if ( memcmp( &(*this)[ i ].adr, &server.adr, sizeof(netadr_t) ) == 0 ) {
common->DPrintf( "idServerScan::InfoResponse LAN_SCAN: duplicate server %s\n", serv.c_str() );
return true;
}
}
}
const char *si_map = server.serverInfo.GetString( "si_map" );
const idDecl *mapDecl = declManager->FindType( DECL_MAPDEF, si_map, false );
const idDeclEntityDef *mapDef = static_cast< const idDeclEntityDef * >( mapDecl );
if ( mapDef ) {
const char *mapName = common->GetLanguageDict()->GetString( mapDef->dict.GetString( "name", si_map ) );
server.serverInfo.Set( "si_mapName", mapName );
} else {
server.serverInfo.Set( "si_mapName", si_map );
}
int index = Append( server );
// for now, don't maintain sorting when adding new info response servers
m_sortedServers.Append( Num()-1 );
if ( listGUI->IsConfigured( ) && !IsFiltered( server ) ) {
GUIAdd( Num()-1, server );
}
if ( listGUI->GetSelection( NULL, 0 ) == ( Num()-1 ) ) {
GUIUpdateSelected();
}
return index;
}
/*
================
idServerScan::AddServer
================
*/
void idServerScan::AddServer( int id, const char *srv ) {
inServer_t s;
incoming_net = true;
incoming_lastTime = Sys_Milliseconds() + INCOMING_TIMEOUT;
s.id = id;
// using IPs, not hosts
if ( !Sys_StringToNetAdr( srv, &s.adr, false ) ) {
common->DPrintf( "idServerScan::AddServer: failed to parse server %s\n", srv );
return;
}
if ( !s.adr.port ) {
s.adr.port = PORT_SERVER;
}
net_servers.Append( s );
}
/*
================
idServerScan::EndServers
================
*/
void idServerScan::EndServers( ) {
incoming_net = false;
l_serverScan = this;
m_sortedServers.Sort( idServerScan::Cmp );
ApplyFilter();
}
/*
================
idServerScan::StartServers
================
*/
void idServerScan::StartServers( bool timeout ) {
incoming_net = true;
incoming_useTimeout = timeout;
incoming_lastTime = Sys_Milliseconds() + REFRESH_START;
}
/*
================
idServerScan::EmitGetInfo
================
*/
void idServerScan::EmitGetInfo( netadr_t &serv ) {
idAsyncNetwork::client.GetServerInfo( serv );
}
/*
===============
idServerScan::GetChallenge
===============
*/
int idServerScan::GetChallenge( ) {
return challenge;
}
/*
================
idServerScan::NetScan
================
*/
void idServerScan::NetScan( ) {
if ( !idAsyncNetwork::client.IsPortInitialized() ) {
// if the port isn't open, initialize it, but wait for a short
// time to let the OS do whatever magic things it needs to do...
idAsyncNetwork::client.InitPort();
// start the scan one second from now...
scan_state = WAIT_ON_INIT;
endWaitTime = Sys_Milliseconds() + 1000;
return;
}
// make sure the client port is open
idAsyncNetwork::client.InitPort();
scan_state = NET_SCAN;
challenge++;
idList<networkServer_t>::Clear();
m_sortedServers.Clear();
cur_info = 0;
net_info.Clear();
listGUI->Clear();
GUIUpdateSelected();
common->DPrintf( "NetScan with challenge %d\n", challenge );
while ( cur_info < Min( net_servers.Num(), MAX_PINGREQUESTS ) ) {
netadr_t serv = net_servers[ cur_info ].adr;
EmitGetInfo( serv );
net_servers[ cur_info ].time = Sys_Milliseconds();
net_info.SetInt( Sys_NetAdrToString( serv ), cur_info );
cur_info++;
}
}
/*
===============
idServerScan::ServerScanFrame
===============
*/
void idServerScan::RunFrame( ) {
if ( scan_state == IDLE ) {
return;
}
if ( scan_state == WAIT_ON_INIT ) {
if ( Sys_Milliseconds() >= endWaitTime ) {
scan_state = IDLE;
NetScan();
}
return;
}
int timeout_limit = Sys_Milliseconds() - REPLY_TIMEOUT;
if ( scan_state == LAN_SCAN ) {
if ( timeout_limit > lan_pingtime ) {
common->Printf( "Scanned for servers on the LAN\n" );
scan_state = IDLE;
}
return;
}
// if scan_state == NET_SCAN
// check for timeouts
int i = 0;
while ( i < net_info.GetNumKeyVals() ) {
if ( timeout_limit > net_servers[ atoi( net_info.GetKeyVal( i )->GetValue().c_str() ) ].time ) {
common->DPrintf( "timeout %s\n", net_info.GetKeyVal( i )->GetKey().c_str() );
net_info.Delete( net_info.GetKeyVal( i )->GetKey().c_str() );
} else {
i++;
}
}
// possibly send more queries
while ( cur_info < net_servers.Num() && net_info.GetNumKeyVals() < MAX_PINGREQUESTS ) {
netadr_t serv = net_servers[ cur_info ].adr;
EmitGetInfo( serv );
net_servers[ cur_info ].time = Sys_Milliseconds();
net_info.SetInt( Sys_NetAdrToString( serv ), cur_info );
cur_info++;
}
// update state
if ( ( !incoming_net || ( incoming_useTimeout && Sys_Milliseconds() > incoming_lastTime ) ) && net_info.GetNumKeyVals() == 0 ) {
EndServers();
// the list is complete, we are no longer waiting for any getInfo replies
common->Printf( "Scanned %d servers.\n", cur_info );
scan_state = IDLE;
}
}
/*
===============
idServerScan::GetBestPing
===============
*/
bool idServerScan::GetBestPing( networkServer_t &serv ) {
int i, ic;
ic = Num();
if ( !ic ) {
return false;
}
serv = (*this)[ 0 ];
for ( i = 0 ; i < ic ; i++ ) {
if ( (*this)[ i ].ping < serv.ping ) {
serv = (*this)[ i ];
}
}
return true;
}
/*
================
idServerScan::GUIConfig
================
*/
void idServerScan::GUIConfig( idUserInterface *pGUI, const char *name ) {
m_pGUI = pGUI;
if ( listGUI == NULL ) {
listGUI = uiManager->AllocListGUI();
}
listGUI->Config( pGUI, name );
}
/*
================
idServerScan::GUIUpdateSelected
================
*/
void idServerScan::GUIUpdateSelected( void ) {
char screenshot[ MAX_STRING_CHARS ];
if ( !m_pGUI ) {
return;
}
int i = listGUI->GetSelection( NULL, 0 );
if ( i == -1 || i >= Num() ) {
m_pGUI->SetStateString( "server_name", "" );
m_pGUI->SetStateString( "player1", "" );
m_pGUI->SetStateString( "player2", "" );
m_pGUI->SetStateString( "player3", "" );
m_pGUI->SetStateString( "player4", "" );
m_pGUI->SetStateString( "player5", "" );
m_pGUI->SetStateString( "player6", "" );
m_pGUI->SetStateString( "player7", "" );
m_pGUI->SetStateString( "player8", "" );
m_pGUI->SetStateString( "server_map", "" );
m_pGUI->SetStateString( "browser_levelshot", "" );
m_pGUI->SetStateString( "server_gameType", "" );
m_pGUI->SetStateString( "server_IP", "" );
m_pGUI->SetStateString( "server_passworded", "" );
} else {
m_pGUI->SetStateString( "server_name", (*this)[ i ].serverInfo.GetString( "si_name" ) );
for ( int j = 0; j < 8; j++ ) {
if ( (*this)[i].clients > j ) {
m_pGUI->SetStateString( va( "player%i", j + 1 ) , (*this)[ i ].nickname[ j ] );
} else {
m_pGUI->SetStateString( va( "player%i", j + 1 ) , "" );
}
}
m_pGUI->SetStateString( "server_map", (*this)[ i ].serverInfo.GetString( "si_mapName" ) );
fileSystem->FindMapScreenshot( (*this)[ i ].serverInfo.GetString( "si_map" ), screenshot, MAX_STRING_CHARS );
m_pGUI->SetStateString( "browser_levelshot", screenshot );
m_pGUI->SetStateString( "server_gameType", (*this)[ i ].serverInfo.GetString( "si_gameType" ) );
m_pGUI->SetStateString( "server_IP", Sys_NetAdrToString( (*this)[ i ].adr ) );
if ( (*this)[ i ].serverInfo.GetBool( "si_usePass" ) ) {
m_pGUI->SetStateString( "server_passworded", "PASSWORD REQUIRED" );
} else {
m_pGUI->SetStateString( "server_passworded", "" );
}
}
}
/*
================
idServerScan::GUIAdd
================
*/
void idServerScan::GUIAdd( int id, const networkServer_t server ) {
idStr name = server.serverInfo.GetString( "si_name", GAME_NAME " Server" );
bool d3xp = false;
bool mod = false;
if ( !idStr::Icmp( server.serverInfo.GetString( "fs_game" ), "d3xp" ) ||
!idStr::Icmp( server.serverInfo.GetString( "fs_game_base" ), "d3xp" ) ) {
d3xp = true;
}
if ( server.serverInfo.GetString( "fs_game" )[ 0 ] != '\0' ) {
mod = true;
}
name += "\t";
if ( server.serverInfo.GetString( "sv_punkbuster" )[ 0 ] == '1' ) {
name += "mtr_PB";
}
name += "\t";
if ( d3xp ) {
// FIXME: even for a 'D3XP mod'
// could have a specific icon for this case
name += "mtr_doom3XPIcon";
} else if ( mod ) {
name += "mtr_doom3Mod";
} else {
name += "mtr_doom3Icon";
}
name += "\t";
name += va( "%i/%i\t", server.clients, server.serverInfo.GetInt( "si_maxPlayers" ) );
name += ( server.ping > -1 ) ? va( "%i\t", server.ping ) : "na\t";
name += server.serverInfo.GetString( "si_gametype" );
name += "\t";
name += server.serverInfo.GetString( "si_mapName" );
name += "\t";
listGUI->Add( id, name );
}
/*
================
idServerScan::ApplyFilter
================
*/
void idServerScan::ApplyFilter( ) {
int i;
networkServer_t serv;
idStr s;
listGUI->SetStateChanges( false );
listGUI->Clear();
for ( i = m_sortAscending ? 0 : m_sortedServers.Num() - 1;
m_sortAscending ? i < m_sortedServers.Num() : i >= 0;
m_sortAscending ? i++ : i-- ) {
serv = (*this)[ m_sortedServers[ i ] ];
if ( !IsFiltered( serv ) ) {
GUIAdd( m_sortedServers[ i ], serv );
}
}
GUIUpdateSelected();
listGUI->SetStateChanges( true );
}
/*
================
idServerScan::IsFiltered
================
*/
bool idServerScan::IsFiltered( const networkServer_t server ) {
int i;
const idKeyValue *keyval;
// OS support filter
#if 0
// filter out pure servers that won't provide checksumed game code for client OS
keyval = server.serverInfo.FindKey( "si_pure" );
if ( keyval && !idStr::Cmp( keyval->GetValue(), "1" ) ) {
if ( ( server.OSMask & ( 1 << BUILD_OS_ID ) ) == 0 ) {
return true;
}
}
#else
if ( ( server.OSMask & ( 1 << BUILD_OS_ID ) ) == 0 ) {
return true;
}
#endif
// password filter
keyval = server.serverInfo.FindKey( "si_usePass" );
if ( keyval && gui_filter_password.GetInteger() == 1 ) {
// show passworded only
if ( keyval->GetValue()[ 0 ] == '0' ) {
return true;
}
} else if ( keyval && gui_filter_password.GetInteger() == 2 ) {
// show no password only
if ( keyval->GetValue()[ 0 ] != '0' ) {
return true;
}
}
// players filter
keyval = server.serverInfo.FindKey( "si_maxPlayers" );
if ( keyval ) {
if ( gui_filter_players.GetInteger() == 1 && server.clients == atoi( keyval->GetValue() ) ) {
return true;
} else if ( gui_filter_players.GetInteger() == 2 && ( !server.clients || server.clients == atoi( keyval->GetValue() ) ) ) {
return true;
}
}
// gametype filter
keyval = server.serverInfo.FindKey( "si_gameType" );
if ( keyval && gui_filter_gameType.GetInteger() ) {
i = 0;
while ( l_gameTypes[ i ] ) {
if ( !keyval->GetValue().Icmp( l_gameTypes[ i ] ) ) {
break;
}
i++;
}
if ( l_gameTypes[ i ] && i != gui_filter_gameType.GetInteger() -1 ) {
return true;
}
}
// idle server filter
keyval = server.serverInfo.FindKey( "si_idleServer" );
if ( keyval && !gui_filter_idle.GetInteger() ) {
if ( !keyval->GetValue().Icmp( "1" ) ) {
return true;
}
}
// autofilter D3XP games if the user does not has the XP installed
if(!fileSystem->HasD3XP() && !idStr::Icmp(server.serverInfo.GetString( "fs_game" ), "d3xp")) {
return true;
}
// filter based on the game doom or XP
if(gui_filter_game.GetInteger() == 1) { //Only Doom
if(idStr::Icmp(server.serverInfo.GetString("fs_game"), "")) {
return true;
}
} else if(gui_filter_game.GetInteger() == 2) { //Only D3XP
if(idStr::Icmp(server.serverInfo.GetString("fs_game"), "d3xp")) {
return true;
}
}
return false;
}
/*
================
idServerScan::Cmp
================
*/
int idServerScan::Cmp( const int *a, const int *b ) {
networkServer_t serv1, serv2;
idStr s1, s2;
int ret;
serv1 = (*l_serverScan)[ *a ];
serv2 = (*l_serverScan)[ *b ];
switch ( l_serverScan->m_sort ) {
case SORT_PING:
ret = serv1.ping < serv2.ping ? -1 : ( serv1.ping > serv2.ping ? 1 : 0 );
return ret;
case SORT_SERVERNAME:
serv1.serverInfo.GetString( "si_name", "", s1 );
serv2.serverInfo.GetString( "si_name", "", s2 );
return s1.IcmpNoColor( s2 );
case SORT_PLAYERS:
ret = serv1.clients < serv2.clients ? -1 : ( serv1.clients > serv2.clients ? 1 : 0 );
return ret;
case SORT_GAMETYPE:
serv1.serverInfo.GetString( "si_gameType", "", s1 );
serv2.serverInfo.GetString( "si_gameType", "", s2 );
return s1.Icmp( s2 );
case SORT_MAP:
serv1.serverInfo.GetString( "si_mapName", "", s1 );
serv2.serverInfo.GetString( "si_mapName", "", s2 );
return s1.Icmp( s2 );
case SORT_GAME:
serv1.serverInfo.GetString( "fs_game", "", s1 );
serv2.serverInfo.GetString( "fs_game", "", s2 );
return s1.Icmp( s2 );
}
return 0;
}
/*
================
idServerScan::SetSorting
================
*/
void idServerScan::SetSorting( serverSort_t sort ) {
l_serverScan = this;
if ( sort == m_sort ) {
m_sortAscending = !m_sortAscending;
} else {
m_sort = sort;
m_sortAscending = true; // is the default for any new sort
m_sortedServers.Sort( idServerScan::Cmp );
}
// trigger a redraw
ApplyFilter();
}

View File

@@ -0,0 +1,170 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __SERVERSCAN_H__
#define __SERVERSCAN_H__
/*
===============================================================================
Scan for servers, on the LAN or from a list
Update a listDef GUI through usage of idListGUI class
When updating large lists of servers, sends out getInfo in small batches to avoid congestion
===============================================================================
*/
// storage for incoming servers / server scan
typedef struct {
netadr_t adr;
int id;
int time;
} inServer_t;
// the menu gui uses a hard-coded control type to display a list of network games
typedef struct {
netadr_t adr;
idDict serverInfo;
int ping;
int id; // idnet mode sends an id for each server in list
int clients;
char nickname[ MAX_NICKLEN ][ MAX_ASYNC_CLIENTS ];
short pings[ MAX_ASYNC_CLIENTS ];
int rate[ MAX_ASYNC_CLIENTS ];
int OSMask;
int challenge;
} networkServer_t;
typedef enum {
SORT_PING,
SORT_SERVERNAME,
SORT_PLAYERS,
SORT_GAMETYPE,
SORT_MAP,
SORT_GAME
} serverSort_t;
class idServerScan : public idList<networkServer_t> {
public:
idServerScan( );
int InfoResponse( networkServer_t &server );
// add an internet server - ( store a numeric id along with it )
void AddServer( int id, const char *srv );
// we are going to feed server entries to be pinged
// if timeout is true, use a timeout once we start AddServer to trigger EndServers and decide the scan is done
void StartServers( bool timeout );
// we are done filling up the list of server entries
void EndServers( );
// scan the current list of servers - used for refreshes and while receiving a fresh list
void NetScan( );
// clear
void Clear( );
// called each game frame. Updates the scanner state, takes care of ongoing scans
void RunFrame( );
typedef enum {
IDLE = 0,
WAIT_ON_INIT,
LAN_SCAN,
NET_SCAN
} scan_state_t;
scan_state_t GetState() { return scan_state; }
void SetState( scan_state_t );
bool GetBestPing( networkServer_t &serv );
// prepare for a LAN scan. idAsyncClient does the network job (UDP broadcast), we do the storage
void SetupLANScan( );
void GUIConfig( idUserInterface *pGUI, const char *name );
// update the GUI fields with information about the currently selected server
void GUIUpdateSelected( void );
void Shutdown( );
void ApplyFilter( );
// there is an internal toggle, call twice with same sort to switch
void SetSorting( serverSort_t sort );
int GetChallenge( );
private:
static const int MAX_PINGREQUESTS = 32; // how many servers to query at once
static const int REPLY_TIMEOUT = 999; // how long should we wait for a reply from a game server
static const int INCOMING_TIMEOUT = 1500; // when we got an incoming server list, how long till we decide the list is done
static const int REFRESH_START = 10000; // how long to wait when sending the initial refresh request
scan_state_t scan_state;
bool incoming_net; // set to true while new servers are fed through AddServer
bool incoming_useTimeout;
int incoming_lastTime;
int lan_pingtime; // holds the time of LAN scan
// servers we're waiting for a reply from
// won't exceed MAX_PINGREQUESTS elements
// holds index of net_servers elements, indexed by 'from' string
idDict net_info;
idList<inServer_t> net_servers;
// where we are in net_servers list for getInfo emissions ( NET_SCAN only )
// we may either be waiting on MAX_PINGREQUESTS, or for net_servers to grow some more ( through AddServer )
int cur_info;
idUserInterface *m_pGUI;
idListGUI * listGUI;
serverSort_t m_sort;
bool m_sortAscending;
idList<int> m_sortedServers; // use ascending for the walking order
idStr screenshot;
int challenge; // challenge for current scan
int endWaitTime; // when to stop waiting on a port init
private:
void LocalClear( ); // we need to clear some internal data as well
void EmitGetInfo( netadr_t &serv );
void GUIAdd( int id, const networkServer_t server );
bool IsFiltered( const networkServer_t server );
static int Cmp( const int *a, const int *b );
};
#endif /* !__SERVERSCAN_H__ */