2010-02-15 23:26:55 +00:00
/*
Copyright ( C ) 1996 - 2001 Id Software , Inc .
Copyright ( C ) 2002 - 2009 John Fitzgibbons and others
Copyright ( C ) 2007 - 2008 Kristian Duske
2014-09-22 08:55:46 +00:00
Copyright ( C ) 2010 - 2014 QuakeSpasm developers
2010-02-15 23:26:55 +00:00
This program 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 2
of the License , or ( at your option ) any later version .
This program 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 this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2010-06-21 11:50:21 +00:00
# include "quakedef.h"
2014-08-01 11:21:54 +00:00
# ifndef _WIN32
2012-04-18 20:33:12 +00:00
# include <dirent.h>
2014-08-01 11:21:54 +00:00
# endif
2010-02-15 23:26:55 +00:00
extern cvar_t pausable ;
int current_skill ;
void Mod_Print ( void ) ;
/*
= = = = = = = = = = = = = = = = = =
Host_Quit_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Quit_f ( void )
{
if ( key_dest ! = key_console & & cls . state ! = ca_dedicated )
{
M_Menu_Quit_f ( ) ;
return ;
}
CL_Disconnect ( ) ;
Host_ShutdownServer ( false ) ;
Sys_Quit ( ) ;
}
//==============================================================================
//johnfitz -- extramaps management
//==============================================================================
2015-05-29 18:33:14 +00:00
/*
= = = = = = = = = = = = = = = = = =
FileList_Add
= = = = = = = = = = = = = = = = = =
*/
void FileList_Add ( const char * name , filelist_item_t * * list )
2010-02-15 23:26:55 +00:00
{
2015-05-29 18:33:14 +00:00
filelist_item_t * item , * cursor , * prev ;
2010-02-15 23:26:55 +00:00
2010-08-02 19:45:16 +00:00
// ignore duplicate
2015-05-29 18:33:14 +00:00
for ( item = * list ; item ; item = item - > next )
2010-08-02 19:45:16 +00:00
{
2015-05-29 18:33:14 +00:00
if ( ! Q_strcmp ( name , item - > name ) )
2010-02-15 23:26:55 +00:00
return ;
2010-08-02 19:45:16 +00:00
}
2010-02-15 23:26:55 +00:00
2015-05-29 18:33:14 +00:00
item = ( filelist_item_t * ) Z_Malloc ( sizeof ( filelist_item_t ) ) ;
q_strlcpy ( item - > name , name , sizeof ( item - > name ) ) ;
2010-02-15 23:26:55 +00:00
2010-08-02 19:45:16 +00:00
// insert each entry in alphabetical order
2015-05-29 18:33:14 +00:00
if ( * list = = NULL | |
q_strcasecmp ( item - > name , ( * list ) - > name ) < 0 ) //insert at front
2010-02-15 23:26:55 +00:00
{
2015-05-29 18:33:14 +00:00
item - > next = * list ;
* list = item ;
2010-08-02 19:45:16 +00:00
}
else //insert later
2010-02-15 23:26:55 +00:00
{
2015-05-29 18:33:14 +00:00
prev = * list ;
cursor = ( * list ) - > next ;
while ( cursor & & ( q_strcasecmp ( item - > name , cursor - > name ) > 0 ) )
2010-02-15 23:26:55 +00:00
{
2010-08-02 19:45:16 +00:00
prev = cursor ;
cursor = cursor - > next ;
}
2015-05-29 18:33:14 +00:00
item - > next = prev - > next ;
prev - > next = item ;
2010-08-02 19:45:16 +00:00
}
2010-02-15 23:26:55 +00:00
}
2015-05-30 02:28:58 +00:00
static void FileList_Clear ( filelist_item_t * * list )
{
filelist_item_t * blah ;
while ( * list )
{
blah = ( * list ) - > next ;
Z_Free ( * list ) ;
* list = blah ;
}
}
2015-05-29 18:33:14 +00:00
filelist_item_t * extralevels ;
void ExtraMaps_Add ( const char * name )
{
FileList_Add ( name , & extralevels ) ;
}
2010-02-15 23:26:55 +00:00
void ExtraMaps_Init ( void )
{
2014-08-01 11:21:54 +00:00
# ifdef _WIN32
WIN32_FIND_DATA fdat ;
HANDLE fhnd ;
# else
2010-02-17 23:32:04 +00:00
DIR * dir_p ;
struct dirent * dir_t ;
2014-08-01 11:21:54 +00:00
# endif
2010-08-02 19:45:16 +00:00
char filestring [ MAX_OSPATH ] ;
char mapname [ 32 ] ;
char ignorepakdir [ 32 ] ;
2010-02-17 23:32:04 +00:00
searchpath_t * search ;
pack_t * pak ;
int i ;
2010-02-15 23:26:55 +00:00
2010-08-02 19:45:16 +00:00
// we don't want to list the maps in id1 pakfiles,
// because these are not "add-on" levels
2011-12-27 10:50:42 +00:00
q_snprintf ( ignorepakdir , sizeof ( ignorepakdir ) , " /%s/ " , GAMENAME ) ;
2010-02-15 23:26:55 +00:00
2010-08-02 19:45:16 +00:00
for ( search = com_searchpaths ; search ; search = search - > next )
2010-02-15 23:26:55 +00:00
{
if ( * search - > filename ) //directory
{
2014-08-01 11:21:54 +00:00
# ifdef _WIN32
q_snprintf ( filestring , sizeof ( filestring ) , " %s/maps/*.bsp " , search - > filename ) ;
fhnd = FindFirstFile ( filestring , & fdat ) ;
if ( fhnd = = INVALID_HANDLE_VALUE )
continue ;
do
{
COM_StripExtension ( fdat . cFileName , mapname , sizeof ( mapname ) ) ;
ExtraMaps_Add ( mapname ) ;
} while ( FindNextFile ( fhnd , & fdat ) ) ;
FindClose ( fhnd ) ;
# else
2011-12-27 10:50:42 +00:00
q_snprintf ( filestring , sizeof ( filestring ) , " %s/maps/ " , search - > filename ) ;
2010-02-17 23:32:04 +00:00
dir_p = opendir ( filestring ) ;
if ( dir_p = = NULL )
continue ;
while ( ( dir_t = readdir ( dir_p ) ) ! = NULL )
{
2014-08-01 11:15:58 +00:00
if ( q_strcasecmp ( COM_FileGetExtension ( dir_t - > d_name ) , " bsp " ) ! = 0 )
2010-02-17 23:32:04 +00:00
continue ;
2011-12-27 08:04:02 +00:00
COM_StripExtension ( dir_t - > d_name , mapname , sizeof ( mapname ) ) ;
2010-02-15 23:26:55 +00:00
ExtraMaps_Add ( mapname ) ;
2010-02-17 23:32:04 +00:00
}
closedir ( dir_p ) ;
2014-08-01 11:21:54 +00:00
# endif
2010-02-15 23:26:55 +00:00
}
else //pakfile
{
2010-08-02 19:45:16 +00:00
if ( ! strstr ( search - > pack - > filename , ignorepakdir ) )
{ //don't list standard id maps
for ( i = 0 , pak = search - > pack ; i < pak - > numfiles ; i + + )
2010-02-17 23:32:04 +00:00
{
2014-08-01 11:15:58 +00:00
if ( ! strcmp ( COM_FileGetExtension ( pak - > files [ i ] . name ) , " bsp " ) )
2010-02-17 23:32:04 +00:00
{
2010-08-02 19:45:16 +00:00
if ( pak - > files [ i ] . filelen > 32 * 1024 )
{ // don't list files under 32k (ammo boxes etc)
2011-12-27 08:04:02 +00:00
COM_StripExtension ( pak - > files [ i ] . name + 5 , mapname , sizeof ( mapname ) ) ;
2010-02-15 23:26:55 +00:00
ExtraMaps_Add ( mapname ) ;
}
2010-02-17 23:32:04 +00:00
}
}
}
2010-02-15 23:26:55 +00:00
}
}
}
2015-05-30 02:28:58 +00:00
static void ExtraMaps_Clear ( void )
2010-02-15 23:26:55 +00:00
{
2015-05-30 02:28:58 +00:00
FileList_Clear ( & extralevels ) ;
2010-02-15 23:26:55 +00:00
}
void ExtraMaps_NewGame ( void )
{
ExtraMaps_Clear ( ) ;
ExtraMaps_Init ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Maps_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Maps_f ( void )
{
int i ;
2015-01-24 08:26:14 +00:00
filelist_item_t * level ;
2010-02-15 23:26:55 +00:00
2010-08-02 19:45:16 +00:00
for ( level = extralevels , i = 0 ; level ; level = level - > next , i + + )
2010-02-15 23:26:55 +00:00
Con_SafePrintf ( " %s \n " , level - > name ) ;
if ( i )
Con_SafePrintf ( " %i map(s) \n " , i ) ;
else
Con_SafePrintf ( " no maps found \n " ) ;
}
//==============================================================================
//johnfitz -- modlist management
//==============================================================================
2015-01-24 08:26:14 +00:00
filelist_item_t * modlist ;
2010-02-15 23:26:55 +00:00
2010-08-29 02:22:55 +00:00
void Modlist_Add ( const char * name )
2010-02-15 23:26:55 +00:00
{
2015-05-29 18:33:14 +00:00
FileList_Add ( name , & modlist ) ;
2010-02-15 23:26:55 +00:00
}
2014-08-01 11:21:54 +00:00
# ifdef _WIN32
void Modlist_Init ( void )
{
2017-08-04 20:36:59 +00:00
WIN32_FIND_DATA fdat ;
HANDLE fhnd ;
2017-06-23 22:02:40 +00:00
DWORD attribs ;
2014-08-01 11:21:54 +00:00
char dir_string [ MAX_OSPATH ] , mod_string [ MAX_OSPATH ] ;
q_snprintf ( dir_string , sizeof ( dir_string ) , " %s/* " , com_basedir ) ;
fhnd = FindFirstFile ( dir_string , & fdat ) ;
if ( fhnd = = INVALID_HANDLE_VALUE )
return ;
do
{
2017-06-23 22:02:40 +00:00
if ( ! strcmp ( fdat . cFileName , " . " ) | | ! strcmp ( fdat . cFileName , " .. " ) )
2015-06-03 03:54:47 +00:00
continue ;
2017-06-23 22:02:40 +00:00
q_snprintf ( mod_string , sizeof ( mod_string ) , " %s/%s " , com_basedir , fdat . cFileName ) ;
attribs = GetFileAttributes ( mod_string ) ;
2017-08-04 20:36:59 +00:00
if ( attribs ! = INVALID_FILE_ATTRIBUTES & & ( attribs & FILE_ATTRIBUTE_DIRECTORY ) ) {
/* don't bother testing for pak files / progs.dat */
2014-08-01 11:21:54 +00:00
Modlist_Add ( fdat . cFileName ) ;
}
} while ( FindNextFile ( fhnd , & fdat ) ) ;
FindClose ( fhnd ) ;
}
# else
2010-02-15 23:26:55 +00:00
void Modlist_Init ( void )
{
2010-02-17 23:32:04 +00:00
DIR * dir_p , * mod_dir_p ;
2017-07-28 20:50:11 +00:00
struct dirent * dir_t ;
2014-08-01 11:15:58 +00:00
char dir_string [ MAX_OSPATH ] , mod_string [ MAX_OSPATH ] ;
2010-02-15 23:26:55 +00:00
2014-07-30 09:02:25 +00:00
q_snprintf ( dir_string , sizeof ( dir_string ) , " %s/ " , com_basedir ) ;
2010-02-17 23:32:04 +00:00
dir_p = opendir ( dir_string ) ;
if ( dir_p = = NULL )
return ;
while ( ( dir_t = readdir ( dir_p ) ) ! = NULL )
{
2014-08-01 11:15:58 +00:00
if ( ! strcmp ( dir_t - > d_name , " . " ) | | ! strcmp ( dir_t - > d_name , " .. " ) )
2010-02-17 23:32:04 +00:00
continue ;
2017-06-23 22:02:40 +00:00
if ( ! q_strcasecmp ( COM_FileGetExtension ( dir_t - > d_name ) , " app " ) ) // skip .app bundles on macOS
continue ;
2014-08-01 11:15:58 +00:00
q_snprintf ( mod_string , sizeof ( mod_string ) , " %s%s/ " , dir_string , dir_t - > d_name ) ;
mod_dir_p = opendir ( mod_string ) ;
2010-02-17 23:32:04 +00:00
if ( mod_dir_p = = NULL )
continue ;
2017-08-04 20:36:59 +00:00
/* don't bother testing for pak files / progs.dat */
2017-06-23 22:02:40 +00:00
Modlist_Add ( dir_t - > d_name ) ;
2010-02-17 23:32:04 +00:00
closedir ( mod_dir_p ) ;
}
closedir ( dir_p ) ;
2010-02-15 23:26:55 +00:00
}
2014-08-01 11:21:54 +00:00
# endif
2010-02-15 23:26:55 +00:00
2015-05-30 02:28:58 +00:00
//==============================================================================
//ericw -- demo list management
//==============================================================================
filelist_item_t * demolist ;
static void DemoList_Clear ( void )
{
FileList_Clear ( & demolist ) ;
}
void DemoList_Rebuild ( void )
{
DemoList_Clear ( ) ;
DemoList_Init ( ) ;
}
// TODO: Factor out to a general-purpose file searching function
void DemoList_Init ( void )
{
# ifdef _WIN32
WIN32_FIND_DATA fdat ;
HANDLE fhnd ;
# else
DIR * dir_p ;
struct dirent * dir_t ;
# endif
char filestring [ MAX_OSPATH ] ;
char demname [ 32 ] ;
char ignorepakdir [ 32 ] ;
searchpath_t * search ;
pack_t * pak ;
int i ;
// we don't want to list the demos in id1 pakfiles,
// because these are not "add-on" demos
q_snprintf ( ignorepakdir , sizeof ( ignorepakdir ) , " /%s/ " , GAMENAME ) ;
for ( search = com_searchpaths ; search ; search = search - > next )
{
if ( * search - > filename ) //directory
{
# ifdef _WIN32
q_snprintf ( filestring , sizeof ( filestring ) , " %s/*.dem " , search - > filename ) ;
fhnd = FindFirstFile ( filestring , & fdat ) ;
if ( fhnd = = INVALID_HANDLE_VALUE )
continue ;
do
{
COM_StripExtension ( fdat . cFileName , demname , sizeof ( demname ) ) ;
FileList_Add ( demname , & demolist ) ;
} while ( FindNextFile ( fhnd , & fdat ) ) ;
FindClose ( fhnd ) ;
# else
q_snprintf ( filestring , sizeof ( filestring ) , " %s/ " , search - > filename ) ;
dir_p = opendir ( filestring ) ;
if ( dir_p = = NULL )
continue ;
while ( ( dir_t = readdir ( dir_p ) ) ! = NULL )
{
if ( q_strcasecmp ( COM_FileGetExtension ( dir_t - > d_name ) , " dem " ) ! = 0 )
continue ;
COM_StripExtension ( dir_t - > d_name , demname , sizeof ( demname ) ) ;
FileList_Add ( demname , & demolist ) ;
}
closedir ( dir_p ) ;
# endif
}
else //pakfile
{
if ( ! strstr ( search - > pack - > filename , ignorepakdir ) )
{ //don't list standard id demos
for ( i = 0 , pak = search - > pack ; i < pak - > numfiles ; i + + )
{
if ( ! strcmp ( COM_FileGetExtension ( pak - > files [ i ] . name ) , " dem " ) )
{
COM_StripExtension ( pak - > files [ i ] . name , demname , sizeof ( demname ) ) ;
FileList_Add ( demname , & demolist ) ;
}
}
}
}
}
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
Host_Mods_f - - johnfitz
list all potential mod directories ( contain either a pak file or a progs . dat )
= = = = = = = = = = = = = = = = = =
*/
void Host_Mods_f ( void )
{
int i ;
2015-01-24 08:26:14 +00:00
filelist_item_t * mod ;
2010-02-15 23:26:55 +00:00
for ( mod = modlist , i = 0 ; mod ; mod = mod - > next , i + + )
Con_SafePrintf ( " %s \n " , mod - > name ) ;
if ( i )
Con_SafePrintf ( " %i mod(s) \n " , i ) ;
else
Con_SafePrintf ( " no mods found \n " ) ;
}
//==============================================================================
/*
= = = = = = = = = = = = =
Host_Mapname_f - - johnfitz
= = = = = = = = = = = = =
*/
void Host_Mapname_f ( void )
{
if ( sv . active )
{
2010-04-26 21:16:50 +00:00
Con_Printf ( " \" mapname \" is \" %s \" \n " , sv . name ) ;
2010-02-15 23:26:55 +00:00
return ;
}
if ( cls . state = = ca_connected )
{
2010-04-26 21:16:50 +00:00
Con_Printf ( " \" mapname \" is \" %s \" \n " , cl . mapname ) ;
2010-02-15 23:26:55 +00:00
return ;
}
Con_Printf ( " no map loaded \n " ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Status_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Status_f ( void )
{
2017-07-28 12:50:10 +00:00
void ( * print_fn ) ( const char * fmt , . . . )
FUNCP_PRINTF ( 1 , 2 ) ;
2010-02-15 23:26:55 +00:00
client_t * client ;
int seconds ;
int minutes ;
int hours = 0 ;
2017-09-17 02:12:53 +00:00
int j , i ;
2010-02-15 23:26:55 +00:00
if ( cmd_source = = src_command )
{
if ( ! sv . active )
{
Cmd_ForwardToServer ( ) ;
return ;
}
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
print_fn = Con_Printf ;
2010-02-15 23:26:55 +00:00
}
else
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
print_fn = SV_ClientPrintf ;
2010-02-15 23:26:55 +00:00
2017-09-17 02:12:53 +00:00
print_fn ( " host: %s \n " , Cvar_VariableString ( " hostname " ) ) ;
print_fn ( " version: " ENGINE_NAME_AND_VER " \n " ) ;
if ( ipv4Available )
print_fn ( " tcp/ip: %s \n " , my_ipv4_address ) ; //Spike -- FIXME: we should really have ports displayed here or something
if ( ipv6Available )
print_fn ( " ipv6: %s \n " , my_ipv6_address ) ;
2010-02-15 23:26:55 +00:00
if ( ipxAvailable )
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
print_fn ( " ipx: %s \n " , my_ipx_address ) ;
2017-09-17 02:12:53 +00:00
print_fn ( " map: %s \n " , sv . name ) ;
for ( i = 1 , j = 0 ; i < MAX_MODELS ; i + + )
if ( sv . model_precache [ i ] )
j + + ;
print_fn ( " models: %i/%i \n " , j , MAX_MODELS - 1 ) ;
for ( i = 1 , j = 0 ; i < MAX_SOUNDS ; i + + )
if ( sv . sound_precache [ i ] )
j + + ;
print_fn ( " sounds: %i/%i \n " , j , MAX_SOUNDS - 1 ) ;
for ( i = 0 , j = 0 ; i < MAX_PARTICLETYPES ; i + + )
if ( sv . particle_precache [ i ] )
j + + ;
if ( j )
print_fn ( " effects: %i/%i \n " , j , MAX_PARTICLETYPES - 1 ) ;
2018-05-01 00:35:14 +00:00
for ( i = 1 , j = 1 ; i < sv . qcvm . num_edicts ; i + + )
if ( ! sv . qcvm . edicts [ i ] . free )
2017-09-17 02:12:53 +00:00
j + + ;
2018-05-01 00:35:14 +00:00
print_fn ( " entities:%i/%i \n " , j , sv . qcvm . max_edicts ) ;
2017-09-17 02:12:53 +00:00
print_fn ( " players: %i active (%i max) \n \n " , net_activeconnections , svs . maxclients ) ;
2010-08-02 19:45:16 +00:00
for ( j = 0 , client = svs . clients ; j < svs . maxclients ; j + + , client + + )
2010-02-15 23:26:55 +00:00
{
if ( ! client - > active )
continue ;
2017-09-17 02:12:53 +00:00
if ( client - > netconnection )
seconds = ( int ) ( net_time - NET_QSocketGetTime ( client - > netconnection ) ) ;
else
seconds = 0 ;
2010-02-15 23:26:55 +00:00
minutes = seconds / 60 ;
if ( minutes )
{
seconds - = ( minutes * 60 ) ;
hours = minutes / 60 ;
if ( hours )
minutes - = ( hours * 60 ) ;
}
else
hours = 0 ;
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
print_fn ( " #%-2u %-16.16s %3i %2i:%02i:%02i \n " , j + 1 , client - > name , ( int ) client - > edict - > v . frags , hours , minutes , seconds ) ;
2017-09-17 02:12:53 +00:00
if ( cmd_source = = src_command )
print_fn ( " %s \n " , client - > netconnection ? NET_QSocketGetTrueAddressString ( client - > netconnection ) : " botclient " ) ;
else
print_fn ( " %s \n " , client - > netconnection ? NET_QSocketGetMaskedAddressString ( client - > netconnection ) : " botclient " ) ;
2010-02-15 23:26:55 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = =
Host_God_f
Sets client to godmode
= = = = = = = = = = = = = = = = = =
*/
void Host_God_f ( void )
{
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
2011-12-12 09:50:23 +00:00
if ( pr_global_struct - > deathmatch )
2010-02-15 23:26:55 +00:00
return ;
//johnfitz -- allow user to explicitly set god mode to on or off
switch ( Cmd_Argc ( ) )
{
case 1 :
sv_player - > v . flags = ( int ) sv_player - > v . flags ^ FL_GODMODE ;
if ( ! ( ( int ) sv_player - > v . flags & FL_GODMODE ) )
SV_ClientPrintf ( " godmode OFF \n " ) ;
else
SV_ClientPrintf ( " godmode ON \n " ) ;
break ;
case 2 :
if ( Q_atof ( Cmd_Argv ( 1 ) ) )
{
sv_player - > v . flags = ( int ) sv_player - > v . flags | FL_GODMODE ;
SV_ClientPrintf ( " godmode ON \n " ) ;
}
else
{
sv_player - > v . flags = ( int ) sv_player - > v . flags & ~ FL_GODMODE ;
SV_ClientPrintf ( " godmode OFF \n " ) ;
}
break ;
default :
Con_Printf ( " god [value] : toggle god mode. values: 0 = off, 1 = on \n " ) ;
break ;
}
//johnfitz
}
/*
= = = = = = = = = = = = = = = = = =
Host_Notarget_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Notarget_f ( void )
{
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
2011-12-12 09:50:23 +00:00
if ( pr_global_struct - > deathmatch )
2010-02-15 23:26:55 +00:00
return ;
//johnfitz -- allow user to explicitly set notarget to on or off
switch ( Cmd_Argc ( ) )
{
case 1 :
sv_player - > v . flags = ( int ) sv_player - > v . flags ^ FL_NOTARGET ;
if ( ! ( ( int ) sv_player - > v . flags & FL_NOTARGET ) )
SV_ClientPrintf ( " notarget OFF \n " ) ;
else
SV_ClientPrintf ( " notarget ON \n " ) ;
break ;
case 2 :
if ( Q_atof ( Cmd_Argv ( 1 ) ) )
{
sv_player - > v . flags = ( int ) sv_player - > v . flags | FL_NOTARGET ;
SV_ClientPrintf ( " notarget ON \n " ) ;
}
else
{
sv_player - > v . flags = ( int ) sv_player - > v . flags & ~ FL_NOTARGET ;
SV_ClientPrintf ( " notarget OFF \n " ) ;
}
break ;
default :
Con_Printf ( " notarget [value] : toggle notarget mode. values: 0 = off, 1 = on \n " ) ;
break ;
}
//johnfitz
}
qboolean noclip_anglehack ;
/*
= = = = = = = = = = = = = = = = = =
Host_Noclip_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Noclip_f ( void )
{
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
2011-12-12 09:50:23 +00:00
if ( pr_global_struct - > deathmatch )
2010-02-15 23:26:55 +00:00
return ;
//johnfitz -- allow user to explicitly set noclip to on or off
switch ( Cmd_Argc ( ) )
{
case 1 :
if ( sv_player - > v . movetype ! = MOVETYPE_NOCLIP )
{
noclip_anglehack = true ;
sv_player - > v . movetype = MOVETYPE_NOCLIP ;
SV_ClientPrintf ( " noclip ON \n " ) ;
}
else
{
noclip_anglehack = false ;
sv_player - > v . movetype = MOVETYPE_WALK ;
SV_ClientPrintf ( " noclip OFF \n " ) ;
}
break ;
case 2 :
if ( Q_atof ( Cmd_Argv ( 1 ) ) )
{
noclip_anglehack = true ;
sv_player - > v . movetype = MOVETYPE_NOCLIP ;
SV_ClientPrintf ( " noclip ON \n " ) ;
}
else
{
noclip_anglehack = false ;
sv_player - > v . movetype = MOVETYPE_WALK ;
SV_ClientPrintf ( " noclip OFF \n " ) ;
}
break ;
default :
Con_Printf ( " noclip [value] : toggle noclip mode. values: 0 = off, 1 = on \n " ) ;
break ;
}
//johnfitz
}
2016-06-07 07:08:23 +00:00
/*
= = = = = = = = = = = = = = = = = = = =
Host_SetPos_f
adapted from fteqw , originally by Alex Shadowalker
= = = = = = = = = = = = = = = = = = = =
*/
void Host_SetPos_f ( void )
{
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
if ( pr_global_struct - > deathmatch )
return ;
if ( Cmd_Argc ( ) ! = 7 & & Cmd_Argc ( ) ! = 4 )
{
SV_ClientPrintf ( " usage: \n " ) ;
SV_ClientPrintf ( " setpos <x> <y> <z> \n " ) ;
SV_ClientPrintf ( " setpos <x> <y> <z> <pitch> <yaw> <roll> \n " ) ;
SV_ClientPrintf ( " current values: \n " ) ;
SV_ClientPrintf ( " %i %i %i %i %i %i \n " ,
( int ) sv_player - > v . origin [ 0 ] ,
( int ) sv_player - > v . origin [ 1 ] ,
( int ) sv_player - > v . origin [ 2 ] ,
( int ) sv_player - > v . v_angle [ 0 ] ,
( int ) sv_player - > v . v_angle [ 1 ] ,
( int ) sv_player - > v . v_angle [ 2 ] ) ;
return ;
}
if ( sv_player - > v . movetype ! = MOVETYPE_NOCLIP )
{
noclip_anglehack = true ;
sv_player - > v . movetype = MOVETYPE_NOCLIP ;
SV_ClientPrintf ( " noclip ON \n " ) ;
}
//make sure they're not going to whizz away from it
sv_player - > v . velocity [ 0 ] = 0 ;
sv_player - > v . velocity [ 1 ] = 0 ;
sv_player - > v . velocity [ 2 ] = 0 ;
sv_player - > v . origin [ 0 ] = atof ( Cmd_Argv ( 1 ) ) ;
sv_player - > v . origin [ 1 ] = atof ( Cmd_Argv ( 2 ) ) ;
sv_player - > v . origin [ 2 ] = atof ( Cmd_Argv ( 3 ) ) ;
if ( Cmd_Argc ( ) = = 7 )
{
sv_player - > v . angles [ 0 ] = atof ( Cmd_Argv ( 4 ) ) ;
sv_player - > v . angles [ 1 ] = atof ( Cmd_Argv ( 5 ) ) ;
sv_player - > v . angles [ 2 ] = atof ( Cmd_Argv ( 6 ) ) ;
sv_player - > v . fixangle = 1 ;
}
SV_LinkEdict ( sv_player , false ) ;
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
Host_Fly_f
Sets client to flymode
= = = = = = = = = = = = = = = = = =
*/
void Host_Fly_f ( void )
{
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
2011-12-12 09:50:23 +00:00
if ( pr_global_struct - > deathmatch )
2010-02-15 23:26:55 +00:00
return ;
//johnfitz -- allow user to explicitly set noclip to on or off
switch ( Cmd_Argc ( ) )
{
case 1 :
if ( sv_player - > v . movetype ! = MOVETYPE_FLY )
{
sv_player - > v . movetype = MOVETYPE_FLY ;
SV_ClientPrintf ( " flymode ON \n " ) ;
}
else
{
sv_player - > v . movetype = MOVETYPE_WALK ;
SV_ClientPrintf ( " flymode OFF \n " ) ;
}
break ;
case 2 :
if ( Q_atof ( Cmd_Argv ( 1 ) ) )
{
sv_player - > v . movetype = MOVETYPE_FLY ;
SV_ClientPrintf ( " flymode ON \n " ) ;
}
else
{
sv_player - > v . movetype = MOVETYPE_WALK ;
SV_ClientPrintf ( " flymode OFF \n " ) ;
}
break ;
default :
Con_Printf ( " fly [value] : toggle fly mode. values: 0 = off, 1 = on \n " ) ;
break ;
}
//johnfitz
}
/*
= = = = = = = = = = = = = = = = = =
Host_Ping_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Ping_f ( void )
{
int i , j ;
2010-08-02 19:45:16 +00:00
float total ;
2010-02-15 23:26:55 +00:00
client_t * client ;
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
SV_ClientPrintf ( " Client ping times: \n " ) ;
2010-08-02 19:45:16 +00:00
for ( i = 0 , client = svs . clients ; i < svs . maxclients ; i + + , client + + )
2010-02-15 23:26:55 +00:00
{
2017-09-17 02:12:53 +00:00
if ( ! client - > spawned | | ! client - > netconnection )
2010-02-15 23:26:55 +00:00
continue ;
total = 0 ;
2010-08-02 19:45:16 +00:00
for ( j = 0 ; j < NUM_PING_TIMES ; j + + )
2010-02-15 23:26:55 +00:00
total + = client - > ping_times [ j ] ;
total / = NUM_PING_TIMES ;
SV_ClientPrintf ( " %4i %s \n " , ( int ) ( total * 1000 ) , client - > name ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
SERVER TRANSITIONS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = = = = = =
Host_Map_f
handle a
map < servername >
command from the console . Active clients are kicked off .
= = = = = = = = = = = = = = = = = = = = = =
*/
void Host_Map_f ( void )
{
int i ;
2010-08-30 02:51:21 +00:00
char name [ MAX_QPATH ] , * p ;
2010-02-15 23:26:55 +00:00
2010-02-16 09:47:04 +00:00
if ( Cmd_Argc ( ) < 2 ) //no map name given
{
if ( cls . state = = ca_dedicated )
{
if ( sv . active )
Con_Printf ( " Current map: %s \n " , sv . name ) ;
else
Con_Printf ( " Server not active \n " ) ;
}
else if ( cls . state = = ca_connected )
{
Con_Printf ( " Current map: %s ( %s ) \n " , cl . levelname , cl . mapname ) ;
}
else
{
Con_Printf ( " map <levelname>: start a new server \n " ) ;
}
return ;
}
2010-02-15 23:26:55 +00:00
if ( cmd_source ! = src_command )
return ;
cls . demonum = - 1 ; // stop demo loop in case this fails
CL_Disconnect ( ) ;
Host_ShutdownServer ( false ) ;
key_dest = key_game ; // remove console or menu
2018-05-01 00:35:14 +00:00
if ( cls . state ! = ca_dedicated )
IN_UpdateGrabs ( ) ;
2010-02-15 23:26:55 +00:00
SCR_BeginLoadingPlaque ( ) ;
svs . serverflags = 0 ; // haven't completed an episode yet
2011-12-27 13:15:31 +00:00
q_strlcpy ( name , Cmd_Argv ( 1 ) , sizeof ( name ) ) ;
2013-03-02 12:03:52 +00:00
// remove (any) trailing ".bsp" from mapname -- S.A.
2010-08-30 02:51:21 +00:00
p = strstr ( name , " .bsp " ) ;
if ( p & & p [ 4 ] = = ' \0 ' )
* p = ' \0 ' ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( & sv . qcvm ) ;
2010-02-15 23:26:55 +00:00
SV_SpawnServer ( name ) ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( NULL ) ;
2010-02-15 23:26:55 +00:00
if ( ! sv . active )
return ;
if ( cls . state ! = ca_dedicated )
{
2011-12-27 13:15:31 +00:00
memset ( cls . spawnparms , 0 , MAX_MAPSTRING ) ;
2010-08-02 19:45:16 +00:00
for ( i = 2 ; i < Cmd_Argc ( ) ; i + + )
2010-02-15 23:26:55 +00:00
{
2011-12-27 13:15:31 +00:00
q_strlcat ( cls . spawnparms , Cmd_Argv ( i ) , MAX_MAPSTRING ) ;
q_strlcat ( cls . spawnparms , " " , MAX_MAPSTRING ) ;
2010-02-15 23:26:55 +00:00
}
Cmd_ExecuteString ( " connect local " , src_command ) ;
}
}
2017-06-23 23:22:00 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = =
Host_Randmap_f
Loads a random map from the " maps " list .
= = = = = = = = = = = = = = = = = = = = = =
*/
void Host_Randmap_f ( void )
{
int i , randlevel , numlevels ;
filelist_item_t * level ;
if ( cmd_source ! = src_command )
return ;
for ( level = extralevels , numlevels = 0 ; level ; level = level - > next )
numlevels + + ;
if ( numlevels = = 0 )
{
Con_Printf ( " no maps \n " ) ;
return ;
}
randlevel = ( rand ( ) % numlevels ) ;
for ( level = extralevels , i = 0 ; level ; level = level - > next , i + + )
{
if ( i = = randlevel )
{
2017-07-19 05:40:37 +00:00
Con_Printf ( " Starting map %s... \n " , level - > name ) ;
2017-06-23 23:22:00 +00:00
Cbuf_AddText ( va ( " map %s \n " , level - > name ) ) ;
return ;
}
}
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
Host_Changelevel_f
Goes to a new map , taking all clients along
= = = = = = = = = = = = = = = = = =
*/
void Host_Changelevel_f ( void )
{
char level [ MAX_QPATH ] ;
if ( Cmd_Argc ( ) ! = 2 )
{
Con_Printf ( " changelevel <levelname> : continue game on a new level \n " ) ;
return ;
}
if ( ! sv . active | | cls . demoplayback )
{
Con_Printf ( " Only the server may changelevel \n " ) ;
return ;
}
//johnfitz -- check for client having map before anything else
2011-12-27 10:50:42 +00:00
q_snprintf ( level , sizeof ( level ) , " maps/%s.bsp " , Cmd_Argv ( 1 ) ) ;
2013-03-01 23:55:12 +00:00
if ( ! COM_FileExists ( level , NULL ) )
2010-02-15 23:26:55 +00:00
Host_Error ( " cannot find map %s " , level ) ;
//johnfitz
2010-02-16 15:39:06 +00:00
key_dest = key_game ; // remove console or menu
2018-05-01 00:35:14 +00:00
if ( cls . state ! = ca_dedicated )
IN_UpdateGrabs ( ) ; // -- S.A.
PR_SwitchQCVM ( & sv . qcvm ) ;
2010-02-15 23:26:55 +00:00
SV_SaveSpawnparms ( ) ;
2011-12-27 13:15:31 +00:00
q_strlcpy ( level , Cmd_Argv ( 1 ) , sizeof ( level ) ) ;
2010-02-15 23:26:55 +00:00
SV_SpawnServer ( level ) ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( NULL ) ;
2013-03-02 10:29:26 +00:00
// also issue an error if spawn failed -- O.S.
if ( ! sv . active )
Host_Error ( " cannot run map %s " , level ) ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Host_Restart_f
Restarts the current server for a dead player
= = = = = = = = = = = = = = = = = =
*/
void Host_Restart_f ( void )
{
char mapname [ MAX_QPATH ] ;
2017-09-17 02:12:53 +00:00
if ( cls . demoplayback )
2010-02-15 23:26:55 +00:00
return ;
if ( cmd_source ! = src_command )
return ;
2017-09-17 02:12:53 +00:00
if ( ! sv . active )
{
if ( * sv . name )
Cmd_ExecuteString ( va ( " map \" %s \" \n " , sv . name ) , src_command ) ;
return ;
}
2013-03-02 10:29:26 +00:00
q_strlcpy ( mapname , sv . name , sizeof ( mapname ) ) ; // mapname gets cleared in spawnserver
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( & sv . qcvm ) ;
2010-02-15 23:26:55 +00:00
SV_SpawnServer ( mapname ) ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( NULL ) ;
2013-03-02 10:29:26 +00:00
if ( ! sv . active )
2013-03-02 10:36:28 +00:00
Host_Error ( " cannot restart map %s " , mapname ) ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Host_Reconnect_f
This command causes the client to wait for the signon messages again .
This is sent just before a server changes levels
2017-09-17 02:12:53 +00:00
for compatibility with quakeworld et al , we also allow this as a user - command to reconnect to the last server we tried , but we can only reliably do that when we ' re not already connected
2010-02-15 23:26:55 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
void Host_Reconnect_Con_f ( void )
{
CL_Disconnect_f ( ) ;
cls . demonum = - 1 ; // stop demo loop in case this fails
if ( cls . demoplayback )
{
CL_StopPlayback ( ) ;
CL_Disconnect ( ) ;
}
CL_EstablishConnection ( NULL ) ;
}
void Host_Reconnect_Sv_f ( void )
2010-02-15 23:26:55 +00:00
{
2014-08-25 02:55:25 +00:00
if ( cls . demoplayback ) // cross-map demo playback fix from Baker
return ;
2010-02-15 23:26:55 +00:00
SCR_BeginLoadingPlaque ( ) ;
2017-09-17 02:12:53 +00:00
cl . protocol_dpdownload = false ;
2010-02-15 23:26:55 +00:00
cls . signon = 0 ; // need new connection messages
}
/*
= = = = = = = = = = = = = = = = = = = = =
Host_Connect_f
User command to connect to server
= = = = = = = = = = = = = = = = = = = = =
*/
void Host_Connect_f ( void )
{
char name [ MAX_QPATH ] ;
cls . demonum = - 1 ; // stop demo loop in case this fails
if ( cls . demoplayback )
{
CL_StopPlayback ( ) ;
CL_Disconnect ( ) ;
}
2011-12-27 13:15:31 +00:00
q_strlcpy ( name , Cmd_Argv ( 1 ) , sizeof ( name ) ) ;
2010-02-15 23:26:55 +00:00
CL_EstablishConnection ( name ) ;
2017-09-17 02:12:53 +00:00
Host_Reconnect_Sv_f ( ) ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
LOAD / SAVE GAME
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# define SAVEGAME_VERSION 5
/*
= = = = = = = = = = = = = = =
Host_SavegameComment
Writes a SAVEGAME_COMMENT_LENGTH character comment describing the current
= = = = = = = = = = = = = = =
*/
void Host_SavegameComment ( char * text )
{
int i ;
char kills [ 20 ] ;
2010-08-02 19:45:16 +00:00
for ( i = 0 ; i < SAVEGAME_COMMENT_LENGTH ; i + + )
2010-02-15 23:26:55 +00:00
text [ i ] = ' ' ;
2011-01-10 10:35:40 +00:00
memcpy ( text , cl . levelname , q_min ( strlen ( cl . levelname ) , 22 ) ) ; //johnfitz -- only copy 22 chars.
2010-02-15 23:26:55 +00:00
sprintf ( kills , " kills:%3i/%3i " , cl . stats [ STAT_MONSTERS ] , cl . stats [ STAT_TOTALMONSTERS ] ) ;
memcpy ( text + 22 , kills , strlen ( kills ) ) ;
// convert space to _ to make stdio happy
2010-08-02 19:45:16 +00:00
for ( i = 0 ; i < SAVEGAME_COMMENT_LENGTH ; i + + )
{
2010-02-15 23:26:55 +00:00
if ( text [ i ] = = ' ' )
text [ i ] = ' _ ' ;
2010-08-02 19:45:16 +00:00
}
2010-02-15 23:26:55 +00:00
text [ SAVEGAME_COMMENT_LENGTH ] = ' \0 ' ;
}
/*
= = = = = = = = = = = = = = =
Host_Savegame_f
= = = = = = = = = = = = = = =
*/
void Host_Savegame_f ( void )
{
2011-12-27 08:04:02 +00:00
char name [ MAX_OSPATH ] ;
2010-02-15 23:26:55 +00:00
FILE * f ;
2010-08-02 19:45:16 +00:00
int i ;
2010-02-15 23:26:55 +00:00
char comment [ SAVEGAME_COMMENT_LENGTH + 1 ] ;
if ( cmd_source ! = src_command )
return ;
if ( ! sv . active )
{
Con_Printf ( " Not playing a local game. \n " ) ;
return ;
}
if ( cl . intermission )
{
Con_Printf ( " Can't save in intermission. \n " ) ;
return ;
}
if ( svs . maxclients ! = 1 )
{
Con_Printf ( " Can't save multiplayer games. \n " ) ;
return ;
}
if ( Cmd_Argc ( ) ! = 2 )
{
Con_Printf ( " save <savename> : save a game \n " ) ;
return ;
}
if ( strstr ( Cmd_Argv ( 1 ) , " .. " ) )
{
Con_Printf ( " Relative pathnames are not allowed. \n " ) ;
return ;
}
for ( i = 0 ; i < svs . maxclients ; i + + )
{
if ( svs . clients [ i ] . active & & ( svs . clients [ i ] . edict - > v . health < = 0 ) )
{
Con_Printf ( " Can't savegame with a dead player \n " ) ;
return ;
}
}
2011-12-27 10:50:42 +00:00
q_snprintf ( name , sizeof ( name ) , " %s/%s " , com_gamedir , Cmd_Argv ( 1 ) ) ;
2014-04-26 07:50:54 +00:00
COM_AddExtension ( name , " .sav " , sizeof ( name ) ) ;
2010-02-15 23:26:55 +00:00
Con_Printf ( " Saving game to %s... \n " , name ) ;
f = fopen ( name , " w " ) ;
if ( ! f )
{
Con_Printf ( " ERROR: couldn't open. \n " ) ;
return ;
}
2018-05-08 22:42:36 +00:00
PR_SwitchQCVM ( & sv . qcvm ) ;
2010-02-15 23:26:55 +00:00
fprintf ( f , " %i \n " , SAVEGAME_VERSION ) ;
Host_SavegameComment ( comment ) ;
fprintf ( f , " %s \n " , comment ) ;
2010-08-02 19:45:16 +00:00
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
2010-02-15 23:26:55 +00:00
fprintf ( f , " %f \n " , svs . clients - > spawn_parms [ i ] ) ;
fprintf ( f , " %d \n " , current_skill ) ;
fprintf ( f , " %s \n " , sv . name ) ;
2018-05-01 00:35:14 +00:00
fprintf ( f , " %f \n " , qcvm - > time ) ;
2010-02-15 23:26:55 +00:00
// write the light styles
2017-09-17 02:12:53 +00:00
for ( i = 0 ; i < MAX_LIGHTSTYLES_VANILLA ; i + + )
2010-02-15 23:26:55 +00:00
{
if ( sv . lightstyles [ i ] )
fprintf ( f , " %s \n " , sv . lightstyles [ i ] ) ;
else
fprintf ( f , " m \n " ) ;
}
ED_WriteGlobals ( f ) ;
2018-05-01 00:35:14 +00:00
for ( i = 0 ; i < qcvm - > num_edicts ; i + + )
2010-02-15 23:26:55 +00:00
{
ED_Write ( f , EDICT_NUM ( i ) ) ;
fflush ( f ) ;
}
2017-09-17 02:12:53 +00:00
//add extra info (lightstyles, precaches, etc) in a way that's supposed to be compatible with DP.
//sidenote - this provides extended lightstyles and support for late precaches
//it does NOT protect against spawnfunc precache changes - we would need to include makestatics here too (and optionally baselines, or just recalculate those).
fprintf ( f , " /* \n " ) ;
fprintf ( f , " // QuakeSpasm extended savegame \n " ) ;
for ( i = MAX_LIGHTSTYLES_VANILLA ; i < MAX_LIGHTSTYLES ; i + + )
{
if ( sv . lightstyles [ i ] )
fprintf ( f , " sv.lightstyles %i \" %s \" \n " , i , sv . lightstyles [ i ] ) ;
else
fprintf ( f , " sv.lightstyles %i \" \" \n " , i ) ;
}
for ( i = 1 ; i < MAX_MODELS ; i + + )
{
if ( sv . model_precache [ i ] )
fprintf ( f , " sv.model_precache %i \" %s \" \n " , i , sv . model_precache [ i ] ) ;
}
for ( i = 1 ; i < MAX_SOUNDS ; i + + )
{
if ( sv . sound_precache [ i ] )
fprintf ( f , " sv.sound_precache %i \" %s \" \n " , i , sv . sound_precache [ i ] ) ;
}
for ( i = 1 ; i < MAX_PARTICLETYPES ; i + + )
{
if ( sv . particle_precache [ i ] )
fprintf ( f , " sv.particle_precache %i \" %s \" \n " , i , sv . particle_precache [ i ] ) ;
}
fprintf ( f , " */ \n " ) ;
2010-02-15 23:26:55 +00:00
fclose ( f ) ;
Con_Printf ( " done. \n " ) ;
2018-05-08 22:42:36 +00:00
PR_SwitchQCVM ( NULL ) ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = =
Host_Loadgame_f
= = = = = = = = = = = = = = =
*/
void Host_Loadgame_f ( void )
{
2017-04-16 02:53:06 +00:00
static char * start ;
2010-02-15 23:26:55 +00:00
char name [ MAX_OSPATH ] ;
char mapname [ MAX_QPATH ] ;
float time , tfloat ;
2017-04-16 02:53:06 +00:00
const char * data ;
int i ;
2010-02-15 23:26:55 +00:00
edict_t * ent ;
2010-08-02 19:45:16 +00:00
int entnum ;
int version ;
float spawn_parms [ NUM_SPAWN_PARMS ] ;
2010-02-15 23:26:55 +00:00
if ( cmd_source ! = src_command )
return ;
if ( Cmd_Argc ( ) ! = 2 )
{
Con_Printf ( " load <savename> : load a game \n " ) ;
return ;
}
2017-09-17 02:12:53 +00:00
2017-04-09 20:42:22 +00:00
if ( strstr ( Cmd_Argv ( 1 ) , " .. " ) )
{
Con_Printf ( " Relative pathnames are not allowed. \n " ) ;
return ;
}
2010-02-15 23:26:55 +00:00
cls . demonum = - 1 ; // stop demo loop in case this fails
2011-12-27 10:50:42 +00:00
q_snprintf ( name , sizeof ( name ) , " %s/%s " , com_gamedir , Cmd_Argv ( 1 ) ) ;
2014-04-26 07:50:54 +00:00
COM_AddExtension ( name , " .sav " , sizeof ( name ) ) ;
2010-02-15 23:26:55 +00:00
// we can't call SCR_BeginLoadingPlaque, because too much stack space has
// been used. The menu calls it before stuffing loadgame command
// SCR_BeginLoadingPlaque ();
Con_Printf ( " Loading game from %s... \n " , name ) ;
2017-04-16 02:53:06 +00:00
// avoid leaking if the previous Host_Loadgame_f failed with a Host_Error
if ( start ! = NULL )
free ( start ) ;
2017-05-09 00:01:41 +00:00
start = ( char * ) COM_LoadMallocFile_TextMode_OSPath ( name , NULL ) ;
2017-04-16 02:53:06 +00:00
if ( start = = NULL )
2010-02-15 23:26:55 +00:00
{
Con_Printf ( " ERROR: couldn't open. \n " ) ;
return ;
}
2017-04-16 02:53:06 +00:00
data = start ;
data = COM_ParseIntNewline ( data , & version ) ;
2010-02-15 23:26:55 +00:00
if ( version ! = SAVEGAME_VERSION )
{
2017-04-16 02:53:06 +00:00
free ( start ) ;
start = NULL ;
2010-02-15 23:26:55 +00:00
Con_Printf ( " Savegame is version %i, not %i \n " , version , SAVEGAME_VERSION ) ;
return ;
}
2017-04-16 02:53:06 +00:00
data = COM_ParseStringNewline ( data ) ;
2010-08-02 19:45:16 +00:00
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
2017-04-16 02:53:06 +00:00
data = COM_ParseFloatNewline ( data , & spawn_parms [ i ] ) ;
2010-02-15 23:26:55 +00:00
// this silliness is so we can load 1.06 save files, which have float skill values
2017-04-16 02:53:06 +00:00
data = COM_ParseFloatNewline ( data , & tfloat ) ;
2010-02-15 23:26:55 +00:00
current_skill = ( int ) ( tfloat + 0.1 ) ;
Cvar_SetValue ( " skill " , ( float ) current_skill ) ;
2017-04-16 02:53:06 +00:00
data = COM_ParseStringNewline ( data ) ;
q_strlcpy ( mapname , com_token , sizeof ( mapname ) ) ;
data = COM_ParseFloatNewline ( data , & time ) ;
2010-02-15 23:26:55 +00:00
CL_Disconnect_f ( ) ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( & sv . qcvm ) ;
2010-02-15 23:26:55 +00:00
SV_SpawnServer ( mapname ) ;
if ( ! sv . active )
{
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( NULL ) ;
2017-04-16 02:53:06 +00:00
free ( start ) ;
start = NULL ;
2010-02-15 23:26:55 +00:00
Con_Printf ( " Couldn't load map \n " ) ;
return ;
}
sv . paused = true ; // pause until all clients connect
sv . loadgame = true ;
// load the light styles
2017-09-17 02:12:53 +00:00
for ( i = 0 ; i < MAX_LIGHTSTYLES_VANILLA ; i + + )
2010-02-15 23:26:55 +00:00
{
2017-04-16 02:53:06 +00:00
data = COM_ParseStringNewline ( data ) ;
sv . lightstyles [ i ] = ( const char * ) Hunk_Strdup ( com_token , " lightstyles " ) ;
2010-02-15 23:26:55 +00:00
}
// load the edicts out of the savegame file
entnum = - 1 ; // -1 is the globals
2017-04-16 02:53:06 +00:00
while ( * data )
2010-02-15 23:26:55 +00:00
{
2017-09-17 02:12:53 +00:00
while ( * data = = ' ' | | * data = = ' \r ' | | * data = = ' \n ' )
data + + ;
if ( data [ 0 ] = = ' / ' & & data [ 1 ] = = ' * ' & & ( data [ 2 ] = = ' \r ' | | data [ 2 ] = = ' \n ' ) )
{ //looks like an extended saved game
char * end ;
const char * ext ;
ext = data + 2 ;
while ( ( end = strchr ( ext , ' \n ' ) ) )
{
* end = 0 ;
ext = COM_Parse ( ext ) ;
if ( ! strcmp ( com_token , " sv.lightstyles " ) )
{
int idx ;
ext = COM_Parse ( ext ) ;
idx = atoi ( com_token ) ;
ext = COM_Parse ( ext ) ;
if ( idx > = 0 & & idx < MAX_LIGHTSTYLES )
{
if ( * com_token )
sv . lightstyles [ idx ] = ( const char * ) Hunk_Strdup ( com_token , " lightstyles " ) ;
else
sv . lightstyles [ idx ] = NULL ;
}
}
else if ( ! strcmp ( com_token , " sv.model_precache " ) )
{
int idx ;
ext = COM_Parse ( ext ) ;
idx = atoi ( com_token ) ;
ext = COM_Parse ( ext ) ;
if ( idx > = 1 & & idx < MAX_MODELS )
{
sv . model_precache [ idx ] = ( const char * ) Hunk_Strdup ( com_token , " model_precache " ) ;
sv . models [ idx ] = Mod_ForName ( sv . model_precache [ idx ] , idx = = 1 ) ;
//if (idx == 1)
// sv.worldmodel = sv.models[idx];
}
}
else if ( ! strcmp ( com_token , " sv.sound_precache " ) )
{
int idx ;
ext = COM_Parse ( ext ) ;
idx = atoi ( com_token ) ;
ext = COM_Parse ( ext ) ;
if ( idx > = 1 & & idx < MAX_MODELS )
sv . sound_precache [ idx ] = ( const char * ) Hunk_Strdup ( com_token , " sound_precache " ) ;
}
else if ( ! strcmp ( com_token , " sv.particle_precache " ) )
{
int idx ;
ext = COM_Parse ( ext ) ;
idx = atoi ( com_token ) ;
ext = COM_Parse ( ext ) ;
if ( idx > = 1 & & idx < MAX_PARTICLETYPES )
sv . particle_precache [ idx ] = ( const char * ) Hunk_Strdup ( com_token , " particle_precache " ) ;
}
* end = ' \n ' ;
ext = end + 1 ;
}
}
data = COM_Parse ( data ) ;
2010-02-15 23:26:55 +00:00
if ( ! com_token [ 0 ] )
break ; // end of file
if ( strcmp ( com_token , " { " ) )
2011-12-15 06:31:51 +00:00
{
2010-02-15 23:26:55 +00:00
Sys_Error ( " First token isn't a brace " ) ;
2011-12-15 06:31:51 +00:00
}
2010-02-15 23:26:55 +00:00
if ( entnum = = - 1 )
{ // parse the global vars
2017-04-16 02:53:06 +00:00
data = ED_ParseGlobals ( data ) ;
2010-02-15 23:26:55 +00:00
}
else
{ // parse an edict
ent = EDICT_NUM ( entnum ) ;
2018-05-01 00:35:14 +00:00
if ( entnum < qcvm - > num_edicts ) {
2016-06-25 05:21:22 +00:00
ent - > free = false ;
2018-05-01 00:35:14 +00:00
memset ( & ent - > v , 0 , qcvm - > progs - > entityfields * 4 ) ;
2016-06-24 16:04:25 +00:00
}
else {
2018-05-01 00:35:14 +00:00
memset ( ent , 0 , qcvm - > edict_size ) ;
2016-06-24 16:04:25 +00:00
}
2017-04-16 02:53:06 +00:00
data = ED_ParseEdict ( data , ent ) ;
2010-02-15 23:26:55 +00:00
// link it into the bsp tree
if ( ! ent - > free )
SV_LinkEdict ( ent , false ) ;
}
entnum + + ;
}
2018-05-01 00:35:14 +00:00
qcvm - > num_edicts = entnum ;
qcvm - > time = time ;
2010-02-15 23:26:55 +00:00
2017-04-16 02:53:06 +00:00
free ( start ) ;
start = NULL ;
2010-02-15 23:26:55 +00:00
2010-08-02 19:45:16 +00:00
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
2010-02-15 23:26:55 +00:00
svs . clients - > spawn_parms [ i ] = spawn_parms [ i ] ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( NULL ) ;
2010-02-15 23:26:55 +00:00
if ( cls . state ! = ca_dedicated )
{
CL_EstablishConnection ( " local " ) ;
2017-09-17 02:12:53 +00:00
Host_Reconnect_Sv_f ( ) ;
2010-02-15 23:26:55 +00:00
}
}
//============================================================================
/*
= = = = = = = = = = = = = = = = = = = = = =
Host_Name_f
= = = = = = = = = = = = = = = = = = = = = =
*/
void Host_Name_f ( void )
{
2010-08-29 02:22:55 +00:00
char newName [ 32 ] ;
2010-02-15 23:26:55 +00:00
if ( Cmd_Argc ( ) = = 1 )
{
Con_Printf ( " \" name \" is \" %s \" \n " , cl_name . string ) ;
return ;
}
if ( Cmd_Argc ( ) = = 2 )
2011-12-27 13:15:31 +00:00
q_strlcpy ( newName , Cmd_Argv ( 1 ) , sizeof ( newName ) ) ;
2010-02-15 23:26:55 +00:00
else
2011-12-27 13:15:31 +00:00
q_strlcpy ( newName , Cmd_Args ( ) , sizeof ( newName ) ) ;
2010-08-29 10:22:17 +00:00
newName [ 15 ] = 0 ; // client_t structure actually says name[32].
2010-02-15 23:26:55 +00:00
if ( cmd_source = = src_command )
{
if ( Q_strcmp ( cl_name . string , newName ) = = 0 )
return ;
Cvar_Set ( " _cl_name " , newName ) ;
if ( cls . state = = ca_connected )
Cmd_ForwardToServer ( ) ;
return ;
}
if ( host_client - > name [ 0 ] & & strcmp ( host_client - > name , " unconnected " ) )
2010-08-02 19:45:16 +00:00
{
2010-02-15 23:26:55 +00:00
if ( Q_strcmp ( host_client - > name , newName ) ! = 0 )
Con_Printf ( " %s renamed to %s \n " , host_client - > name , newName ) ;
2010-08-02 19:45:16 +00:00
}
2010-02-15 23:26:55 +00:00
Q_strcpy ( host_client - > name , newName ) ;
64 bit compatibility effort, 4/nn: x86_64 works just fine now, yey!
the QuakeC interpreter used to use string pointer offsets from pr_strings
even when the pointers lead to engine data which is often well out of
32bit range on a 64bit architecture and they lead to crashes. they now
go through the new PR_SetEngineString and PR_GetString functions which
turn any address outside the pr_strings area into an index into a table
of engine string addresses, adding new string addresses to the table as
needed. the engine strings table is allocated with 256 entries at first
(see the PR_STRING_ALLOCSLOTS definition in pr_edict.c) and its size is
incremented by 256 as needed and re-allocated on the zone. managing that
allocation and reallocation is accomplished by the recently added Z_Realloc
function. implementation based on the uhexen2 (hexen2: hammer of thyrion)
engine which, in turn, is loosely based on twilight and quakeforge engines.
pr_strings range check is from tyrquake.
pr_edict.c: added the new PR_SetEngineString, PR_GetString, PR_AllocString
public functions and the new private PR_AllocStringSlots function. made
ED_NewString private to pr_edict.c and reworked it to return an index to a
newly allocated string.
progs.h: added prototypes for the new public PR_SetEngineString, PR_GetString
and PR_AllocString functions.
host_cmd.c, pr_cmds.c, pr_edict.c, pr_exec.c, progs.h, sv_main.c, sv_phys.c:
modifed to use the new PR_SetEngineString and PR_GetString functions.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@38 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-17 15:04:50 +00:00
host_client - > edict - > v . netname = PR_SetEngineString ( host_client - > name ) ;
2010-02-15 23:26:55 +00:00
// send notification to all clients
MSG_WriteByte ( & sv . reliable_datagram , svc_updatename ) ;
MSG_WriteByte ( & sv . reliable_datagram , host_client - svs . clients ) ;
MSG_WriteString ( & sv . reliable_datagram , host_client - > name ) ;
}
void Host_Say ( qboolean teamonly )
{
2010-08-31 11:55:55 +00:00
int j ;
2010-08-31 12:15:38 +00:00
client_t * client ;
client_t * save ;
2010-08-29 02:22:55 +00:00
const char * p ;
2010-08-31 11:55:55 +00:00
char text [ MAXCMDLINE ] , * p2 ;
qboolean quoted ;
2010-02-15 23:26:55 +00:00
qboolean fromServer = false ;
if ( cmd_source = = src_command )
{
2013-03-02 12:03:52 +00:00
if ( cls . state ! = ca_dedicated )
2010-02-15 23:26:55 +00:00
{
Cmd_ForwardToServer ( ) ;
return ;
}
2013-03-02 12:03:52 +00:00
fromServer = true ;
teamonly = false ;
2010-02-15 23:26:55 +00:00
}
if ( Cmd_Argc ( ) < 2 )
return ;
save = host_client ;
p = Cmd_Args ( ) ;
// remove quotes if present
2010-08-31 11:55:55 +00:00
quoted = false ;
2010-08-31 12:15:38 +00:00
if ( * p = = ' \" ' )
2010-02-15 23:26:55 +00:00
{
p + + ;
2010-08-31 11:55:55 +00:00
quoted = true ;
2010-02-15 23:26:55 +00:00
}
// turn on color set 1
if ( ! fromServer )
2010-08-31 11:55:55 +00:00
q_snprintf ( text , sizeof ( text ) , " \001 %s: %s " , save - > name , p ) ;
2010-02-15 23:26:55 +00:00
else
2010-08-31 11:55:55 +00:00
q_snprintf ( text , sizeof ( text ) , " \001 <%s> %s " , hostname . string , p ) ;
2010-02-15 23:26:55 +00:00
2010-08-31 11:55:55 +00:00
// check length & truncate if necessary
2011-12-29 19:06:08 +00:00
j = ( int ) strlen ( text ) ;
if ( j > = ( int ) sizeof ( text ) - 1 )
2010-08-31 11:55:55 +00:00
{
text [ sizeof ( text ) - 2 ] = ' \n ' ;
text [ sizeof ( text ) - 1 ] = ' \0 ' ;
}
else
{
p2 = text + j ;
while ( ( const char * ) p2 > ( const char * ) text & &
( p2 [ - 1 ] = = ' \r ' | | p2 [ - 1 ] = = ' \n ' | | ( p2 [ - 1 ] = = ' \" ' & & quoted ) ) )
{
if ( p2 [ - 1 ] = = ' \" ' & & quoted )
quoted = false ;
p2 [ - 1 ] = ' \0 ' ;
p2 - - ;
}
p2 [ 0 ] = ' \n ' ;
p2 [ 1 ] = ' \0 ' ;
}
2010-02-15 23:26:55 +00:00
for ( j = 0 , client = svs . clients ; j < svs . maxclients ; j + + , client + + )
{
if ( ! client | | ! client - > active | | ! client - > spawned )
continue ;
if ( teamplay . value & & teamonly & & client - > edict - > v . team ! = save - > edict - > v . team )
continue ;
host_client = client ;
SV_ClientPrintf ( " %s " , text ) ;
}
host_client = save ;
2010-08-31 11:55:55 +00:00
if ( cls . state = = ca_dedicated )
Sys_Printf ( " %s " , & text [ 1 ] ) ;
2010-02-15 23:26:55 +00:00
}
void Host_Say_f ( void )
{
Host_Say ( false ) ;
}
void Host_Say_Team_f ( void )
{
Host_Say ( true ) ;
}
void Host_Tell_f ( void )
{
2010-08-31 11:55:55 +00:00
int j ;
2010-08-31 12:15:38 +00:00
client_t * client ;
client_t * save ;
2010-08-29 02:22:55 +00:00
const char * p ;
2010-08-31 12:15:38 +00:00
char text [ MAXCMDLINE ] , * p2 ;
2010-08-31 11:55:55 +00:00
qboolean quoted ;
2010-02-15 23:26:55 +00:00
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
if ( Cmd_Argc ( ) < 3 )
return ;
p = Cmd_Args ( ) ;
// remove quotes if present
2010-08-31 11:55:55 +00:00
quoted = false ;
2010-08-31 12:15:38 +00:00
if ( * p = = ' \" ' )
2010-02-15 23:26:55 +00:00
{
p + + ;
2010-08-31 11:55:55 +00:00
quoted = true ;
2010-02-15 23:26:55 +00:00
}
2010-08-31 11:55:55 +00:00
q_snprintf ( text , sizeof ( text ) , " %s: %s " , host_client - > name , p ) ;
2010-02-15 23:26:55 +00:00
// check length & truncate if necessary
2011-12-29 19:06:08 +00:00
j = ( int ) strlen ( text ) ;
if ( j > = ( int ) sizeof ( text ) - 1 )
2010-08-31 11:55:55 +00:00
{
text [ sizeof ( text ) - 2 ] = ' \n ' ;
text [ sizeof ( text ) - 1 ] = ' \0 ' ;
}
else
{
p2 = text + j ;
while ( ( const char * ) p2 > ( const char * ) text & &
( p2 [ - 1 ] = = ' \r ' | | p2 [ - 1 ] = = ' \n ' | | ( p2 [ - 1 ] = = ' \" ' & & quoted ) ) )
{
if ( p2 [ - 1 ] = = ' \" ' & & quoted )
quoted = false ;
p2 [ - 1 ] = ' \0 ' ;
p2 - - ;
}
p2 [ 0 ] = ' \n ' ;
p2 [ 1 ] = ' \0 ' ;
}
2010-02-15 23:26:55 +00:00
save = host_client ;
for ( j = 0 , client = svs . clients ; j < svs . maxclients ; j + + , client + + )
{
if ( ! client - > active | | ! client - > spawned )
continue ;
2013-09-25 17:01:40 +00:00
if ( q_strcasecmp ( client - > name , Cmd_Argv ( 1 ) ) )
2010-02-15 23:26:55 +00:00
continue ;
host_client = client ;
SV_ClientPrintf ( " %s " , text ) ;
break ;
}
host_client = save ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Color_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Color_f ( void )
{
int top , bottom ;
int playercolor ;
if ( Cmd_Argc ( ) = = 1 )
{
Con_Printf ( " \" color \" is \" %i %i \" \n " , ( ( int ) cl_color . value ) > > 4 , ( ( int ) cl_color . value ) & 0x0f ) ;
Con_Printf ( " color <0-13> [0-13] \n " ) ;
return ;
}
if ( Cmd_Argc ( ) = = 2 )
top = bottom = atoi ( Cmd_Argv ( 1 ) ) ;
else
{
top = atoi ( Cmd_Argv ( 1 ) ) ;
bottom = atoi ( Cmd_Argv ( 2 ) ) ;
}
top & = 15 ;
if ( top > 13 )
top = 13 ;
bottom & = 15 ;
if ( bottom > 13 )
bottom = 13 ;
playercolor = top * 16 + bottom ;
if ( cmd_source = = src_command )
{
Cvar_SetValue ( " _cl_color " , playercolor ) ;
if ( cls . state = = ca_connected )
Cmd_ForwardToServer ( ) ;
return ;
}
host_client - > colors = playercolor ;
host_client - > edict - > v . team = bottom + 1 ;
// send notification to all clients
MSG_WriteByte ( & sv . reliable_datagram , svc_updatecolors ) ;
MSG_WriteByte ( & sv . reliable_datagram , host_client - svs . clients ) ;
MSG_WriteByte ( & sv . reliable_datagram , host_client - > colors ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Kill_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Kill_f ( void )
{
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
if ( sv_player - > v . health < = 0 )
{
SV_ClientPrintf ( " Can't suicide -- allready dead! \n " ) ;
return ;
}
2018-05-01 00:35:14 +00:00
pr_global_struct - > time = qcvm - > time ;
2010-02-15 23:26:55 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( sv_player ) ;
PR_ExecuteProgram ( pr_global_struct - > ClientKill ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Pause_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Pause_f ( void )
{
2014-12-08 19:30:36 +00:00
//ericw -- demo pause support (inspired by MarkV)
2015-05-29 18:33:19 +00:00
if ( cls . demoplayback )
2014-12-08 19:30:36 +00:00
{
cls . demopaused = ! cls . demopaused ;
cl . paused = cls . demopaused ;
return ;
}
2010-02-15 23:26:55 +00:00
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
if ( ! pausable . value )
SV_ClientPrintf ( " Pause not allowed. \n " ) ;
else
{
sv . paused ^ = 1 ;
if ( sv . paused )
{
64 bit compatibility effort, 4/nn: x86_64 works just fine now, yey!
the QuakeC interpreter used to use string pointer offsets from pr_strings
even when the pointers lead to engine data which is often well out of
32bit range on a 64bit architecture and they lead to crashes. they now
go through the new PR_SetEngineString and PR_GetString functions which
turn any address outside the pr_strings area into an index into a table
of engine string addresses, adding new string addresses to the table as
needed. the engine strings table is allocated with 256 entries at first
(see the PR_STRING_ALLOCSLOTS definition in pr_edict.c) and its size is
incremented by 256 as needed and re-allocated on the zone. managing that
allocation and reallocation is accomplished by the recently added Z_Realloc
function. implementation based on the uhexen2 (hexen2: hammer of thyrion)
engine which, in turn, is loosely based on twilight and quakeforge engines.
pr_strings range check is from tyrquake.
pr_edict.c: added the new PR_SetEngineString, PR_GetString, PR_AllocString
public functions and the new private PR_AllocStringSlots function. made
ED_NewString private to pr_edict.c and reworked it to return an index to a
newly allocated string.
progs.h: added prototypes for the new public PR_SetEngineString, PR_GetString
and PR_AllocString functions.
host_cmd.c, pr_cmds.c, pr_edict.c, pr_exec.c, progs.h, sv_main.c, sv_phys.c:
modifed to use the new PR_SetEngineString and PR_GetString functions.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@38 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-17 15:04:50 +00:00
SV_BroadcastPrintf ( " %s paused the game \n " , PR_GetString ( sv_player - > v . netname ) ) ;
2010-02-15 23:26:55 +00:00
}
else
{
64 bit compatibility effort, 4/nn: x86_64 works just fine now, yey!
the QuakeC interpreter used to use string pointer offsets from pr_strings
even when the pointers lead to engine data which is often well out of
32bit range on a 64bit architecture and they lead to crashes. they now
go through the new PR_SetEngineString and PR_GetString functions which
turn any address outside the pr_strings area into an index into a table
of engine string addresses, adding new string addresses to the table as
needed. the engine strings table is allocated with 256 entries at first
(see the PR_STRING_ALLOCSLOTS definition in pr_edict.c) and its size is
incremented by 256 as needed and re-allocated on the zone. managing that
allocation and reallocation is accomplished by the recently added Z_Realloc
function. implementation based on the uhexen2 (hexen2: hammer of thyrion)
engine which, in turn, is loosely based on twilight and quakeforge engines.
pr_strings range check is from tyrquake.
pr_edict.c: added the new PR_SetEngineString, PR_GetString, PR_AllocString
public functions and the new private PR_AllocStringSlots function. made
ED_NewString private to pr_edict.c and reworked it to return an index to a
newly allocated string.
progs.h: added prototypes for the new public PR_SetEngineString, PR_GetString
and PR_AllocString functions.
host_cmd.c, pr_cmds.c, pr_edict.c, pr_exec.c, progs.h, sv_main.c, sv_phys.c:
modifed to use the new PR_SetEngineString and PR_GetString functions.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@38 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-17 15:04:50 +00:00
SV_BroadcastPrintf ( " %s unpaused the game \n " , PR_GetString ( sv_player - > v . netname ) ) ;
2010-02-15 23:26:55 +00:00
}
// send notification to all clients
MSG_WriteByte ( & sv . reliable_datagram , svc_setpause ) ;
MSG_WriteByte ( & sv . reliable_datagram , sv . paused ) ;
}
}
//===========================================================================
/*
= = = = = = = = = = = = = = = = = =
Host_PreSpawn_f
= = = = = = = = = = = = = = = = = =
*/
void Host_PreSpawn_f ( void )
{
if ( cmd_source = = src_command )
{
Con_Printf ( " prespawn is not valid from the console \n " ) ;
return ;
}
if ( host_client - > spawned )
{
Con_Printf ( " prespawn not valid -- allready spawned \n " ) ;
return ;
}
2017-09-17 02:12:53 +00:00
//will start splurging out prespawn data
host_client - > sendsignon = 2 ;
host_client - > signonidx = 0 ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Host_Spawn_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Spawn_f ( void )
{
int i ;
client_t * client ;
edict_t * ent ;
if ( cmd_source = = src_command )
{
Con_Printf ( " spawn is not valid from the console \n " ) ;
return ;
}
if ( host_client - > spawned )
{
Con_Printf ( " Spawn not valid -- allready spawned \n " ) ;
return ;
}
2017-09-17 02:12:53 +00:00
host_client - > knowntoqc = true ;
2010-02-15 23:26:55 +00:00
// run the entrance script
if ( sv . loadgame )
{ // loaded games are fully inited allready
// if this is the last client to be connected, unpause
sv . paused = false ;
}
else
{
// set up the edict
ent = host_client - > edict ;
2018-05-01 00:35:14 +00:00
memset ( & ent - > v , 0 , qcvm - > progs - > entityfields * 4 ) ;
2010-02-15 23:26:55 +00:00
ent - > v . colormap = NUM_FOR_EDICT ( ent ) ;
ent - > v . team = ( host_client - > colors & 15 ) + 1 ;
64 bit compatibility effort, 4/nn: x86_64 works just fine now, yey!
the QuakeC interpreter used to use string pointer offsets from pr_strings
even when the pointers lead to engine data which is often well out of
32bit range on a 64bit architecture and they lead to crashes. they now
go through the new PR_SetEngineString and PR_GetString functions which
turn any address outside the pr_strings area into an index into a table
of engine string addresses, adding new string addresses to the table as
needed. the engine strings table is allocated with 256 entries at first
(see the PR_STRING_ALLOCSLOTS definition in pr_edict.c) and its size is
incremented by 256 as needed and re-allocated on the zone. managing that
allocation and reallocation is accomplished by the recently added Z_Realloc
function. implementation based on the uhexen2 (hexen2: hammer of thyrion)
engine which, in turn, is loosely based on twilight and quakeforge engines.
pr_strings range check is from tyrquake.
pr_edict.c: added the new PR_SetEngineString, PR_GetString, PR_AllocString
public functions and the new private PR_AllocStringSlots function. made
ED_NewString private to pr_edict.c and reworked it to return an index to a
newly allocated string.
progs.h: added prototypes for the new public PR_SetEngineString, PR_GetString
and PR_AllocString functions.
host_cmd.c, pr_cmds.c, pr_edict.c, pr_exec.c, progs.h, sv_main.c, sv_phys.c:
modifed to use the new PR_SetEngineString and PR_GetString functions.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@38 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-17 15:04:50 +00:00
ent - > v . netname = PR_SetEngineString ( host_client - > name ) ;
2010-02-15 23:26:55 +00:00
// copy spawn parms out of the client_t
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
( & pr_global_struct - > parm1 ) [ i ] = host_client - > spawn_parms [ i ] ;
// call the spawn function
2018-05-01 00:35:14 +00:00
pr_global_struct - > time = qcvm - > time ;
2010-02-15 23:26:55 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( sv_player ) ;
PR_ExecuteProgram ( pr_global_struct - > ClientConnect ) ;
2018-05-01 00:35:14 +00:00
if ( ( Sys_DoubleTime ( ) - NET_QSocketGetTime ( host_client - > netconnection ) ) < = qcvm - > time )
2010-02-15 23:26:55 +00:00
Sys_Printf ( " %s entered the game \n " , host_client - > name ) ;
PR_ExecuteProgram ( pr_global_struct - > PutClientInServer ) ;
}
// send all current names, colors, and frag counts
SZ_Clear ( & host_client - > message ) ;
// send time of update
MSG_WriteByte ( & host_client - > message , svc_time ) ;
2018-05-01 00:35:14 +00:00
MSG_WriteFloat ( & host_client - > message , qcvm - > time ) ;
2017-09-17 02:12:53 +00:00
if ( host_client - > protocol_pext2 & PEXT2_PREDINFO )
MSG_WriteShort ( & host_client - > message , ( host_client - > lastmovemessage & 0xffff ) ) ;
2010-02-15 23:26:55 +00:00
2010-08-02 19:45:16 +00:00
for ( i = 0 , client = svs . clients ; i < svs . maxclients ; i + + , client + + )
2010-02-15 23:26:55 +00:00
{
2017-09-17 02:12:53 +00:00
if ( ! client - > knowntoqc )
continue ;
2010-02-15 23:26:55 +00:00
MSG_WriteByte ( & host_client - > message , svc_updatename ) ;
MSG_WriteByte ( & host_client - > message , i ) ;
MSG_WriteString ( & host_client - > message , client - > name ) ;
MSG_WriteByte ( & host_client - > message , svc_updatefrags ) ;
MSG_WriteByte ( & host_client - > message , i ) ;
MSG_WriteShort ( & host_client - > message , client - > old_frags ) ;
MSG_WriteByte ( & host_client - > message , svc_updatecolors ) ;
MSG_WriteByte ( & host_client - > message , i ) ;
MSG_WriteByte ( & host_client - > message , client - > colors ) ;
}
// send all current light styles
2010-08-02 19:45:16 +00:00
for ( i = 0 ; i < MAX_LIGHTSTYLES ; i + + )
2010-02-15 23:26:55 +00:00
{
2017-09-17 02:12:53 +00:00
//CL_ClearState should have cleared all lightstyles, so don't send irrelevant ones
if ( sv . lightstyles [ i ] )
{
MSG_WriteByte ( & host_client - > message , svc_lightstyle ) ;
MSG_WriteByte ( & host_client - > message , ( char ) i ) ;
MSG_WriteString ( & host_client - > message , sv . lightstyles [ i ] ) ;
}
2010-02-15 23:26:55 +00:00
}
//
// send some stats
//
MSG_WriteByte ( & host_client - > message , svc_updatestat ) ;
MSG_WriteByte ( & host_client - > message , STAT_TOTALSECRETS ) ;
MSG_WriteLong ( & host_client - > message , pr_global_struct - > total_secrets ) ;
MSG_WriteByte ( & host_client - > message , svc_updatestat ) ;
MSG_WriteByte ( & host_client - > message , STAT_TOTALMONSTERS ) ;
MSG_WriteLong ( & host_client - > message , pr_global_struct - > total_monsters ) ;
MSG_WriteByte ( & host_client - > message , svc_updatestat ) ;
MSG_WriteByte ( & host_client - > message , STAT_SECRETS ) ;
MSG_WriteLong ( & host_client - > message , pr_global_struct - > found_secrets ) ;
MSG_WriteByte ( & host_client - > message , svc_updatestat ) ;
MSG_WriteByte ( & host_client - > message , STAT_MONSTERS ) ;
MSG_WriteLong ( & host_client - > message , pr_global_struct - > killed_monsters ) ;
//
// send a fixangle
// Never send a roll angle, because savegames can catch the server
// in a state where it is expecting the client to correct the angle
// and it won't happen if the game was just loaded, so you wind up
// with a permanent head tilt
ent = EDICT_NUM ( 1 + ( host_client - svs . clients ) ) ;
MSG_WriteByte ( & host_client - > message , svc_setangle ) ;
2010-08-02 19:45:16 +00:00
for ( i = 0 ; i < 2 ; i + + )
2016-06-24 06:15:41 +00:00
MSG_WriteAngle ( & host_client - > message , ent - > v . angles [ i ] , sv . protocolflags ) ;
MSG_WriteAngle ( & host_client - > message , 0 , sv . protocolflags ) ;
2010-02-15 23:26:55 +00:00
2017-09-17 02:12:53 +00:00
if ( ! ( host_client - > protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) )
SV_WriteClientdataToMessage ( host_client , & host_client - > message ) ;
2010-02-15 23:26:55 +00:00
MSG_WriteByte ( & host_client - > message , svc_signonnum ) ;
MSG_WriteByte ( & host_client - > message , 3 ) ;
host_client - > sendsignon = true ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Begin_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Begin_f ( void )
{
if ( cmd_source = = src_command )
{
Con_Printf ( " begin is not valid from the console \n " ) ;
return ;
}
host_client - > spawned = true ;
}
//===========================================================================
/*
= = = = = = = = = = = = = = = = = =
Host_Kick_f
Kicks a user off of the server
= = = = = = = = = = = = = = = = = =
*/
void Host_Kick_f ( void )
{
2010-08-29 02:22:55 +00:00
const char * who ;
const char * message = NULL ;
2010-02-15 23:26:55 +00:00
client_t * save ;
2010-08-02 19:45:16 +00:00
int i ;
2010-02-15 23:26:55 +00:00
qboolean byNumber = false ;
if ( cmd_source = = src_command )
{
if ( ! sv . active )
{
Cmd_ForwardToServer ( ) ;
return ;
}
}
2011-12-12 09:50:23 +00:00
else if ( pr_global_struct - > deathmatch )
2010-02-15 23:26:55 +00:00
return ;
save = host_client ;
if ( Cmd_Argc ( ) > 2 & & Q_strcmp ( Cmd_Argv ( 1 ) , " # " ) = = 0 )
{
i = Q_atof ( Cmd_Argv ( 2 ) ) - 1 ;
if ( i < 0 | | i > = svs . maxclients )
return ;
if ( ! svs . clients [ i ] . active )
return ;
host_client = & svs . clients [ i ] ;
byNumber = true ;
}
else
{
for ( i = 0 , host_client = svs . clients ; i < svs . maxclients ; i + + , host_client + + )
{
if ( ! host_client - > active )
continue ;
2013-09-25 17:01:40 +00:00
if ( q_strcasecmp ( host_client - > name , Cmd_Argv ( 1 ) ) = = 0 )
2010-02-15 23:26:55 +00:00
break ;
}
}
if ( i < svs . maxclients )
{
if ( cmd_source = = src_command )
if ( cls . state = = ca_dedicated )
who = " Console " ;
else
who = cl_name . string ;
else
who = save - > name ;
// can't kick yourself!
if ( host_client = = save )
return ;
if ( Cmd_Argc ( ) > 2 )
{
message = COM_Parse ( Cmd_Args ( ) ) ;
if ( byNumber )
{
2013-03-02 12:03:52 +00:00
message + + ; // skip the #
while ( * message = = ' ' ) // skip white space
2010-02-15 23:26:55 +00:00
message + + ;
2013-03-02 12:03:52 +00:00
message + = strlen ( Cmd_Argv ( 2 ) ) ; // skip the number
2010-02-15 23:26:55 +00:00
}
while ( * message & & * message = = ' ' )
message + + ;
}
if ( message )
SV_ClientPrintf ( " Kicked by %s: %s \n " , who , message ) ;
else
SV_ClientPrintf ( " Kicked by %s \n " , who ) ;
SV_DropClient ( false ) ;
}
host_client = save ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
DEBUGGING TOOLS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
Host_Give_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Give_f ( void )
{
2010-08-29 02:22:55 +00:00
const char * t ;
2010-08-02 19:45:16 +00:00
int v ;
2010-02-15 23:26:55 +00:00
eval_t * val ;
if ( cmd_source = = src_command )
{
Cmd_ForwardToServer ( ) ;
return ;
}
2011-12-12 09:50:23 +00:00
if ( pr_global_struct - > deathmatch )
2010-02-15 23:26:55 +00:00
return ;
t = Cmd_Argv ( 1 ) ;
v = atoi ( Cmd_Argv ( 2 ) ) ;
switch ( t [ 0 ] )
{
2010-08-02 19:45:16 +00:00
case ' 0 ' :
case ' 1 ' :
case ' 2 ' :
case ' 3 ' :
case ' 4 ' :
case ' 5 ' :
case ' 6 ' :
case ' 7 ' :
case ' 8 ' :
case ' 9 ' :
// MED 01/04/97 added hipnotic give stuff
if ( hipnotic )
{
2017-09-17 02:12:53 +00:00
if ( t [ 0 ] = = ' 6 ' )
{
if ( t [ 1 ] = = ' a ' )
sv_player - > v . items = ( int ) sv_player - > v . items | HIT_PROXIMITY_GUN ;
else
sv_player - > v . items = ( int ) sv_player - > v . items | IT_GRENADE_LAUNCHER ;
}
else if ( t [ 0 ] = = ' 9 ' )
sv_player - > v . items = ( int ) sv_player - > v . items | HIT_LASER_CANNON ;
else if ( t [ 0 ] = = ' 0 ' )
sv_player - > v . items = ( int ) sv_player - > v . items | HIT_MJOLNIR ;
else if ( t [ 0 ] > = ' 2 ' )
sv_player - > v . items = ( int ) sv_player - > v . items | ( IT_SHOTGUN < < ( t [ 0 ] - ' 2 ' ) ) ;
2010-08-02 19:45:16 +00:00
}
else
{
2017-09-17 02:12:53 +00:00
if ( t [ 0 ] > = ' 2 ' )
sv_player - > v . items = ( int ) sv_player - > v . items | ( IT_SHOTGUN < < ( t [ 0 ] - ' 2 ' ) ) ;
2010-08-02 19:45:16 +00:00
}
2010-02-15 23:26:55 +00:00
break ;
2010-08-02 19:45:16 +00:00
case ' s ' :
2010-02-15 23:26:55 +00:00
if ( rogue )
{
2017-09-17 02:12:53 +00:00
val = GetEdictFieldValue ( sv_player , ED_FindFieldOffset ( " ammo_shells1 " ) ) ;
if ( val )
val - > _float = v ;
2010-02-15 23:26:55 +00:00
}
2010-08-02 19:45:16 +00:00
sv_player - > v . ammo_shells = v ;
break ;
2010-02-15 23:26:55 +00:00
2010-08-02 19:45:16 +00:00
case ' n ' :
2010-02-15 23:26:55 +00:00
if ( rogue )
{
2017-09-17 02:12:53 +00:00
val = GetEdictFieldValue ( sv_player , ED_FindFieldOffset ( " ammo_nails1 " ) ) ;
if ( val )
{
val - > _float = v ;
if ( sv_player - > v . weapon < = IT_LIGHTNING )
sv_player - > v . ammo_nails = v ;
}
2010-02-15 23:26:55 +00:00
}
else
{
2017-09-17 02:12:53 +00:00
sv_player - > v . ammo_nails = v ;
2010-02-15 23:26:55 +00:00
}
2010-08-02 19:45:16 +00:00
break ;
case ' l ' :
2010-02-15 23:26:55 +00:00
if ( rogue )
{
2017-09-17 02:12:53 +00:00
val = GetEdictFieldValue ( sv_player , ED_FindFieldOffset ( " ammo_lava_nails " ) ) ;
if ( val )
{
val - > _float = v ;
if ( sv_player - > v . weapon > IT_LIGHTNING )
sv_player - > v . ammo_nails = v ;
}
2010-02-15 23:26:55 +00:00
}
2010-08-02 19:45:16 +00:00
break ;
case ' r ' :
2010-02-15 23:26:55 +00:00
if ( rogue )
{
2017-09-17 02:12:53 +00:00
val = GetEdictFieldValue ( sv_player , ED_FindFieldOffset ( " ammo_rockets1 " ) ) ;
if ( val )
{
val - > _float = v ;
if ( sv_player - > v . weapon < = IT_LIGHTNING )
sv_player - > v . ammo_rockets = v ;
}
2010-02-15 23:26:55 +00:00
}
else
{
2017-09-17 02:12:53 +00:00
sv_player - > v . ammo_rockets = v ;
2010-02-15 23:26:55 +00:00
}
2010-08-02 19:45:16 +00:00
break ;
case ' m ' :
2010-02-15 23:26:55 +00:00
if ( rogue )
{
2017-09-17 02:12:53 +00:00
val = GetEdictFieldValue ( sv_player , ED_FindFieldOffset ( " ammo_multi_rockets " ) ) ;
if ( val )
{
val - > _float = v ;
if ( sv_player - > v . weapon > IT_LIGHTNING )
sv_player - > v . ammo_rockets = v ;
}
2010-02-15 23:26:55 +00:00
}
2010-08-02 19:45:16 +00:00
break ;
case ' h ' :
sv_player - > v . health = v ;
break ;
case ' c ' :
2010-02-15 23:26:55 +00:00
if ( rogue )
{
2017-09-17 02:12:53 +00:00
val = GetEdictFieldValue ( sv_player , ED_FindFieldOffset ( " ammo_cells1 " ) ) ;
if ( val )
{
val - > _float = v ;
if ( sv_player - > v . weapon < = IT_LIGHTNING )
sv_player - > v . ammo_cells = v ;
}
2010-02-15 23:26:55 +00:00
}
else
{
2017-09-17 02:12:53 +00:00
sv_player - > v . ammo_cells = v ;
2010-02-15 23:26:55 +00:00
}
2010-08-02 19:45:16 +00:00
break ;
case ' p ' :
2010-02-15 23:26:55 +00:00
if ( rogue )
{
2017-09-17 02:12:53 +00:00
val = GetEdictFieldValue ( sv_player , ED_FindFieldOffset ( " ammo_plasma " ) ) ;
if ( val )
{
val - > _float = v ;
if ( sv_player - > v . weapon > IT_LIGHTNING )
sv_player - > v . ammo_cells = v ;
}
2010-02-15 23:26:55 +00:00
}
2010-08-02 19:45:16 +00:00
break ;
2010-02-15 23:26:55 +00:00
//johnfitz -- give armour
2010-08-02 19:45:16 +00:00
case ' a ' :
2010-02-15 23:26:55 +00:00
if ( v > 150 )
{
2017-09-17 02:12:53 +00:00
sv_player - > v . armortype = 0.8 ;
sv_player - > v . armorvalue = v ;
sv_player - > v . items = sv_player - > v . items -
2010-08-02 19:45:16 +00:00
( ( int ) ( sv_player - > v . items ) & ( int ) ( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3 ) ) +
IT_ARMOR3 ;
2010-02-15 23:26:55 +00:00
}
else if ( v > 100 )
{
2017-09-17 02:12:53 +00:00
sv_player - > v . armortype = 0.6 ;
sv_player - > v . armorvalue = v ;
sv_player - > v . items = sv_player - > v . items -
2010-08-02 19:45:16 +00:00
( ( int ) ( sv_player - > v . items ) & ( int ) ( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3 ) ) +
IT_ARMOR2 ;
2010-02-15 23:26:55 +00:00
}
else if ( v > = 0 )
{
2017-09-17 02:12:53 +00:00
sv_player - > v . armortype = 0.3 ;
sv_player - > v . armorvalue = v ;
sv_player - > v . items = sv_player - > v . items -
2010-08-02 19:45:16 +00:00
( ( int ) ( sv_player - > v . items ) & ( int ) ( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3 ) ) +
IT_ARMOR1 ;
2010-02-15 23:26:55 +00:00
}
break ;
2010-08-02 19:45:16 +00:00
//johnfitz
}
2010-02-15 23:26:55 +00:00
//johnfitz -- update currentammo to match new ammo (so statusbar updates correctly)
switch ( ( int ) ( sv_player - > v . weapon ) )
{
case IT_SHOTGUN :
case IT_SUPER_SHOTGUN :
sv_player - > v . currentammo = sv_player - > v . ammo_shells ;
break ;
case IT_NAILGUN :
case IT_SUPER_NAILGUN :
case RIT_LAVA_SUPER_NAILGUN :
sv_player - > v . currentammo = sv_player - > v . ammo_nails ;
break ;
case IT_GRENADE_LAUNCHER :
case IT_ROCKET_LAUNCHER :
case RIT_MULTI_GRENADE :
case RIT_MULTI_ROCKET :
sv_player - > v . currentammo = sv_player - > v . ammo_rockets ;
break ;
case IT_LIGHTNING :
case HIT_LASER_CANNON :
case HIT_MJOLNIR :
sv_player - > v . currentammo = sv_player - > v . ammo_cells ;
break ;
case RIT_LAVA_NAILGUN : //same as IT_AXE
if ( rogue )
sv_player - > v . currentammo = sv_player - > v . ammo_nails ;
break ;
case RIT_PLASMA_GUN : //same as HIT_PROXIMITY_GUN
if ( rogue )
sv_player - > v . currentammo = sv_player - > v . ammo_cells ;
if ( hipnotic )
sv_player - > v . currentammo = sv_player - > v . ammo_rockets ;
break ;
}
//johnfitz
}
edict_t * FindViewthing ( void )
{
int i ;
edict_t * e ;
2018-05-01 00:35:14 +00:00
for ( i = 0 ; i < qcvm - > num_edicts ; i + + )
2010-02-15 23:26:55 +00:00
{
e = EDICT_NUM ( i ) ;
64 bit compatibility effort, 4/nn: x86_64 works just fine now, yey!
the QuakeC interpreter used to use string pointer offsets from pr_strings
even when the pointers lead to engine data which is often well out of
32bit range on a 64bit architecture and they lead to crashes. they now
go through the new PR_SetEngineString and PR_GetString functions which
turn any address outside the pr_strings area into an index into a table
of engine string addresses, adding new string addresses to the table as
needed. the engine strings table is allocated with 256 entries at first
(see the PR_STRING_ALLOCSLOTS definition in pr_edict.c) and its size is
incremented by 256 as needed and re-allocated on the zone. managing that
allocation and reallocation is accomplished by the recently added Z_Realloc
function. implementation based on the uhexen2 (hexen2: hammer of thyrion)
engine which, in turn, is loosely based on twilight and quakeforge engines.
pr_strings range check is from tyrquake.
pr_edict.c: added the new PR_SetEngineString, PR_GetString, PR_AllocString
public functions and the new private PR_AllocStringSlots function. made
ED_NewString private to pr_edict.c and reworked it to return an index to a
newly allocated string.
progs.h: added prototypes for the new public PR_SetEngineString, PR_GetString
and PR_AllocString functions.
host_cmd.c, pr_cmds.c, pr_edict.c, pr_exec.c, progs.h, sv_main.c, sv_phys.c:
modifed to use the new PR_SetEngineString and PR_GetString functions.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@38 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-17 15:04:50 +00:00
if ( ! strcmp ( PR_GetString ( e - > v . classname ) , " viewthing " ) )
2010-02-15 23:26:55 +00:00
return e ;
}
Con_Printf ( " No viewthing on map \n " ) ;
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Viewmodel_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Viewmodel_f ( void )
{
edict_t * e ;
2012-05-30 08:56:06 +00:00
qmodel_t * m ;
2010-02-15 23:26:55 +00:00
e = FindViewthing ( ) ;
if ( ! e )
return ;
m = Mod_ForName ( Cmd_Argv ( 1 ) , false ) ;
if ( ! m )
{
Con_Printf ( " Can't load %s \n " , Cmd_Argv ( 1 ) ) ;
return ;
}
e - > v . frame = 0 ;
cl . model_precache [ ( int ) e - > v . modelindex ] = m ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Viewframe_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Viewframe_f ( void )
{
edict_t * e ;
int f ;
2012-05-30 08:56:06 +00:00
qmodel_t * m ;
2010-02-15 23:26:55 +00:00
e = FindViewthing ( ) ;
if ( ! e )
return ;
m = cl . model_precache [ ( int ) e - > v . modelindex ] ;
f = atoi ( Cmd_Argv ( 1 ) ) ;
if ( f > = m - > numframes )
2010-08-02 19:45:16 +00:00
f = m - > numframes - 1 ;
2010-02-15 23:26:55 +00:00
e - > v . frame = f ;
}
2012-05-30 08:56:06 +00:00
void PrintFrameName ( qmodel_t * m , int frame )
2010-02-15 23:26:55 +00:00
{
aliashdr_t * hdr ;
maliasframedesc_t * pframedesc ;
hdr = ( aliashdr_t * ) Mod_Extradata ( m ) ;
if ( ! hdr )
return ;
pframedesc = & hdr - > frames [ frame ] ;
Con_Printf ( " frame %i: %s \n " , frame , pframedesc - > name ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Viewnext_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Viewnext_f ( void )
{
edict_t * e ;
2012-05-30 08:56:06 +00:00
qmodel_t * m ;
2010-02-15 23:26:55 +00:00
e = FindViewthing ( ) ;
if ( ! e )
return ;
m = cl . model_precache [ ( int ) e - > v . modelindex ] ;
e - > v . frame = e - > v . frame + 1 ;
if ( e - > v . frame > = m - > numframes )
e - > v . frame = m - > numframes - 1 ;
PrintFrameName ( m , e - > v . frame ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Viewprev_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Viewprev_f ( void )
{
edict_t * e ;
2012-05-30 08:56:06 +00:00
qmodel_t * m ;
2010-02-15 23:26:55 +00:00
e = FindViewthing ( ) ;
if ( ! e )
return ;
m = cl . model_precache [ ( int ) e - > v . modelindex ] ;
e - > v . frame = e - > v . frame - 1 ;
if ( e - > v . frame < 0 )
e - > v . frame = 0 ;
PrintFrameName ( m , e - > v . frame ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
DEMO LOOP CONTROL
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
Host_Startdemos_f
= = = = = = = = = = = = = = = = = =
*/
void Host_Startdemos_f ( void )
{
int i , c ;
if ( cls . state = = ca_dedicated )
return ;
c = Cmd_Argc ( ) - 1 ;
if ( c > MAX_DEMOS )
{
Con_Printf ( " Max %i demos in demoloop \n " , MAX_DEMOS ) ;
c = MAX_DEMOS ;
}
Con_Printf ( " %i demo(s) in loop \n " , c ) ;
2010-08-02 19:45:16 +00:00
for ( i = 1 ; i < c + 1 ; i + + )
2011-12-27 13:15:31 +00:00
q_strlcpy ( cls . demos [ i - 1 ] , Cmd_Argv ( i ) , sizeof ( cls . demos [ 0 ] ) ) ;
2010-02-15 23:26:55 +00:00
if ( ! sv . active & & cls . demonum ! = - 1 & & ! cls . demoplayback )
{
cls . demonum = 0 ;
2010-02-19 13:32:21 +00:00
if ( ! fitzmode )
{ /* QuakeSpasm customization: */
/* go straight to menu, no CL_NextDemo */
2014-12-08 19:30:30 +00:00
cls . demonum = - 1 ;
2010-04-28 06:42:09 +00:00
Cbuf_InsertText ( " menu_main \n " ) ;
2010-02-19 13:32:21 +00:00
return ;
}
2010-02-15 23:26:55 +00:00
CL_NextDemo ( ) ;
}
else
2010-02-19 13:32:21 +00:00
{
2010-02-15 23:26:55 +00:00
cls . demonum = - 1 ;
2010-02-19 13:32:21 +00:00
}
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Host_Demos_f
Return to looping demos
= = = = = = = = = = = = = = = = = =
*/
void Host_Demos_f ( void )
{
if ( cls . state = = ca_dedicated )
return ;
if ( cls . demonum = = - 1 )
cls . demonum = 1 ;
CL_Disconnect_f ( ) ;
CL_NextDemo ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Host_Stopdemo_f
Return to looping demos
= = = = = = = = = = = = = = = = = =
*/
void Host_Stopdemo_f ( void )
{
if ( cls . state = = ca_dedicated )
return ;
if ( ! cls . demoplayback )
return ;
CL_StopPlayback ( ) ;
CL_Disconnect ( ) ;
}
2017-09-17 02:12:53 +00:00
//=============================================================================
//download stuff
static void Host_Download_f ( void )
{
const char * fname = Cmd_Argv ( 1 ) ;
int fsize ;
if ( cmd_source = = src_command )
{
//FIXME: add some sort of queuing thing
// if (cls.state == ca_connected)
// Cmd_ForwardToServer ();
return ;
}
else if ( cmd_source = = src_client )
{
if ( host_client - > download . file )
{ //abort the current download if the previous didn't terminate properly.
SV_ClientPrintf ( " cancelling previous download \n " ) ;
MSG_WriteByte ( & host_client - > message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > message , " \n stopdownload \n " ) ;
fclose ( host_client - > download . file ) ;
host_client - > download . file = NULL ;
}
host_client - > download . size = 0 ;
host_client - > download . started = false ;
host_client - > download . sendpos = 0 ;
host_client - > download . ackpos = 0 ;
fsize = - 1 ;
if ( ! COM_DownloadNameOkay ( fname ) )
SV_ClientPrintf ( " refusing download of %s - restricted filename \n " , fname ) ;
else
{
fsize = COM_FOpenFile ( fname , & host_client - > download . file , NULL ) ;
if ( ! host_client - > download . file )
SV_ClientPrintf ( " server does not have file %s \n " , fname ) ;
else if ( file_from_pak )
{
SV_ClientPrintf ( " refusing download of %s from inside pak \n " , fname ) ;
fclose ( host_client - > download . file ) ;
host_client - > download . file = NULL ;
}
else if ( fsize < 0 | | fsize > 50 * 1024 * 1024 )
{
SV_ClientPrintf ( " refusing download of large file %s \n " , fname ) ;
fclose ( host_client - > download . file ) ;
host_client - > download . file = NULL ;
}
}
host_client - > download . size = ( unsigned int ) fsize ;
if ( host_client - > download . file )
{
host_client - > download . startpos = ftell ( host_client - > download . file ) ;
Con_Printf ( " downloading %s to %s \n " , fname , host_client - > name ) ;
MSG_WriteByte ( & host_client - > message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > message , va ( " \n cl_downloadbegin %u \" %s \" \n " , host_client - > download . size , fname ) ) ;
q_strlcpy ( host_client - > download . name , fname , sizeof ( host_client - > download . name ) ) ;
}
else
{
Con_Printf ( " refusing download of %s to %s \n " , fname , host_client - > name ) ;
MSG_WriteByte ( & host_client - > message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > message , " \n stopdownload \n " ) ;
}
host_client - > sendsignon = true ; //override any keepalive issues.
}
}
static void Host_StartDownload_f ( void )
{
if ( cmd_source ! = src_client )
return ;
if ( host_client - > download . file )
host_client - > download . started = true ;
else
SV_ClientPrintf ( " no download started \n " ) ;
}
//just writes download data onto the end of the outgoing unreliable buffer
void Host_AppendDownloadData ( client_t * client , sizebuf_t * buf )
{
if ( buf - > cursize + 7 > buf - > maxsize )
return ; //no space for anything
if ( client - > download . file & & client - > download . started )
{
byte tbuf [ 1400 ] ; //don't be too aggressive, ethernet mtu is about 1450
unsigned int size = client - > download . size - client - > download . sendpos ;
//size might be 0 at eof, and that's needed to avoid failure if we drop the last few packets
if ( size > sizeof ( tbuf ) )
size = sizeof ( tbuf ) ;
if ( ( int ) size > buf - > maxsize - ( buf - > cursize + 7 ) )
size = ( int ) ( buf - > maxsize - ( buf - > cursize + 7 ) ) ; //don't overflow
if ( size & & fread ( tbuf , 1 , size , host_client - > download . file ) < size )
client - > download . ackpos = client - > download . sendpos = client - > download . size ; //some kind of error...
else
{
MSG_WriteByte ( buf , svcdp_downloaddata ) ;
MSG_WriteLong ( buf , client - > download . sendpos ) ;
MSG_WriteShort ( buf , size ) ;
SZ_Write ( buf , tbuf , size ) ;
client - > download . sendpos + = size ;
}
}
}
//parses incoming acks from the client, so we know which parts of the file the client actually received.
void Host_DownloadAck ( client_t * client )
{
unsigned int start = MSG_ReadLong ( ) ;
unsigned int size = ( unsigned short ) MSG_ReadShort ( ) ;
if ( ! client - > download . started | | ! client - > download . file )
return ;
if ( client - > download . ackpos < start )
{
client - > download . sendpos = client - > download . ackpos ; //there was a gap, rewind to the known gap
fseek ( client - > download . file , host_client - > download . startpos + client - > download . sendpos , SEEK_SET ) ;
}
else if ( client - > download . ackpos < start + size )
client - > download . ackpos = start + size ; //no loss yet.
//else FIXME: build a log of parts known to be acked to avoid resending them later, skip past them in acks
if ( client - > download . ackpos = = client - > download . size )
{
unsigned int hash = 0 ;
byte * data ;
client - > download . started = false ;
data = malloc ( client - > download . size ) ;
if ( data )
{
fseek ( client - > download . file , host_client - > download . startpos , SEEK_SET ) ;
fread ( data , 1 , host_client - > download . size , client - > download . file ) ;
hash = CRC_Block ( data , host_client - > download . size ) ;
free ( data ) ;
}
fclose ( client - > download . file ) ;
client - > download . file = NULL ;
MSG_WriteByte ( & host_client - > message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > message , va ( " cl_downloadfinished %u %u \" %s \" \n " , client - > download . size , hash , client - > download . name ) ) ;
* client - > download . name = 0 ;
host_client - > sendsignon = true ; //override any keepalive issues.
}
}
2010-02-15 23:26:55 +00:00
//=============================================================================
/*
= = = = = = = = = = = = = = = = = =
Host_InitCommands
= = = = = = = = = = = = = = = = = =
*/
void Host_InitCommands ( void )
{
Cmd_AddCommand ( " maps " , Host_Maps_f ) ; //johnfitz
Cmd_AddCommand ( " mods " , Host_Mods_f ) ; //johnfitz
2010-02-27 08:05:36 +00:00
Cmd_AddCommand ( " games " , Host_Mods_f ) ; // as an alias to "mods" -- S.A. / QuakeSpasm
2010-02-15 23:26:55 +00:00
Cmd_AddCommand ( " mapname " , Host_Mapname_f ) ; //johnfitz
2017-06-23 23:22:00 +00:00
Cmd_AddCommand ( " randmap " , Host_Randmap_f ) ; //ericw
2010-02-15 23:26:55 +00:00
2017-09-17 02:12:53 +00:00
Cmd_AddCommand_ClientCommand ( " status " , Host_Status_f ) ;
2010-02-15 23:26:55 +00:00
Cmd_AddCommand ( " quit " , Host_Quit_f ) ;
2017-09-17 02:12:53 +00:00
Cmd_AddCommand_ClientCommand ( " god " , Host_God_f ) ;
Cmd_AddCommand_ClientCommand ( " notarget " , Host_Notarget_f ) ;
Cmd_AddCommand_ClientCommand ( " fly " , Host_Fly_f ) ;
2010-02-15 23:26:55 +00:00
Cmd_AddCommand ( " map " , Host_Map_f ) ;
Cmd_AddCommand ( " restart " , Host_Restart_f ) ;
Cmd_AddCommand ( " changelevel " , Host_Changelevel_f ) ;
Cmd_AddCommand ( " connect " , Host_Connect_f ) ;
2017-09-17 02:12:53 +00:00
Cmd_AddCommand_Console ( " reconnect " , Host_Reconnect_Con_f ) ;
Cmd_AddCommand_ServerCommand ( " reconnect " , Host_Reconnect_Sv_f ) ;
Cmd_AddCommand_ClientCommand ( " name " , Host_Name_f ) ;
Cmd_AddCommand_ClientCommand ( " noclip " , Host_Noclip_f ) ;
Cmd_AddCommand_ClientCommand ( " setpos " , Host_SetPos_f ) ; //QuakeSpasm
Cmd_AddCommand_ClientCommand ( " say " , Host_Say_f ) ;
Cmd_AddCommand_ClientCommand ( " say_team " , Host_Say_Team_f ) ;
Cmd_AddCommand_ClientCommand ( " tell " , Host_Tell_f ) ;
Cmd_AddCommand_ClientCommand ( " color " , Host_Color_f ) ;
Cmd_AddCommand_ClientCommand ( " kill " , Host_Kill_f ) ;
Cmd_AddCommand_ClientCommand ( " pause " , Host_Pause_f ) ;
Cmd_AddCommand_ClientCommand ( " spawn " , Host_Spawn_f ) ;
Cmd_AddCommand_ClientCommand ( " begin " , Host_Begin_f ) ;
Cmd_AddCommand_ClientCommand ( " prespawn " , Host_PreSpawn_f ) ;
Cmd_AddCommand_ClientCommand ( " kick " , Host_Kick_f ) ;
Cmd_AddCommand_ClientCommand ( " ping " , Host_Ping_f ) ;
2010-02-15 23:26:55 +00:00
Cmd_AddCommand ( " load " , Host_Loadgame_f ) ;
Cmd_AddCommand ( " save " , Host_Savegame_f ) ;
2017-09-17 02:12:53 +00:00
Cmd_AddCommand_ClientCommand ( " give " , Host_Give_f ) ;
Cmd_AddCommand_ClientCommand ( " download " , Host_Download_f ) ;
Cmd_AddCommand_ClientCommand ( " sv_startdownload " , Host_StartDownload_f ) ;
2010-02-15 23:26:55 +00:00
Cmd_AddCommand ( " startdemos " , Host_Startdemos_f ) ;
Cmd_AddCommand ( " demos " , Host_Demos_f ) ;
Cmd_AddCommand ( " stopdemo " , Host_Stopdemo_f ) ;
Cmd_AddCommand ( " viewmodel " , Host_Viewmodel_f ) ;
Cmd_AddCommand ( " viewframe " , Host_Viewframe_f ) ;
Cmd_AddCommand ( " viewnext " , Host_Viewnext_f ) ;
Cmd_AddCommand ( " viewprev " , Host_Viewprev_f ) ;
Cmd_AddCommand ( " mcache " , Mod_Print ) ;
}
2010-08-02 19:45:16 +00:00