mirror of
https://github.com/id-Software/DOOM-3.git
synced 2026-03-20 00:49:31 +01:00
hello world
This commit is contained in:
135
neo/framework/BuildDefines.h
Normal file
135
neo/framework/BuildDefines.h
Normal 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
|
||||
|
||||
28
neo/framework/BuildVersion.h
Normal file
28
neo/framework/BuildVersion.h
Normal 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
1257
neo/framework/CVarSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
309
neo/framework/CVarSystem.h
Normal file
309
neo/framework/CVarSystem.h
Normal 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
783
neo/framework/CmdSystem.cpp
Normal 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
188
neo/framework/CmdSystem.h
Normal 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
3101
neo/framework/Common.cpp
Normal file
File diff suppressed because it is too large
Load Diff
215
neo/framework/Common.h
Normal file
215
neo/framework/Common.h
Normal 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
2576
neo/framework/Compressor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
73
neo/framework/Compressor.h
Normal file
73
neo/framework/Compressor.h
Normal 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
1186
neo/framework/Console.cpp
Normal file
File diff suppressed because it is too large
Load Diff
72
neo/framework/Console.h
Normal file
72
neo/framework/Console.h
Normal 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
1745
neo/framework/DeclAF.cpp
Normal file
File diff suppressed because it is too large
Load Diff
216
neo/framework/DeclAF.h
Normal file
216
neo/framework/DeclAF.h
Normal 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__ */
|
||||
153
neo/framework/DeclEntityDef.cpp
Normal file
153
neo/framework/DeclEntityDef.cpp
Normal 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();
|
||||
}
|
||||
51
neo/framework/DeclEntityDef.h
Normal file
51
neo/framework/DeclEntityDef.h
Normal 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
473
neo/framework/DeclFX.cpp
Normal 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
113
neo/framework/DeclFX.h
Normal 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__ */
|
||||
2230
neo/framework/DeclManager.cpp
Normal file
2230
neo/framework/DeclManager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
336
neo/framework/DeclManager.h
Normal file
336
neo/framework/DeclManager.h
Normal 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
668
neo/framework/DeclPDA.cpp
Normal 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
167
neo/framework/DeclPDA.h
Normal 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__ */
|
||||
1431
neo/framework/DeclParticle.cpp
Normal file
1431
neo/framework/DeclParticle.cpp
Normal file
File diff suppressed because it is too large
Load Diff
218
neo/framework/DeclParticle.h
Normal file
218
neo/framework/DeclParticle.h
Normal 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
185
neo/framework/DeclSkin.cpp
Normal 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
64
neo/framework/DeclSkin.h
Normal 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
177
neo/framework/DeclTable.cpp
Normal 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
56
neo/framework/DeclTable.h
Normal 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__ */
|
||||
39
neo/framework/DemoChecksum.h
Normal file
39
neo/framework/DemoChecksum.h
Normal 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
328
neo/framework/DemoFile.cpp
Normal 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
88
neo/framework/DemoFile.h
Normal 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
604
neo/framework/EditField.cpp
Normal 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
79
neo/framework/EditField.h
Normal 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
274
neo/framework/EventLoop.cpp
Normal 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
88
neo/framework/EventLoop.h
Normal 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
1365
neo/framework/File.cpp
Normal file
File diff suppressed because it is too large
Load Diff
243
neo/framework/File.h
Normal file
243
neo/framework/File.h
Normal 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
4217
neo/framework/FileSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
289
neo/framework/FileSystem.h
Normal file
289
neo/framework/FileSystem.h
Normal 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
785
neo/framework/KeyInput.cpp
Normal 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
221
neo/framework/KeyInput.h
Normal 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
115
neo/framework/Licensee.h
Normal 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
3324
neo/framework/Session.cpp
Normal file
File diff suppressed because it is too large
Load Diff
165
neo/framework/Session.h
Normal file
165
neo/framework/Session.h
Normal 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__ */
|
||||
363
neo/framework/Session_local.h
Normal file
363
neo/framework/Session_local.h
Normal 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__ */
|
||||
1654
neo/framework/Session_menu.cpp
Normal file
1654
neo/framework/Session_menu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4470
neo/framework/Unzip.cpp
Normal file
4470
neo/framework/Unzip.cpp
Normal file
File diff suppressed because it is too large
Load Diff
346
neo/framework/Unzip.h
Normal file
346
neo/framework/Unzip.h
Normal 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
1112
neo/framework/UsercmdGen.cpp
Normal file
File diff suppressed because it is too large
Load Diff
170
neo/framework/UsercmdGen.h
Normal file
170
neo/framework/UsercmdGen.h
Normal 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__ */
|
||||
2334
neo/framework/async/AsyncClient.cpp
Normal file
2334
neo/framework/async/AsyncClient.cpp
Normal file
File diff suppressed because it is too large
Load Diff
218
neo/framework/async/AsyncClient.h
Normal file
218
neo/framework/async/AsyncClient.h
Normal 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__ */
|
||||
513
neo/framework/async/AsyncNetwork.cpp
Normal file
513
neo/framework/async/AsyncNetwork.cpp
Normal 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 ¤tUserCmd, 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 ¤tUserCmd ) {
|
||||
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" );
|
||||
}
|
||||
|
||||
219
neo/framework/async/AsyncNetwork.h
Normal file
219
neo/framework/async/AsyncNetwork.h
Normal 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 ¤tUserCmd, int frame, int time );
|
||||
static bool UsercmdInputChanged( const usercmd_t &previousUserCmd, const usercmd_t ¤tUserCmd );
|
||||
|
||||
// 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__ */
|
||||
2825
neo/framework/async/AsyncServer.cpp
Normal file
2825
neo/framework/async/AsyncServer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
259
neo/framework/async/AsyncServer.h
Normal file
259
neo/framework/async/AsyncServer.h
Normal 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__ */
|
||||
790
neo/framework/async/MsgChannel.cpp
Normal file
790
neo/framework/async/MsgChannel.cpp
Normal 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 );
|
||||
}
|
||||
201
neo/framework/async/MsgChannel.h
Normal file
201
neo/framework/async/MsgChannel.h
Normal 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__ */
|
||||
215
neo/framework/async/NetworkSystem.cpp
Normal file
215
neo/framework/async/NetworkSystem.cpp
Normal 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;
|
||||
}
|
||||
65
neo/framework/async/NetworkSystem.h
Normal file
65
neo/framework/async/NetworkSystem.h
Normal 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__ */
|
||||
639
neo/framework/async/ServerScan.cpp
Normal file
639
neo/framework/async/ServerScan.cpp
Normal 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();
|
||||
}
|
||||
|
||||
170
neo/framework/async/ServerScan.h
Normal file
170
neo/framework/async/ServerScan.h
Normal 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__ */
|
||||
Reference in New Issue
Block a user