23 Jun 2008
This commit is contained in:
parent
e2b8110780
commit
d8eb784740
|
@ -372,7 +372,7 @@ void CL_ClearState (void)
|
|||
CL_ClearEffects ();
|
||||
CL_ClearTEnts ();
|
||||
|
||||
// wipe the entire cl structure
|
||||
// wipe the entire cl structure
|
||||
memset (&cl, 0, sizeof(cl));
|
||||
memset (&cl_entities, 0, sizeof(cl_entities));
|
||||
|
||||
|
@ -556,60 +556,169 @@ void CL_ParseStatusMessage (void)
|
|||
M_AddToServerList (net_from, s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_PingServers_f
|
||||
=================
|
||||
===================
|
||||
CL_StatusLocal_f
|
||||
===================
|
||||
*/
|
||||
void CL_PingServers_f (void)
|
||||
void CL_GetServerList_f( void )
|
||||
{
|
||||
int i;
|
||||
netadr_t adr;
|
||||
char name[32];
|
||||
char *adrstring;
|
||||
cvar_t *noudp;
|
||||
cvar_t *noipx;
|
||||
|
||||
NET_Config (true); // allow remote
|
||||
NET_Config( true ); // allow remote
|
||||
|
||||
// send a broadcast packet
|
||||
Msg ("pinging broadcast...\n");
|
||||
MsgDev( D_INFO, "status pinging broadcast...\n" );
|
||||
cls.pingtime = cls.realtime;
|
||||
|
||||
noudp = Cvar_Get ("noudp", "0", CVAR_INIT);
|
||||
if (!noudp->value)
|
||||
adr.type = NA_BROADCAST;
|
||||
adr.port = BigShort( PORT_SERVER );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, "status" );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_FreeServerInfo
|
||||
=============
|
||||
*/
|
||||
static void CL_FreeServerInfo( serverinfo_t *server )
|
||||
{
|
||||
if( server->mapname ) Mem_Free( server->mapname );
|
||||
if( server->hostname ) Mem_Free( server->hostname );
|
||||
if( server->shortname ) Mem_Free( server->shortname );
|
||||
if( server->gamename ) Mem_Free( server->gamename );
|
||||
if( server->netaddress ) Mem_Free( server->netaddress );
|
||||
if( server->playerstr ) Mem_Free( server->playerstr );
|
||||
if( server->pingstring ) Mem_Free( server->pingstring);
|
||||
memset( server, 0, sizeof(serverinfo_t));
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_FreeServerList
|
||||
=============
|
||||
*/
|
||||
static void CL_FreeServerList_f( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < cls.numservers; i++ )
|
||||
CL_FreeServerInfo( &cls.serverlist[i] );
|
||||
cls.numservers = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_DupeCheckServerList
|
||||
|
||||
Checks for duplicates and returns true if there is one...
|
||||
Since status has higher priority than info, if there is already an instance and
|
||||
it's not status, and the current one is status, the old one is removed.
|
||||
=============
|
||||
*/
|
||||
static bool CL_DupeCheckServerList( char *adr, bool status )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < cls.numservers; i++ )
|
||||
{
|
||||
adr.type = NA_BROADCAST;
|
||||
adr.port = BigShort(PORT_SERVER);
|
||||
Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
|
||||
}
|
||||
|
||||
noipx = Cvar_Get ("noipx", "0", CVAR_INIT);
|
||||
if (!noipx->value)
|
||||
{
|
||||
adr.type = NA_BROADCAST_IPX;
|
||||
adr.port = BigShort(PORT_SERVER);
|
||||
Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
|
||||
}
|
||||
|
||||
// send a packet to each address book entry
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
com.sprintf (name, "adr%i", i);
|
||||
adrstring = Cvar_VariableString (name);
|
||||
if (!adrstring || !adrstring[0])
|
||||
continue;
|
||||
|
||||
Msg ("pinging %s...\n", adrstring);
|
||||
if (!NET_StringToAdr (adrstring, &adr))
|
||||
if(!cls.serverlist[i].netaddress && !cls.serverlist[i].hostname )
|
||||
{
|
||||
Msg ("Bad address: %s\n", adrstring);
|
||||
CL_FreeServerInfo( &cls.serverlist[i] );
|
||||
continue;
|
||||
}
|
||||
if (!adr.port)
|
||||
adr.port = BigShort(PORT_SERVER);
|
||||
Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
|
||||
if( cls.serverlist[i].netaddress && !com.strcmp( cls.serverlist[i].netaddress, adr ))
|
||||
{
|
||||
if( cls.serverlist[i].statusPacket && status )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if( status )
|
||||
{
|
||||
CL_FreeServerInfo( &cls.serverlist[i] );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_ParseServerStatus
|
||||
|
||||
Parses a status packet from a server
|
||||
FIXME: check against a list of sent status requests so it's not attempting to parse things it shouldn't
|
||||
=============
|
||||
*/
|
||||
bool CL_ParseServerStatus( char *adr, char *info )
|
||||
{
|
||||
serverinfo_t *server;
|
||||
char *token;
|
||||
char shortName[32];
|
||||
|
||||
if( !info || !info[0] )return false;
|
||||
if( !adr || !adr[0] ) return false;
|
||||
if( !com.strchr( info, '\\')) return false;
|
||||
|
||||
if( cls.numservers >= MAX_SERVERS )
|
||||
return true;
|
||||
if( CL_DupeCheckServerList( adr, true ))
|
||||
return true;
|
||||
|
||||
server = &cls.serverlist[cls.numservers];
|
||||
CL_FreeServerInfo( server );
|
||||
cls.numservers++;
|
||||
|
||||
// add net address
|
||||
server->netaddress = copystring( adr );
|
||||
server->mapname = copystring(Info_ValueForKey( info, "mapname"));
|
||||
server->maxplayers = com.atoi(Info_ValueForKey( info, "maxclients"));
|
||||
server->gamename = copystring(Info_ValueForKey( info, "gamename"));
|
||||
server->hostname = copystring(Info_ValueForKey( info, "hostname"));
|
||||
if( server->hostname )
|
||||
{
|
||||
com.strncpy( shortName, server->hostname, sizeof(shortName));
|
||||
server->shortname = copystring( shortName );
|
||||
}
|
||||
|
||||
// Check the player count
|
||||
server->numplayers = com.atoi(Info_ValueForKey( info, "curplayers"));
|
||||
if( server->numplayers <= 0 )
|
||||
{
|
||||
server->numplayers = 0;
|
||||
|
||||
token = strtok( info, "\n" );
|
||||
if( token )
|
||||
{
|
||||
token = strtok( NULL, "\n" );
|
||||
while( token )
|
||||
{
|
||||
server->numplayers++;
|
||||
token = strtok( NULL, "\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if it's valid
|
||||
if( !server->mapname[0] && !server->maxplayers && !server->gamename[0] && !server->hostname[0] )
|
||||
{
|
||||
CL_FreeServerInfo( server );
|
||||
return false;
|
||||
}
|
||||
|
||||
server->playerstr = copystring( va("%i/%i", server->numplayers, server->maxplayers ));
|
||||
|
||||
// add the ping
|
||||
server->ping = (int)(cls.realtime - cls.pingtime) * 1000.0f;
|
||||
server->pingstring = copystring( va("%ims", server->ping ));
|
||||
server->statusPacket = true;
|
||||
|
||||
// print information
|
||||
MsgDev( D_NOTE, "%s %s ", server->hostname, server->mapname );
|
||||
MsgDev( D_NOTE, "%i/%i %ims\n", server->numplayers, server->maxplayers, server->ping );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -619,10 +728,9 @@ CL_ConnectionlessPacket
|
|||
Responses to broadcasts, etc
|
||||
=================
|
||||
*/
|
||||
void CL_ConnectionlessPacket (void)
|
||||
void CL_ConnectionlessPacket( void )
|
||||
{
|
||||
char *s;
|
||||
char *c;
|
||||
char *s, *c;
|
||||
|
||||
MSG_BeginReading (&net_message);
|
||||
MSG_ReadLong (&net_message); // skip the -1
|
||||
|
@ -630,7 +738,6 @@ void CL_ConnectionlessPacket (void)
|
|||
s = MSG_ReadStringLine (&net_message);
|
||||
|
||||
Cmd_TokenizeString(s);
|
||||
|
||||
c = Cmd_Argv(0);
|
||||
|
||||
MsgDev(D_INFO, "%s: %s\n", NET_AdrToString (net_from), c);
|
||||
|
@ -675,8 +782,10 @@ void CL_ConnectionlessPacket (void)
|
|||
// print command from somewhere
|
||||
if (!strcmp(c, "print"))
|
||||
{
|
||||
// print command from somewhere
|
||||
s = MSG_ReadString (&net_message);
|
||||
Msg ("%s", s);
|
||||
if(!CL_ParseServerStatus( NET_AdrToString(net_from), s ))
|
||||
Msg( s );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -701,7 +810,6 @@ void CL_ConnectionlessPacket (void)
|
|||
Netchan_OutOfBandPrint (NS_CLIENT, net_from, "%s", Cmd_Argv(1) );
|
||||
return;
|
||||
}
|
||||
|
||||
Msg ("Unknown command.\n");
|
||||
}
|
||||
|
||||
|
@ -1175,7 +1283,8 @@ void CL_InitLocal (void)
|
|||
// register our commands
|
||||
Cmd_AddCommand ("cmd", CL_ForwardToServer_f, "send a console commandline to the server" );
|
||||
Cmd_AddCommand ("pause", CL_Pause_f, "pause the game (if the server allows pausing)" );
|
||||
Cmd_AddCommand ("pingservers", CL_PingServers_f, "send a broadcast packet" );
|
||||
Cmd_AddCommand ("getserverlist", CL_GetServerList_f, "get info about local servers" );
|
||||
Cmd_AddCommand ("freeserverlist", CL_FreeServerList_f, "clear info about local servers" );
|
||||
|
||||
Cmd_AddCommand ("userinfo", CL_Userinfo_f, "print current client userinfo" );
|
||||
Cmd_AddCommand ("changing", CL_Changing_f, "sent by server to tell client to wait for level change" );
|
||||
|
|
|
@ -162,11 +162,11 @@ VM_CvarRegister, // #24 void Cvar_Register( string name, string value, float f
|
|||
VM_CvarSetValue, // #25 void Cvar_SetValue( string name, float value )
|
||||
VM_CvarGetValue, // #26 float Cvar_GetValue( string name )
|
||||
VM_CvarSetString, // #27 void Cvar_SetString( string name, string value )
|
||||
VM_ComVA, // #28 string va( ... )
|
||||
VM_ComStrlen, // #29 float strlen( string text )
|
||||
VM_TimeStamp, // #30 string Com_TimeStamp( float format )
|
||||
VM_LocalCmd, // #31 void LocalCmd( ... )
|
||||
NULL, // #32 -- reserved --
|
||||
VM_CvarGetString, // #28 void VM_CvarGetString( void )
|
||||
VM_ComVA, // #29 string va( ... )
|
||||
VM_ComStrlen, // #30 float strlen( string text )
|
||||
VM_TimeStamp, // #31 string Com_TimeStamp( float format )
|
||||
VM_LocalCmd, // #32 void LocalCmd( ... )
|
||||
NULL, // #33 -- reserved --
|
||||
NULL, // #34 -- reserved --
|
||||
NULL, // #35 -- reserved --
|
||||
|
|
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#define MAX_EDIT_LINE 256
|
||||
#define COMMAND_HISTORY 32
|
||||
#define MAX_SERVERS 64
|
||||
|
||||
//=============================================================================
|
||||
typedef struct
|
||||
|
@ -229,6 +230,24 @@ typedef enum {
|
|||
dl_single
|
||||
} dltype_t; // download type
|
||||
|
||||
typedef struct serverinfo_s
|
||||
{
|
||||
char *mapname;
|
||||
char *hostname;
|
||||
char *shortname;
|
||||
char *gamename;
|
||||
char *netaddress;
|
||||
|
||||
char *playerstr;
|
||||
int numplayers;
|
||||
int maxplayers;
|
||||
|
||||
char *pingstring;
|
||||
bool statusPacket;
|
||||
int ping;
|
||||
|
||||
} serverinfo_t;
|
||||
|
||||
typedef enum {key_game, key_console, key_message, key_menu} keydest_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -236,9 +255,9 @@ typedef struct
|
|||
connstate_t state;
|
||||
keydest_t key_dest;
|
||||
|
||||
int framecount;
|
||||
float realtime; // always increasing, no clamping, etc
|
||||
float frametime; // seconds since last frame
|
||||
int framecount;
|
||||
float realtime; // always increasing, no clamping, etc
|
||||
float frametime; // seconds since last frame
|
||||
|
||||
// connection information
|
||||
string servername; // name of server from original connect
|
||||
|
@ -266,6 +285,9 @@ typedef struct
|
|||
string demoname; // for demo looping
|
||||
|
||||
file_t *demofile;
|
||||
serverinfo_t serverlist[MAX_SERVERS]; // servers to join
|
||||
int numservers;
|
||||
float pingtime; // servers timebase
|
||||
|
||||
// hudprogram stack
|
||||
byte *hud_program;
|
||||
|
|
177
engine/common.c
177
engine/common.c
|
@ -686,6 +686,26 @@ void VM_CvarGetValue( void )
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
VM_CvarGetString
|
||||
|
||||
string Cvar_GetString( string name )
|
||||
=========
|
||||
*/
|
||||
void VM_CvarGetString( void )
|
||||
{
|
||||
const char *name;
|
||||
|
||||
if(!VM_ValidateArgs( "Cvar_GetString", 1 ))
|
||||
return;
|
||||
|
||||
VM_ValidateString(PRVM_G_STRING(OFS_PARM0));
|
||||
name = PRVM_G_STRING(OFS_PARM0);
|
||||
PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(Cvar_VariableString( name ));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VM_LocalCmd
|
||||
|
@ -1306,11 +1326,11 @@ VM_CvarRegister, // #24 void Cvar_Register( string name, string value, float f
|
|||
VM_CvarSetValue, // #25 void Cvar_SetValue( string name, float value )
|
||||
VM_CvarGetValue, // #26 float Cvar_GetValue( string name )
|
||||
VM_CvarSetString, // #27 void Cvar_SetString( string name, string value )
|
||||
VM_ComVA, // #28 string va( ... )
|
||||
VM_ComStrlen, // #29 float strlen( string text )
|
||||
VM_TimeStamp, // #30 string Com_TimeStamp( float format )
|
||||
VM_LocalCmd, // #31 void LocalCmd( ... )
|
||||
NULL, // #32 -- reserved --
|
||||
VM_CvarGetString, // #28 void VM_CvarGetString( void )
|
||||
VM_ComVA, // #29 string va( ... )
|
||||
VM_ComStrlen, // #30 float strlen( string text )
|
||||
VM_TimeStamp, // #31 string Com_TimeStamp( float format )
|
||||
VM_LocalCmd, // #32 void LocalCmd( ... )
|
||||
NULL, // #33 -- reserved --
|
||||
NULL, // #34 -- reserved --
|
||||
NULL, // #35 -- reserved --
|
||||
|
@ -1384,14 +1404,14 @@ Info_Print
|
|||
printing current key-value pair
|
||||
===============
|
||||
*/
|
||||
void Info_Print (char *s)
|
||||
void Info_Print( char *s )
|
||||
{
|
||||
char key[512];
|
||||
char value[512];
|
||||
char *o;
|
||||
int l;
|
||||
|
||||
if (*s == '\\') s++;
|
||||
if( *s == '\\' )s++;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
|
@ -1431,7 +1451,7 @@ Searches the string for the given
|
|||
key and returns the associated value, or an empty string.
|
||||
===============
|
||||
*/
|
||||
char *Info_ValueForKey (char *s, char *key)
|
||||
char *Info_ValueForKey( char *s, char *key )
|
||||
{
|
||||
char pkey[512];
|
||||
static char value[2][512]; // use two buffers so compares work without stomping on each other
|
||||
|
@ -1439,13 +1459,13 @@ char *Info_ValueForKey (char *s, char *key)
|
|||
char *o;
|
||||
|
||||
valueindex ^= 1;
|
||||
if (*s == '\\') s++;
|
||||
while (1)
|
||||
if( *s == '\\' ) s++;
|
||||
while( 1 )
|
||||
{
|
||||
o = pkey;
|
||||
while (*s != '\\')
|
||||
while( *s != '\\' && *s != '\n' )
|
||||
{
|
||||
if (!*s) return "";
|
||||
if(!*s) return "";
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
|
@ -1453,15 +1473,15 @@ char *Info_ValueForKey (char *s, char *key)
|
|||
|
||||
o = value[valueindex];
|
||||
|
||||
while (*s != '\\' && *s)
|
||||
while( *s != '\\' && *s != '\n' && *s)
|
||||
{
|
||||
if (!*s) return "";
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
|
||||
if (!strcmp (key, pkey) ) return value[valueindex];
|
||||
if (!*s) return "";
|
||||
if(!com.strcmp( key, pkey )) return value[valueindex];
|
||||
if(!*s) return "";
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
@ -1959,6 +1979,133 @@ bool Cmd_GetSoundList( const char *s, char *completedname, int length )
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Cmd_CheckMapsList( void )
|
||||
{
|
||||
byte buf[MAX_SYSPATH]; // 1 kb
|
||||
char *buffer, string[MAX_STRING];
|
||||
search_t *t;
|
||||
file_t *f;
|
||||
int i;
|
||||
|
||||
if(FS_FileExists("scripts/maps.lst"))
|
||||
return true; // exist
|
||||
|
||||
t = FS_Search( "maps/*.bsp", false );
|
||||
if(!t) return false;
|
||||
|
||||
buffer = Z_Malloc( t->numfilenames * 2 * sizeof(string));
|
||||
for( i = 0; i < t->numfilenames; i++ )
|
||||
{
|
||||
const char *data = NULL;
|
||||
char *entities = NULL;
|
||||
char entfilename[MAX_QPATH];
|
||||
int ver = -1, lumpofs = 0, lumplen = 0;
|
||||
char mapname[MAX_QPATH], message[MAX_QPATH];
|
||||
|
||||
f = FS_Open(t->filenames[i], "rb");
|
||||
FS_FileBase( t->filenames[i], mapname );
|
||||
|
||||
if( f )
|
||||
{
|
||||
int num_spawnpoints = 0;
|
||||
|
||||
memset(buf, 0, 1024);
|
||||
FS_Read(f, buf, 1024);
|
||||
if(!memcmp(buf, "IBSP", 4))
|
||||
{
|
||||
dheader_t *header = (dheader_t *)buf;
|
||||
ver = LittleLong(((int *)buf)[1]);
|
||||
switch(ver)
|
||||
{
|
||||
case 38: // quake2
|
||||
case 39: // xash
|
||||
case 46: // quake3
|
||||
case 47: // return to castle wolfenstein
|
||||
lumpofs = LittleLong(header->lumps[LUMP_ENTITIES].fileofs);
|
||||
lumplen = LittleLong(header->lumps[LUMP_ENTITIES].filelen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lump_t ents; // quake1 entity lump
|
||||
memcpy(&ents, buf + 4, sizeof(lump_t)); // skip first four bytes (version)
|
||||
ver = LittleLong(((int *)buf)[0]);
|
||||
|
||||
switch( ver )
|
||||
{
|
||||
case 28: // quake 1 beta
|
||||
case 29: // quake 1 regular
|
||||
case 30: // Half-Life regular
|
||||
lumpofs = LittleLong(ents.fileofs);
|
||||
lumplen = LittleLong(ents.filelen);
|
||||
break;
|
||||
default:
|
||||
ver = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
com.strncpy(entfilename, t->filenames[i], sizeof(entfilename));
|
||||
FS_StripExtension( entfilename );
|
||||
FS_DefaultExtension( entfilename, ".ent" );
|
||||
entities = (char *)FS_LoadFile(entfilename, NULL);
|
||||
|
||||
if( !entities && lumplen >= 10 )
|
||||
{
|
||||
FS_Seek(f, lumpofs, SEEK_SET);
|
||||
entities = (char *)Z_Malloc(lumplen + 1);
|
||||
FS_Read(f, entities, lumplen);
|
||||
}
|
||||
if(entities)
|
||||
{
|
||||
// if there are entities to parse, a missing message key just
|
||||
// means there is no title, so clear the message string now
|
||||
message[0] = 0;
|
||||
data = entities;
|
||||
com.strncpy(message, "No Title", MAX_QPATH);
|
||||
|
||||
while(Com_ParseToken(&data))
|
||||
{
|
||||
if(!strcmp(com_token, "{" )) continue;
|
||||
else if(!strcmp(com_token, "}" )) break;
|
||||
else if(!strcmp(com_token, "message" ))
|
||||
{
|
||||
// get the message contents
|
||||
Com_ParseToken(&data);
|
||||
if(!strcmp(com_token, "" )) continue;
|
||||
com.strncpy(message, com_token, sizeof(message));
|
||||
}
|
||||
else if(!strcmp(com_token, "classname" ))
|
||||
{
|
||||
Com_ParseToken(&data);
|
||||
if(!com.strcmp(com_token, "info_player_deatchmatch"))
|
||||
num_spawnpoints++;
|
||||
else if(!com.strcmp(com_token, "info_player_start"))
|
||||
num_spawnpoints++;
|
||||
}
|
||||
if(num_spawnpoints > 0) break; // valid map
|
||||
}
|
||||
}
|
||||
|
||||
if( entities) Mem_Free(entities);
|
||||
if( f ) FS_Close(f);
|
||||
|
||||
// format: mapname "maptitle"\n
|
||||
com.sprintf(string, "%s \"%s\"\n", mapname, message );
|
||||
com.strcat(buffer, string); // add new string
|
||||
}
|
||||
}
|
||||
if( t ) Mem_Free(t); // free search result
|
||||
|
||||
// write generated maps.lst
|
||||
if(FS_WriteFile("scripts/maps.lst", buffer, strlen(buffer)))
|
||||
{
|
||||
if( buffer ) Mem_Free(buffer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_WriteVariables
|
||||
|
|
|
@ -262,6 +262,7 @@ void VM_Cmd_Reset( void );
|
|||
|
||||
#define PRVM_GetString vm->GetString
|
||||
#define PRVM_SetEngineString vm->SetEngineString
|
||||
#define PRVM_SetTempString vm->SetTempString
|
||||
#define PRVM_AllocString vm->AllocString
|
||||
#define PRVM_FreeString vm->FreeString
|
||||
|
||||
|
@ -317,6 +318,7 @@ void VM_CvarRegister( void );
|
|||
void VM_CvarSetValue( void );
|
||||
void VM_CvarGetValue( void );
|
||||
void VM_CvarSetString( void );
|
||||
void VM_CvarGetString( void );
|
||||
void VM_ComVA( void );
|
||||
void VM_ComStrlen( void );
|
||||
void VM_TimeStamp( void );
|
||||
|
@ -389,6 +391,7 @@ bool Cmd_GetDemoList(const char *s, char *completedname, int length );
|
|||
bool Cmd_GetMovieList(const char *s, char *completedname, int length );
|
||||
bool Cmd_GetMusicList(const char *s, char *completedname, int length );
|
||||
bool Cmd_GetSoundList(const char *s, char *completedname, int length );
|
||||
bool Cmd_CheckMapsList( void );
|
||||
void Sys_Error( const char *msg, ... );
|
||||
void Sys_SendKeyEvents( void );
|
||||
|
||||
|
|
|
@ -250,16 +250,6 @@ typedef enum
|
|||
Handles byte ordering and avoids alignment errors
|
||||
==============================================================================
|
||||
*/
|
||||
typedef struct sizebuf_s
|
||||
{
|
||||
bool overflowed; // set to true if the buffer size failed
|
||||
byte *data;
|
||||
int maxsize;
|
||||
int cursize;
|
||||
int readcount;
|
||||
int errorcount; // cause by errors
|
||||
} sizebuf_t;
|
||||
|
||||
#define SZ_GetSpace(buf, len) _SZ_GetSpace(buf, len, __FILE__, __LINE__ )
|
||||
#define SZ_Write(buf, data, len) _SZ_Write(buf, data, len, __FILE__, __LINE__ )
|
||||
void SZ_Init (sizebuf_t *buf, byte *data, int length);
|
||||
|
|
|
@ -125,20 +125,20 @@ char *SV_StatusString (void)
|
|||
int statusLength;
|
||||
int playerLength;
|
||||
|
||||
strcpy (status, Cvar_Serverinfo());
|
||||
strcat (status, "\n");
|
||||
com.strcpy( status, Cvar_Serverinfo());
|
||||
com.strcat( status, "\n" );
|
||||
statusLength = strlen(status);
|
||||
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
for( i = 0; i < maxclients->value; i++ )
|
||||
{
|
||||
cl = &svs.clients[i];
|
||||
if (cl->state == cs_connected || cl->state == cs_spawned )
|
||||
{
|
||||
com.sprintf (player, "%i %i \"%s\"\n", cl->edict->priv.sv->client->ps.stats[STAT_FRAGS], cl->ping, cl->name);
|
||||
playerLength = strlen(player);
|
||||
if (statusLength + playerLength >= sizeof(status) )
|
||||
break; // can't hold any more
|
||||
strcpy (status + statusLength, player);
|
||||
if( statusLength + playerLength >= sizeof(status))
|
||||
break; // can't hold any more
|
||||
com.strcpy( status + statusLength, player );
|
||||
statusLength += playerLength;
|
||||
}
|
||||
}
|
||||
|
@ -479,13 +479,13 @@ void SV_ConnectionlessPacket (void)
|
|||
c = Cmd_Argv(0);
|
||||
MsgWarn("SV_ConnectionlessPacket: %s : %s\n", NET_AdrToString(net_from), c);
|
||||
|
||||
if (!strcmp(c, "ping")) SVC_Ping ();
|
||||
else if (!strcmp(c, "ack")) SVC_Ack ();
|
||||
else if (!strcmp(c,"status")) SVC_Status ();
|
||||
else if (!strcmp(c,"info")) SVC_Info ();
|
||||
else if (!strcmp(c,"getchallenge")) SVC_GetChallenge ();
|
||||
else if (!strcmp(c,"connect")) SVC_DirectConnect ();
|
||||
else if (!strcmp(c, "rcon")) SVC_RemoteCommand ();
|
||||
if (!strcmp(c, "ping")) SVC_Ping();
|
||||
else if (!strcmp(c, "ack")) SVC_Ack();
|
||||
else if (!strcmp(c,"status")) SVC_Status();
|
||||
else if (!strcmp(c,"info")) SVC_Info();
|
||||
else if (!strcmp(c,"getchallenge")) SVC_GetChallenge();
|
||||
else if (!strcmp(c,"connect")) SVC_DirectConnect();
|
||||
else if (!strcmp(c, "rcon")) SVC_RemoteCommand();
|
||||
else Msg ("bad connectionless packet from %s:\n%s\n", NET_AdrToString (net_from), s);
|
||||
}
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ SV_WriteSaveFile
|
|||
void SV_WriteSaveFile( char *name )
|
||||
{
|
||||
char path[MAX_SYSPATH];
|
||||
char comment[32];
|
||||
string comment;
|
||||
dsavehdr_t *header;
|
||||
file_t *savfile;
|
||||
bool autosave = false;
|
||||
|
@ -390,7 +390,7 @@ void Sav_LoadComment( lump_t *l )
|
|||
if (l->filelen % sizeof(*in)) Host_Error("Sav_LoadComment: funny lump size\n" );
|
||||
|
||||
size = l->filelen / sizeof(*in);
|
||||
com.strncpy(svs.comment, in, size );
|
||||
com.strncpy( svs.comment, in, size );
|
||||
}
|
||||
|
||||
void Sav_LoadCvars( lump_t *l )
|
||||
|
@ -601,7 +601,7 @@ bool SV_ReadComment( char *comment, int savenum )
|
|||
|
||||
if(!savfile)
|
||||
{
|
||||
com.strncpy( comment, "<empty>", MAX_QPATH );
|
||||
com.strncpy( comment, "<empty>", MAX_STRING );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -611,13 +611,13 @@ bool SV_ReadComment( char *comment, int savenum )
|
|||
|
||||
if(id != IDSAVEHEADER || i != SAVE_VERSION)
|
||||
{
|
||||
com.strncpy( comment, "<corrupted>", MAX_QPATH );
|
||||
com.strncpy( comment, "<corrupted>", MAX_STRING );
|
||||
return false;
|
||||
}
|
||||
|
||||
sav_base = (byte *)header;
|
||||
Sav_LoadComment(&header->lumps[LUMP_COMMENTS]);
|
||||
com.strncpy( comment, svs.comment, MAX_QPATH );
|
||||
com.strncpy( comment, svs.comment, MAX_STRING );
|
||||
Mem_Free( savfile );
|
||||
|
||||
return true;
|
||||
|
@ -2217,11 +2217,11 @@ VM_CvarRegister, // #24 void Cvar_Register( string name, string value, float f
|
|||
VM_CvarSetValue, // #25 void Cvar_SetValue( string name, float value )
|
||||
VM_CvarGetValue, // #26 float Cvar_GetValue( string name )
|
||||
VM_CvarSetString, // #27 void Cvar_SetString( string name, string value )
|
||||
VM_ComVA, // #28 string va( ... )
|
||||
VM_ComStrlen, // #29 float strlen( string text )
|
||||
VM_TimeStamp, // #30 string Com_TimeStamp( float format )
|
||||
VM_LocalCmd, // #31 void LocalCmd( ... )
|
||||
NULL, // #32 -- reserved --
|
||||
VM_CvarGetString, // #28 void VM_CvarGetString( void )
|
||||
VM_ComVA, // #29 string va( ... )
|
||||
VM_ComStrlen, // #30 float strlen( string text )
|
||||
VM_TimeStamp, // #31 string Com_TimeStamp( float format )
|
||||
VM_LocalCmd, // #32 void LocalCmd( ... )
|
||||
NULL, // #33 -- reserved --
|
||||
NULL, // #34 -- reserved --
|
||||
NULL, // #35 -- reserved --
|
||||
|
|
|
@ -1831,7 +1831,7 @@ void SearchLocalGames( void )
|
|||
M_Print( 16 + 16, 120 - 48 + 24, "please be patient." );
|
||||
|
||||
re->EndFrame(); // the text box won't show up unless we do a buffer swap
|
||||
CL_PingServers_f(); // send out info packets
|
||||
//CL_PingServers_f(); // send out info packets
|
||||
}
|
||||
|
||||
void SearchLocalGamesFunc( void *self )
|
||||
|
@ -1978,132 +1978,6 @@ void StartServerActionFunc( void *self )
|
|||
M_ForceMenuOff();
|
||||
}
|
||||
|
||||
bool Menu_CheckMapsList( void )
|
||||
{
|
||||
byte buf[MAX_SYSPATH]; // 1 kb
|
||||
char *buffer, string[MAX_STRING];
|
||||
search_t *t;
|
||||
file_t *f;
|
||||
int i;
|
||||
|
||||
if(FS_FileExists("scripts/maps.lst"))
|
||||
return true; // exist
|
||||
|
||||
t = FS_Search( "maps/*.bsp", false );
|
||||
if(!t) return false;
|
||||
|
||||
buffer = Z_Malloc( t->numfilenames * 2 * sizeof(string));
|
||||
for(i = 0; i < t->numfilenames; i++)
|
||||
{
|
||||
const char *data = NULL;
|
||||
char *entities = NULL;
|
||||
char entfilename[MAX_QPATH];
|
||||
int ver = -1, lumpofs = 0, lumplen = 0;
|
||||
char mapname[MAX_QPATH], message[MAX_QPATH];
|
||||
|
||||
f = FS_Open(t->filenames[i], "rb");
|
||||
FS_FileBase( t->filenames[i], mapname );
|
||||
|
||||
if( f )
|
||||
{
|
||||
int num_spawnpoints = 0;
|
||||
|
||||
memset(buf, 0, 1024);
|
||||
FS_Read(f, buf, 1024);
|
||||
if(!memcmp(buf, "IBSP", 4))
|
||||
{
|
||||
dheader_t *header = (dheader_t *)buf;
|
||||
ver = LittleLong(((int *)buf)[1]);
|
||||
switch(ver)
|
||||
{
|
||||
case 38: // quake2 (xash)
|
||||
case 46: // quake3
|
||||
case 47: // return to castle wolfenstein
|
||||
lumpofs = LittleLong(header->lumps[LUMP_ENTITIES].fileofs);
|
||||
lumplen = LittleLong(header->lumps[LUMP_ENTITIES].filelen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lump_t ents; // quake1 entity lump
|
||||
memcpy(&ents, buf + 4, sizeof(lump_t)); // skip first four bytes (version)
|
||||
ver = LittleLong(((int *)buf)[0]);
|
||||
|
||||
switch( ver )
|
||||
{
|
||||
case 28: // quake 1 beta
|
||||
case 29: // quake 1 regular
|
||||
case 30: // Half-Life regular
|
||||
lumpofs = LittleLong(ents.fileofs);
|
||||
lumplen = LittleLong(ents.filelen);
|
||||
break;
|
||||
default:
|
||||
ver = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
com.strncpy(entfilename, t->filenames[i], sizeof(entfilename));
|
||||
FS_StripExtension( entfilename );
|
||||
FS_DefaultExtension( entfilename, ".ent" );
|
||||
entities = (char *)FS_LoadFile(entfilename, NULL);
|
||||
|
||||
if( !entities && lumplen >= 10 )
|
||||
{
|
||||
FS_Seek(f, lumpofs, SEEK_SET);
|
||||
entities = (char *)Z_Malloc(lumplen + 1);
|
||||
FS_Read(f, entities, lumplen);
|
||||
}
|
||||
if(entities)
|
||||
{
|
||||
// if there are entities to parse, a missing message key just
|
||||
// means there is no title, so clear the message string now
|
||||
message[0] = 0;
|
||||
data = entities;
|
||||
com.strncpy(message, "No Title", MAX_QPATH);
|
||||
|
||||
while(Com_ParseToken(&data))
|
||||
{
|
||||
if(!strcmp(com_token, "{" )) continue;
|
||||
else if(!strcmp(com_token, "}" )) break;
|
||||
else if(!strcmp(com_token, "message" ))
|
||||
{
|
||||
// get the message contents
|
||||
Com_ParseToken(&data);
|
||||
if(!strcmp(com_token, "" )) continue;
|
||||
com.strncpy(message, com_token, sizeof(message));
|
||||
}
|
||||
else if(!strcmp(com_token, "classname" ))
|
||||
{
|
||||
Com_ParseToken(&data);
|
||||
if(!com.strcmp(com_token, "info_player_deatchmatch"))
|
||||
num_spawnpoints++;
|
||||
else if(!com.strcmp(com_token, "info_player_start"))
|
||||
num_spawnpoints++;
|
||||
}
|
||||
if(num_spawnpoints > 0) break; // valid map
|
||||
}
|
||||
}
|
||||
|
||||
if( entities) Mem_Free(entities);
|
||||
if( f ) FS_Close(f);
|
||||
|
||||
// format: mapname "maptitle"/r
|
||||
com.sprintf(string, "%s \"%s\"\r", mapname, message );
|
||||
com.strcat(buffer, string); // add new string
|
||||
}
|
||||
}
|
||||
if( t ) Mem_Free(t); // free search result
|
||||
|
||||
// write generated maps.lst
|
||||
if(FS_WriteFile("scripts/maps.lst", buffer, strlen(buffer)))
|
||||
{
|
||||
if( buffer ) Mem_Free(buffer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void StartServer_MenuInit( void )
|
||||
{
|
||||
static const char *dm_coop_names[] =
|
||||
|
@ -2119,7 +1993,7 @@ void StartServer_MenuInit( void )
|
|||
file_t *fp;
|
||||
|
||||
// create new maplist if not exist
|
||||
if(!Menu_CheckMapsList())
|
||||
if(!Cmd_CheckMapsList())
|
||||
{
|
||||
MsgWarn("StartServer_MenuInit: maps.lst not found\n");
|
||||
return;
|
||||
|
|
|
@ -44,11 +44,139 @@ void PF_readcomment( void )
|
|||
return;
|
||||
|
||||
savenum = (int)PRVM_G_FLOAT(OFS_PARM0);
|
||||
|
||||
PRVM_G_FLOAT(OFS_PARM1) = (float)SV_ReadComment( comment[savenum], savenum );
|
||||
SV_ReadComment( comment[savenum], savenum );
|
||||
PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString( comment[savenum] );
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
PF_joinserver
|
||||
|
||||
float JoinServer( float serevernum )
|
||||
=========
|
||||
*/
|
||||
void PF_joinserver( void )
|
||||
{
|
||||
string buffer;
|
||||
int i;
|
||||
|
||||
if(!VM_ValidateArgs( "JoinServer", 1 ))
|
||||
return;
|
||||
i = (int)PRVM_G_FLOAT(OFS_PARM0);
|
||||
PRVM_G_FLOAT(OFS_RETURN) = 0;
|
||||
|
||||
if( i < cls.numservers && cls.serverlist[i].maxplayers > 1 && cls.serverlist[i].netaddress )
|
||||
{
|
||||
com.sprintf( buffer, "connect %s\n", cls.serverlist[i].netaddress );
|
||||
Cbuf_AddText( buffer );
|
||||
PRVM_G_FLOAT(OFS_RETURN) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
PF_getserverinfo
|
||||
|
||||
string ServerInfo( float num )
|
||||
=========
|
||||
*/
|
||||
void PF_getserverinfo( void )
|
||||
{
|
||||
static string serverinfo[MAX_SERVERS];
|
||||
serverinfo_t *s;
|
||||
int i;
|
||||
|
||||
if(!VM_ValidateArgs( "ServerInfo", 1 ))
|
||||
return;
|
||||
|
||||
i = (int)PRVM_G_FLOAT(OFS_PARM0);
|
||||
PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString( "<empty>" );
|
||||
|
||||
if( i < cls.numservers )
|
||||
{
|
||||
s = &cls.serverlist[i];
|
||||
if( s && s->hostname && s->maxplayers > 1 ) // ignore singleplayer servers
|
||||
{
|
||||
com.snprintf( serverinfo[i], MAX_STRING, "%s %15s %7i/%i %7i\n", s->hostname, s->mapname, s->numplayers, s->maxplayers, s->ping );
|
||||
PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString( serverinfo[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
PF_getmapslist
|
||||
|
||||
string GetMapsList( void )
|
||||
=========
|
||||
*/
|
||||
int mapcount = 0;
|
||||
|
||||
void PF_getmapslist( void )
|
||||
{
|
||||
static char mapstring[MAX_INPUTLINE];
|
||||
|
||||
if(!VM_ValidateArgs( "GetMapsList", 0 ))
|
||||
return;
|
||||
|
||||
PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString( "'none'" );
|
||||
mapstring[0] = '\0';
|
||||
mapcount = 0;
|
||||
|
||||
// create new maplist if not exist
|
||||
if(!Cmd_CheckMapsList())
|
||||
{
|
||||
MsgWarn("GetMapsList: maps.lst not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// paranoid mode :-)
|
||||
if(!Com_LoadScript( "scripts/maps.lst", NULL, 0 ))
|
||||
return;
|
||||
|
||||
while(Com_GetToken( true ))
|
||||
{
|
||||
com.strcat( mapstring, va("'%s'", com_token ));
|
||||
while(Com_TryToken()); // skip other stuff
|
||||
mapcount++;
|
||||
}
|
||||
PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString( mapstring );
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
PF_getmapscount
|
||||
|
||||
string GetMapsCount( void )
|
||||
=========
|
||||
*/
|
||||
void PF_getmapscount( void )
|
||||
{
|
||||
if(!VM_ValidateArgs( "GetMapsCount", 0 ))
|
||||
return;
|
||||
|
||||
PRVM_G_FLOAT(OFS_RETURN) = mapcount;
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
PF_newserver
|
||||
|
||||
void NewServer( string mapname )
|
||||
=========
|
||||
*/
|
||||
void PF_newserver( void )
|
||||
{
|
||||
const char *s;
|
||||
|
||||
if(!VM_ValidateArgs( "NewServer", 1 ))
|
||||
return;
|
||||
s = PRVM_G_STRING(OFS_PARM0);
|
||||
VM_ValidateString( s );
|
||||
|
||||
Cbuf_AddText( va("map %s\n", s ));
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
PF_substring
|
||||
|
@ -478,11 +606,11 @@ VM_CvarRegister, // #24 void Cvar_Register( string name, string value, float f
|
|||
VM_CvarSetValue, // #25 void Cvar_SetValue( string name, float value )
|
||||
VM_CvarGetValue, // #26 float Cvar_GetValue( string name )
|
||||
VM_CvarSetString, // #27 void Cvar_SetString( string name, string value )
|
||||
VM_ComVA, // #28 string va( ... )
|
||||
VM_ComStrlen, // #29 float strlen( string text )
|
||||
VM_TimeStamp, // #30 string Com_TimeStamp( float format )
|
||||
VM_LocalCmd, // #31 void LocalCmd( ... )
|
||||
NULL, // #32 -- reserved --
|
||||
VM_CvarGetString, // #28 void VM_CvarGetString( void )
|
||||
VM_ComVA, // #29 string va( ... )
|
||||
VM_ComStrlen, // #30 float strlen( string text )
|
||||
VM_TimeStamp, // #31 string Com_TimeStamp( float format )
|
||||
VM_LocalCmd, // #32 void LocalCmd( ... )
|
||||
NULL, // #33 -- reserved --
|
||||
NULL, // #34 -- reserved --
|
||||
NULL, // #35 -- reserved --
|
||||
|
@ -560,6 +688,11 @@ PF_callfunction, // #117 void callfunction( ..., string function_name )
|
|||
PF_testfunction, // #118 float testfunction( string function_name )
|
||||
PF_newgame, // #119 void NewGame( void )
|
||||
PF_readcomment, // #120 string ReadComment( float savenum )
|
||||
PF_joinserver, // #121 float JoinServer( float num )
|
||||
PF_getserverinfo, // #122 string ServerInfo( float num )
|
||||
PF_getmapslist, // #123 string GetMapsList( void )
|
||||
PF_getmapscount, // #124 float GetMapsCount( void )
|
||||
PF_newserver, // #125 void NewServer( string mapname )
|
||||
};
|
||||
|
||||
const int vm_ui_numbuiltins = sizeof(vm_ui_builtins) / sizeof(prvm_builtin_t);
|
|
@ -22,13 +22,6 @@ void UI_KeyEvent( int key )
|
|||
PRVM_ExecuteProgram (prog->globals.ui->m_keydown, "QC function m_keydown is missing");
|
||||
|
||||
PRVM_End;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
case K_ESCAPE:
|
||||
UI_HideMenu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UI_Draw( void )
|
||||
|
|
|
@ -375,8 +375,9 @@ bool SC_EndOfScript (bool newline)
|
|||
return false;
|
||||
}
|
||||
|
||||
// release script
|
||||
Mem_Free (script->buffer);
|
||||
// FIXME: stupid xash bug
|
||||
if(Mem_IsAllocated( script->buffer ))
|
||||
Mem_Free( script->buffer );
|
||||
if(script == scriptstack + 1)
|
||||
{
|
||||
endofscript = true;
|
||||
|
|
|
@ -316,6 +316,16 @@ typedef struct pmove_s
|
|||
int (*pointcontents)( vec3_t point );
|
||||
} pmove_t;
|
||||
|
||||
typedef struct sizebuf_s
|
||||
{
|
||||
bool overflowed; // set to true if the buffer size failed
|
||||
byte *data;
|
||||
int maxsize;
|
||||
int cursize;
|
||||
int readcount;
|
||||
int errorcount; // cause by errors
|
||||
} sizebuf_t;
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
|
@ -519,6 +529,7 @@ typedef struct vprogs_exp_s
|
|||
// string manipulations
|
||||
const char *(*GetString)( int num );
|
||||
int (*SetEngineString)( const char *s );
|
||||
int (*SetTempString)( const char *s );
|
||||
int (*AllocString)( size_t bufferlength, char **pointer );
|
||||
void (*FreeString)( int num );
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "vprogs.h"
|
||||
|
||||
static prvm_prog_t prog_list[PRVM_MAXPROGS];
|
||||
sizebuf_t vm_tempstringsbuf;
|
||||
|
||||
int prvm_type_size[8] = {1, sizeof(string_t)/4,1,3,1,1, sizeof(func_t)/4, sizeof(void *)/4};
|
||||
|
||||
|
@ -1972,29 +1973,55 @@ edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
|
|||
|
||||
const char *PRVM_GetString(int num)
|
||||
{
|
||||
if (num >= 0 && num < vm.prog->stringssize)
|
||||
return vm.prog->strings + num;
|
||||
else if (num < 0 && num >= -vm.prog->numknownstrings)
|
||||
if( num >= 0 )
|
||||
{
|
||||
num = -1 - num;
|
||||
if (!vm.prog->knownstrings[num])
|
||||
PRVM_ERROR("PRVM_GetString: attempt to get string that is already freed");
|
||||
return vm.prog->knownstrings[num];
|
||||
if( num < vm.prog->stringssize ) return vm.prog->strings + num;
|
||||
else if( num <= vm.prog->stringssize + vm_tempstringsbuf.maxsize)
|
||||
{
|
||||
num -= vm.prog->stringssize;
|
||||
if( num < vm_tempstringsbuf.cursize )
|
||||
return (char *)vm_tempstringsbuf.data + num;
|
||||
else
|
||||
{
|
||||
VM_Warning("PRVM_GetString: Invalid temp-string offset (%i >= %i vm_tempstringsbuf.cursize)\n", num, vm_tempstringsbuf.cursize);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VM_Warning("PRVM_GetString: Invalid constant-string offset (%i >= %i prog->stringssize)\n", num, vm.prog->stringssize);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PRVM_ERROR("PRVM_GetString: invalid string offset %i", num);
|
||||
return "";
|
||||
num = -1 - num;
|
||||
if (num < vm.prog->numknownstrings)
|
||||
{
|
||||
if (!vm.prog->knownstrings[num])
|
||||
VM_Warning("PRVM_GetString: Invalid zone-string offset (%i has been freed)\n", num);
|
||||
return vm.prog->knownstrings[num];
|
||||
}
|
||||
else
|
||||
{
|
||||
VM_Warning("PRVM_GetString: Invalid zone-string offset (%i >= %i)\n", num, vm.prog->numknownstrings);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PRVM_SetEngineString(const char *s)
|
||||
int PRVM_SetEngineString( const char *s )
|
||||
{
|
||||
int i;
|
||||
if (!s)
|
||||
return 0;
|
||||
if (s >= vm.prog->strings && s <= vm.prog->strings + vm.prog->stringssize)
|
||||
PRVM_ERROR("PRVM_SetEngineString: s in vm.prog->strings area");
|
||||
// if it's in the tempstrings area, use a reserved range
|
||||
// (otherwise we'd get millions of useless string offsets cluttering the database)
|
||||
if (s >= (char *)vm_tempstringsbuf.data && s < (char *)vm_tempstringsbuf.data + vm_tempstringsbuf.maxsize)
|
||||
return vm.prog->stringssize + (s - (char *)vm_tempstringsbuf.data);
|
||||
// see if it's a known string address
|
||||
for (i = 0;i < vm.prog->numknownstrings;i++)
|
||||
if (vm.prog->knownstrings[i] == s)
|
||||
return -1 - i;
|
||||
|
@ -2025,6 +2052,44 @@ int PRVM_SetEngineString(const char *s)
|
|||
return -1 - i;
|
||||
}
|
||||
|
||||
// temp string handling
|
||||
|
||||
// all tempstrings go into this buffer consecutively, and it is reset
|
||||
// whenever PRVM_ExecuteProgram returns to the engine
|
||||
// (technically each PRVM_ExecuteProgram call saves the cursize value and
|
||||
// restores it on return, so multiple recursive calls can share the same
|
||||
// buffer)
|
||||
// the buffer size is automatically grown as needed
|
||||
|
||||
int PRVM_SetTempString( const char *s )
|
||||
{
|
||||
int size;
|
||||
char *t;
|
||||
|
||||
if (!s) return 0;
|
||||
|
||||
size = (int)com.strlen(s) + 1;
|
||||
MsgDev( D_MEMORY, "PRVM_SetTempString: cursize %i, size %i\n", vm_tempstringsbuf.cursize, size);
|
||||
if (vm_tempstringsbuf.maxsize < vm_tempstringsbuf.cursize + size)
|
||||
{
|
||||
size_t old_maxsize = vm_tempstringsbuf.maxsize;
|
||||
if( vm_tempstringsbuf.cursize + size >= 1<<28 )
|
||||
PRVM_ERROR("PRVM_SetTempString: ran out of tempstring memory! (refusing to grow tempstring buffer over 256MB, cursize %i, size %i)\n", vm_tempstringsbuf.cursize, size);
|
||||
vm_tempstringsbuf.maxsize = max( vm_tempstringsbuf.maxsize, 65536 );
|
||||
while( vm_tempstringsbuf.maxsize < vm_tempstringsbuf.cursize + size )
|
||||
vm_tempstringsbuf.maxsize *= 2;
|
||||
if (vm_tempstringsbuf.maxsize != old_maxsize || vm_tempstringsbuf.data == NULL)
|
||||
{
|
||||
MsgDev( D_NOTE, "PRVM_SetTempString: enlarging tempstrings buffer (%iKB -> %iKB)\n", old_maxsize/1024, vm_tempstringsbuf.maxsize/1024);
|
||||
vm_tempstringsbuf.data = Mem_Realloc( vm.prog->progs_mempool, vm_tempstringsbuf.data, vm_tempstringsbuf.maxsize );
|
||||
}
|
||||
}
|
||||
t = (char *)vm_tempstringsbuf.data + vm_tempstringsbuf.cursize;
|
||||
Mem_Copy( t, s, size );
|
||||
vm_tempstringsbuf.cursize += size;
|
||||
return PRVM_SetEngineString( t );
|
||||
}
|
||||
|
||||
int PRVM_AllocString(size_t bufferlength, char **pointer)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -323,6 +323,7 @@ vprogs_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
|
|||
vm.LoadFromFile = PRVM_ED_LoadFromFile;
|
||||
vm.GetString = PRVM_GetString;
|
||||
vm.SetEngineString = PRVM_SetEngineString;
|
||||
vm.SetTempString = PRVM_SetTempString;
|
||||
vm.AllocString = PRVM_AllocString;
|
||||
vm.FreeString = PRVM_FreeString;
|
||||
|
||||
|
|
|
@ -418,6 +418,7 @@ void PRVM_ED_PrintNum (int ent);
|
|||
|
||||
const char *PRVM_GetString(int num);
|
||||
int PRVM_SetEngineString(const char *s);
|
||||
int PRVM_SetTempString( const char *s );
|
||||
int PRVM_AllocString(size_t bufferlength, char **pointer);
|
||||
void PRVM_FreeString(int num);
|
||||
|
||||
|
|
Reference in New Issue