diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index f09498eb..0a935f0b 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -2769,7 +2769,7 @@ void CL_Init( void ) IN_TouchInit(); COM_ResetLibraryError(); - if( !CL_LoadProgs( va( "%s/%s", GI->dll_path, GI->client_lib))) + if( !CL_LoadProgs( va( "%s/%s", GI->dll_path, SI.clientlib))) Host_Error( "can't initialize client.dll\n" ); cls.initialized = true; diff --git a/engine/client/console.c b/engine/client/console.c index c6457b3c..bc317ada 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -1238,72 +1238,6 @@ void Con_Print( const char *txt ) } } -/* -============= -Con_Printf - -============= -*/ -void Con_Printf( char *szFmt, ... ) -{ - static char buffer[MAX_PRINT_MSG]; - va_list args; - - if( !host.allow_console ) - return; - - va_start( args, szFmt ); - Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ); - va_end( args ); - - Sys_Print( buffer ); -} - -/* -============= -Con_DPrintf - -============= -*/ -void Con_DPrintf( char *szFmt, ... ) -{ - static char buffer[MAX_PRINT_MSG]; - va_list args; - - if( host_developer.value < DEV_NORMAL ) - return; - - va_start( args, szFmt ); - Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ); - va_end( args ); - - if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' ) - return; // hlrally spam - - Sys_Print( buffer ); -} - -/* -============= -Con_Reportf - -============= -*/ -void Con_Reportf( char *szFmt, ... ) -{ - static char buffer[MAX_PRINT_MSG]; - va_list args; - - if( host_developer.value < DEV_EXTENDED ) - return; - - va_start( args, szFmt ); - Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ); - va_end( args ); - - Sys_Print( buffer ); -} - /* ================ Con_NPrint diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index 24fed9ac..ad2bf0d1 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -718,56 +718,6 @@ float CL_GetSequenceDuration( cl_entity_t *ent, int sequence ) return 0.1f; } -/* -==================== -StudioGetAnim - -==================== -*/ -void *R_StudioGetAnim( studiohdr_t *m_pStudioHeader, model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc ) -{ - mstudioseqgroup_t *pseqgroup; - cache_user_t *paSequences; - size_t filesize; - byte *buf; - - pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup; - if( pseqdesc->seqgroup == 0 ) - return ((byte *)m_pStudioHeader + pseqgroup->data + pseqdesc->animindex); - - paSequences = (cache_user_t *)m_pSubModel->submodels; - - if( paSequences == NULL ) - { - paSequences = (cache_user_t *)Mem_Alloc( com_studiocache, MAXSTUDIOGROUPS * sizeof( cache_user_t )); - m_pSubModel->submodels = (void *)paSequences; - } - - // check for already loaded - if( !Mod_CacheCheck(( cache_user_t *)&( paSequences[pseqdesc->seqgroup] ))) - { - string filepath, modelname, modelpath; - - COM_FileBase( m_pSubModel->name, modelname ); - COM_ExtractFilePath( m_pSubModel->name, modelpath ); - - // NOTE: here we build real sub-animation filename because stupid user may rename model without recompile - Q_snprintf( filepath, sizeof( filepath ), "%s/%s%i%i.mdl", modelpath, modelname, pseqdesc->seqgroup / 10, pseqdesc->seqgroup % 10 ); - - buf = FS_LoadFile( filepath, &filesize, false ); - if( !buf || !filesize ) Host_Error( "StudioGetAnim: can't load %s\n", filepath ); - if( IDSEQGRPHEADER != *(uint *)buf ) Host_Error( "StudioGetAnim: %s is corrupted\n", filepath ); - - Con_Printf( "loading: %s\n", filepath ); - - paSequences[pseqdesc->seqgroup].data = Mem_Alloc( com_studiocache, filesize ); - memcpy( paSequences[pseqdesc->seqgroup].data, buf, filesize ); - Mem_Free( buf ); - } - - return ((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex); -} - /* ==================== StudioFxTransform @@ -877,197 +827,6 @@ void R_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, cons } } -/* -==================== -StudioCalcBoneQuaternion - -==================== -*/ -void R_StudioCalcBoneQuaternion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec4_t q ) -{ - vec3_t angles1; - vec3_t angles2; - int j, k; - - for( j = 0; j < 3; j++ ) - { - if( !panim || panim->offset[j+3] == 0 ) - { - angles2[j] = angles1[j] = pbone->value[j+3]; // default; - } - else - { - mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]); - - k = frame; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - - // find span of values that includes the frame we want - while( panimvalue->num.total <= k ) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - } - - // bah, missing blend! - if( panimvalue->num.valid > k ) - { - angles1[j] = panimvalue[k+1].value; - - if( panimvalue->num.valid > k + 1 ) - { - angles2[j] = panimvalue[k+2].value; - } - else - { - if( panimvalue->num.total > k + 1 ) - angles2[j] = angles1[j]; - else angles2[j] = panimvalue[panimvalue->num.valid+2].value; - } - } - else - { - angles1[j] = panimvalue[panimvalue->num.valid].value; - if( panimvalue->num.total > k + 1 ) - angles2[j] = angles1[j]; - else angles2[j] = panimvalue[panimvalue->num.valid+2].value; - } - - angles1[j] = pbone->value[j+3] + angles1[j] * pbone->scale[j+3]; - angles2[j] = pbone->value[j+3] + angles2[j] * pbone->scale[j+3]; - } - - if( pbone->bonecontroller[j+3] != -1 && adj != NULL ) - { - angles1[j] += adj[pbone->bonecontroller[j+3]]; - angles2[j] += adj[pbone->bonecontroller[j+3]]; - } - } - - if( !VectorCompare( angles1, angles2 )) - { - vec4_t q1, q2; - - AngleQuaternion( angles1, q1, true ); - AngleQuaternion( angles2, q2, true ); - QuaternionSlerp( q1, q2, s, q ); - } - else - { - AngleQuaternion( angles1, q, true ); - } -} - -/* -==================== -StudioCalcBonePosition - -==================== -*/ -void R_StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec3_t pos ) -{ - vec3_t origin1; - vec3_t origin2; - int j, k; - - for( j = 0; j < 3; j++ ) - { - if( !panim || panim->offset[j] == 0 ) - { - origin2[j] = origin1[j] = pbone->value[j]; // default; - } - else - { - mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]); - - k = frame; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - - // find span of values that includes the frame we want - while( panimvalue->num.total <= k ) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - } - - // bah, missing blend! - if( panimvalue->num.valid > k ) - { - origin1[j] = panimvalue[k+1].value; - - if( panimvalue->num.valid > k + 1 ) - { - origin2[j] = panimvalue[k+2].value; - } - else - { - if( panimvalue->num.total > k + 1 ) - origin2[j] = origin1[j]; - else origin2[j] = panimvalue[panimvalue->num.valid+2].value; - } - } - else - { - origin1[j] = panimvalue[panimvalue->num.valid].value; - if( panimvalue->num.total > k + 1 ) - origin2[j] = origin1[j]; - else origin2[j] = panimvalue[panimvalue->num.valid+2].value; - } - - origin1[j] = pbone->value[j] + origin1[j] * pbone->scale[j]; - origin2[j] = pbone->value[j] + origin2[j] * pbone->scale[j]; - } - - if( pbone->bonecontroller[j] != -1 && adj != NULL ) - { - origin1[j] += adj[pbone->bonecontroller[j]]; - origin2[j] += adj[pbone->bonecontroller[j]]; - } - } - - if( !VectorCompare( origin1, origin2 )) - { - VectorLerp( origin1, s, origin2, pos ); - } - else - { - VectorCopy( origin1, pos ); - } -} - -/* -==================== -StudioSlerpBones - -==================== -*/ -void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s ) -{ - int i; - - s = bound( 0.0f, s, 1.0f ); - - for( i = 0; i < numbones; i++ ) - { - QuaternionSlerp( q1[i], q2[i], s, q1[i] ); - VectorLerp( pos1[i], s, pos2[i], pos1[i] ); - } -} - /* ==================== StudioCalcRotations diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 05677092..07fa3d62 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -977,13 +977,16 @@ void Cmd_ExecuteString( char *text ) if( host.apply_game_config ) return; // don't send nothing to server: we is a server! +#ifndef XASH_DEDICATED // forward the command line to the server, so the entity DLL can parse it if( host.type == HOST_NORMAL ) { if( cls.state >= ca_connected ) Cmd_ForwardToServer(); } - else if( text[0] != '@' && host.type == HOST_NORMAL ) + else +#endif + if( text[0] != '@' && host.type == HOST_NORMAL ) { // commands with leading '@' are hidden system commands Con_Printf( S_WARN "Unknown command \"%s\"\n", text ); @@ -999,6 +1002,7 @@ things like godmode, noclip, etc, are commands directed to the server, so when they are typed in at the console, they will need to be forwarded. =================== */ +#ifndef XASH_DEDICATED void Cmd_ForwardToServer( void ) { char str[MAX_CMD_BUFFER]; @@ -1032,6 +1036,7 @@ void Cmd_ForwardToServer( void ) MSG_WriteString( &cls.netchan.message, str ); } +#endif // XASH_DEDICATED /* ============ @@ -1141,7 +1146,9 @@ void Cmd_Init( void ) Cmd_AddCommand( "wait", Cmd_Wait_f, "make script execution wait for some rendered frames" ); Cmd_AddCommand( "cmdlist", Cmd_List_f, "display all console commands beginning with the specified prefix" ); Cmd_AddCommand( "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in .rc script)" ); +#ifndef XASH_DEDICATED Cmd_AddCommand( "cmd", Cmd_ForwardToServer, "send a console commandline to the server" ); +#endif Cmd_AddCommand( "alias", Cmd_Alias_f, "create a script function. Without arguments show the list of all alias" ); Cmd_AddCommand( "unalias", Cmd_UnAlias_f, "remove a script function" ); Cmd_AddCommand( "if", Cmd_If_f, "compare and set condition bits" ); diff --git a/engine/common/common.h b/engine/common/common.h index 873f24ad..cfe1eef8 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -301,6 +301,8 @@ typedef struct sysinfo_s string exeName; // exe.filename string rcName; // .rc script name string basedirName; // name of base directory + string gamedll; + string clientlib; gameinfo_t *GameInfo; // current GameInfo gameinfo_t *games[MAX_MODS]; // environment games (founded at each engine start) int numgames; diff --git a/engine/common/con_utils.c b/engine/common/con_utils.c index 3931dacc..972f1706 100644 --- a/engine/common/con_utils.c +++ b/engine/common/con_utils.c @@ -464,6 +464,7 @@ qboolean Cmd_GetSoundList( const char *s, char *completedname, int length ) return true; } +#ifndef XASH_DEDICATED /* ===================================== Cmd_GetItemsList @@ -510,6 +511,7 @@ qboolean Cmd_GetItemsList( const char *s, char *completedname, int length ) } return true; } +#endif /* ===================================== @@ -817,8 +819,10 @@ autocomplete_list_t cmd_list[] = { "music", Cmd_GetMusicList, }, { "movie", Cmd_GetMovieList }, { "exec", Cmd_GetConfigList }, +#ifndef XASH_DEDICATED { "give", Cmd_GetItemsList }, { "drop", Cmd_GetItemsList }, +#endif { "game", Cmd_GetGamesList }, { "save", Cmd_GetSavesList }, { "load", Cmd_GetSavesList }, @@ -901,6 +905,7 @@ void Cmd_WriteOpenGLVariables( file_t *f ) Cvar_LookupVars( FCVAR_GLCONFIG, NULL, f, Cmd_WriteOpenGLCvar ); } +#ifndef XASH_DEDICATED /* =============== Host_WriteConfig @@ -946,6 +951,7 @@ void Host_WriteConfig( void ) } else MsgDev( D_ERROR, "Couldn't write config.cfg.\n" ); } +#endif /* =============== diff --git a/engine/common/custom.c b/engine/common/custom.c index 7b4b15c5..4a51bf1f 100644 --- a/engine/common/custom.c +++ b/engine/common/custom.c @@ -44,11 +44,13 @@ void COM_ClearCustomizationList( customization_t *pHead, qboolean bCleanDecals ) if( pCurrent->bInUse && pCurrent->pInfo ) { +#ifndef XASH_DEDICATED if( pCurrent->resource.type == t_decal ) { if( bCleanDecals && CL_Active( )) R_DecalRemoveAll( pCurrent->nUserData1 ); } +#endif FS_FreeImage( pCurrent->pInfo ); } diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 23a1010d..c01b3c31 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -90,12 +90,13 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti { if( FBitSet( var->flags, FCVAR_USERINFO )) { - if ( host.type == HOST_DEDICATED ) + if ( Host_IsDedicated() ) { // g-cont. this is a very strange behavior... Info_SetValueForKey( SV_Serverinfo(), var->name, value, MAX_SERVERINFO_STRING ), SV_BroadcastCommand( "fullserverinfo \"%s\"\n", SV_Serverinfo( )); } +#ifndef XASH_DEDICATED else { if( !Info_SetValueForKey( CL_Userinfo(), var->name, value, MAX_INFO_STRING )) @@ -104,6 +105,7 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti // time to update server copy of userinfo CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", var->name, value ); } +#endif } if( FBitSet( var->flags, FCVAR_SERVER ) && notify ) diff --git a/engine/common/dedicated.c b/engine/common/dedicated.c new file mode 100644 index 00000000..a7cbfc84 --- /dev/null +++ b/engine/common/dedicated.c @@ -0,0 +1,497 @@ +/* +dedicated.c - stubs for dedicated server +Copyright (C) 2018 a1batross, mittorn + +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 3 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. +*/ +#ifdef XASH_DEDICATED +#include "common.h" +#include "mathlib.h" + +const char *svc_strings[256] = +{ + "svc_bad", + "svc_nop", + "svc_disconnect", + "svc_changing", + "svc_version", + "svc_setview", + "svc_sound", + "svc_time", + "svc_print", + "svc_stufftext", + "svc_setangle", + "svc_serverdata", + "svc_lightstyle", + "svc_updateuserinfo", + "svc_deltatable", + "svc_clientdata", + "svc_stopsound", + "svc_updatepings", + "svc_particle", + "svc_restoresound", + "svc_spawnstatic", + "svc_event_reliable", + "svc_spawnbaseline", + "svc_temp_entity", + "svc_setpause", + "svc_signonnum", + "svc_centerprint", + "svc_event", + "svc_soundindex", + "svc_ambientsound", + "svc_intermission", + "svc_modelindex", + "svc_cdtrack", + "svc_serverinfo", + "svc_eventindex", + "svc_weaponanim", + "svc_bspdecal", + "svc_roomtype", + "svc_addangle", + "svc_usermessage", + "svc_packetentities", + "svc_deltapacketentities", + "svc_chokecount", + "svc_resourcelist", + "svc_deltamovevars", + "svc_customization", + "svc_unused46", + "svc_crosshairangle", + "svc_soundfade", + "svc_unused49", + "svc_unused50", + "svc_director", + "svc_studiodecal", + "svc_unused53", + "svc_unused54", + "svc_unused55", + "svc_unused56", + "svc_querycvarvalue", + "svc_querycvarvalue2", + "svc_unused59", + "svc_unused60", + "svc_unused61", + "svc_unused62", + "svc_unused63", +}; + +qboolean CL_Active( void ) +{ + return false; +} + +qboolean CL_Initialized( void ) +{ + return false; +} + +qboolean CL_IsInGame( void ) +{ + return true; // always active for dedicated servers +} + +qboolean CL_IsInMenu( void ) +{ + return false; +} + +qboolean CL_IsInConsole( void ) +{ + return false; +} + +qboolean CL_IsIntermission( void ) +{ + return false; +} + +qboolean CL_IsPlaybackDemo( void ) +{ + return false; +} + +qboolean CL_IsRecordDemo( void ) +{ + return false; +} + + +qboolean CL_DisableVisibility( void ) +{ + return false; +} + +qboolean CL_IsBackgroundDemo( void ) +{ + return false; +} + +qboolean CL_IsBackgroundMap( void ) +{ + return false; +} + +void CL_Init() +{ + +} + +void Key_Init() +{ + +} + +void IN_Init() +{ + +} + +void CL_Drop() +{ + +} + +void CL_ClearEdicts() +{ + +} + +void Key_SetKeyDest(int key_dest) +{ + +} + +void UI_SetActiveMenu( qboolean fActive ) +{ + +} + +void CL_WriteMessageHistory() +{ + +} + +void Host_ClientBegin() +{ + +} + +void Host_ClientFrame() +{ + +} + +void Host_InputFrame() +{ + Cbuf_Execute(); +} + +void VID_InitDefaultResolution() +{ + +} + +void Con_Init() +{ + +} + +void R_ClearAllDecals() +{ + +} +int R_CreateDecalList( struct decallist_s *pList ) +{ + return 0; +} + +void S_StopSound(int entnum, int channel, const char *soundname) +{ + +} + +int S_GetCurrentStaticSounds( soundlist_t *pout, int size ) +{ + return 0; +} + +int CL_GetMaxClients() +{ + return 0; +} + +void IN_TouchInitConfig() +{ + +} + +void CL_Disconnect() +{ + +} + +void CL_Shutdown() +{ + +} + +void R_ClearStaticEntities() +{ + +} + +void Host_Credits() +{ + +} + +qboolean UI_CreditsActive() +{ + return false; +} + +void GL_FreeImage( const char *name ) +{ + +} + +void S_StopBackgroundTrack() +{ + +} + +void SCR_BeginLoadingPlaque( qboolean is_background ) +{ + +} + +int S_GetCurrentDynamicSounds( soundlist_t *pout, int size ) +{ + return 0; +} + +void S_StopAllSounds( qboolean ambient ) +{ + +} + +void Con_NPrintf( int idx, char *fmt, ... ) +{ + +} + +void Con_NXPrintf( struct con_nprint_s *info, char *fmt, ... ) +{ + +} + +const byte *GL_TextureData( unsigned int texnum ) +{ + return NULL; +} + +void SCR_CheckStartupVids() +{ + +} + +imgfilter_t *R_FindTexFilter( const char *texname ) +{ + return NULL; +} + +#include "sprite.h" + +/* +==================== +Mod_LoadSpriteModel + +load sprite model +==================== +*/ +void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags ) +{ + dsprite_q1_t *pinq1; + dsprite_hl_t *pinhl; + dsprite_t *pin; + short *numi = NULL; + dframetype_t *pframetype; + msprite_t *psprite; + int i, size; + + if( loaded ) *loaded = false; + pin = (dsprite_t *)buffer; + mod->type = mod_sprite; + i = pin->version; + + if( pin->ident != IDSPRITEHEADER ) + { + MsgDev( D_ERROR, "%s has wrong id (%x should be %x)\n", mod->name, pin->ident, IDSPRITEHEADER ); + return; + } + + if( i != SPRITE_VERSION_Q1 && i != SPRITE_VERSION_HL && i != SPRITE_VERSION_32 ) + { + MsgDev( D_ERROR, "%s has wrong version number (%i should be %i or %i)\n", mod->name, i, SPRITE_VERSION_Q1, SPRITE_VERSION_HL ); + return; + } + + mod->mempool = Mem_AllocPool( va( "^2%s^7", mod->name )); + + if( i == SPRITE_VERSION_Q1 || i == SPRITE_VERSION_32 ) + { + pinq1 = (dsprite_q1_t *)buffer; + size = sizeof( msprite_t ) + ( pinq1->numframes - 1 ) * sizeof( psprite->frames ); + psprite = Mem_Alloc( mod->mempool, size ); + mod->cache.data = psprite; // make link to extradata + + psprite->type = pinq1->type; + psprite->texFormat = SPR_ADDITIVE; //SPR_ALPHTEST; + psprite->numframes = mod->numframes = pinq1->numframes; + psprite->facecull = SPR_CULL_FRONT; + psprite->radius = pinq1->boundingradius; + psprite->synctype = pinq1->synctype; + + mod->mins[0] = mod->mins[1] = -pinq1->bounds[0] * 0.5f; + mod->maxs[0] = mod->maxs[1] = pinq1->bounds[0] * 0.5f; + mod->mins[2] = -pinq1->bounds[1] * 0.5f; + mod->maxs[2] = pinq1->bounds[1] * 0.5f; + numi = NULL; + } + else if( i == SPRITE_VERSION_HL ) + { + pinhl = (dsprite_hl_t *)buffer; + size = sizeof( msprite_t ) + ( pinhl->numframes - 1 ) * sizeof( psprite->frames ); + psprite = Mem_Alloc( mod->mempool, size ); + mod->cache.data = psprite; // make link to extradata + + psprite->type = pinhl->type; + psprite->texFormat = pinhl->texFormat; + psprite->numframes = mod->numframes = pinhl->numframes; + psprite->facecull = pinhl->facetype; + psprite->radius = pinhl->boundingradius; + psprite->synctype = pinhl->synctype; + + mod->mins[0] = mod->mins[1] = -pinhl->bounds[0] * 0.5f; + mod->maxs[0] = mod->maxs[1] = pinhl->bounds[0] * 0.5f; + mod->mins[2] = -pinhl->bounds[1] * 0.5f; + mod->maxs[2] = pinhl->bounds[1] * 0.5f; + numi = (short *)(pinhl + 1); + } + + if( host.type == HOST_DEDICATED ) + { + // skip frames loading + if( loaded ) *loaded = true; // done + psprite->numframes = 0; + return; + } + + if( numi == NULL ) + { + rgbdata_t *pal; + + pal = FS_LoadImage( "#id.pal", (byte *)&i, 768 ); + pframetype = (dframetype_t *)(pinq1 + 1); + FS_FreeImage( pal ); // palette installed, no reason to keep this data + } + else if( *numi == 256 ) + { + byte *src = (byte *)(numi+1); + rgbdata_t *pal; + + // install palette + switch( psprite->texFormat ) + { + case SPR_INDEXALPHA: + pal = FS_LoadImage( "#gradient.pal", src, 768 ); + break; + case SPR_ALPHTEST: + pal = FS_LoadImage( "#masked.pal", src, 768 ); + break; + default: + pal = FS_LoadImage( "#normal.pal", src, 768 ); + break; + } + + pframetype = (dframetype_t *)(src + 768); + FS_FreeImage( pal ); // palette installed, no reason to keep this data + } + else + { + MsgDev( D_ERROR, "%s has wrong number of palette colors %i (should be 256)\n", mod->name, *numi ); + return; + } + + if( mod->numframes < 1 ) + { + MsgDev( D_ERROR, "%s has invalid # of frames: %d\n", mod->name, mod->numframes ); + return; + } + + if( loaded ) *loaded = true; // done +} + +/* +==================== +Mod_UnloadSpriteModel + +release sprite model and frames +==================== +*/ +void Mod_UnloadSpriteModel( model_t *mod ) +{ + msprite_t *psprite; + mspritegroup_t *pspritegroup; + mspriteframe_t *pspriteframe; + int i, j; + + Assert( mod != NULL ); + +#ifndef XASH_DEDICATED + if( mod->type == mod_sprite ) + { + if( host.type != HOST_DEDICATED ) + { + psprite = mod->cache.data; + + if( psprite ) + { + // release all textures + for( i = 0; i < psprite->numframes; i++ ) + { + if( psprite->frames[i].type == SPR_SINGLE ) + { + pspriteframe = psprite->frames[i].frameptr; + GL_FreeTexture( pspriteframe->gl_texturenum ); + } + else + { + pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr; + + for( j = 0; j < pspritegroup->numframes; j++ ) + { + pspriteframe = pspritegroup->frames[i]; + GL_FreeTexture( pspriteframe->gl_texturenum ); + } + } + } + } + } + } +#endif + + Mem_FreePool( &mod->mempool ); + memset( mod, 0, sizeof( *mod )); +} + +#endif // XASH_DEDICATED \ No newline at end of file diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index 54b5bd75..e1b223d2 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -1386,6 +1386,27 @@ void FS_LoadGameInfo( const char *rootfolder ) Sys_Error( "Couldn't find game directory '%s'\n", fs_gamedir ); SI.GameInfo = SI.games[i]; + if( !Sys_GetParmFromCmdLine( "-dll", SI.gamedll ) ) + { +#ifdef XASH_INTERNAL_GAMELIBS + Q_strncpy( SI.gamedll, "server", sizeof( SI.gamedll ) ); +#elif defined(_WIN32) + Q_strncpy( SI.gamedll, GI->game_dll, sizeof( SI.gamedll ) ); +#elif defined(__APPLE__) + Q_strncpy( SI.gamedll, GI->game_dll_osx, sizeof( SI.gamedll ) ); +#else + Q_strncpy( SI.gamedll, GI->game_dll_linux, sizeof( SI.gamedll ) ); +#endif + } + if( !Sys_GetParmFromCmdLine( "-clientlib", SI.clientlib ) ) + { +#ifdef __ANDROID__ + Q_strncpy( SI.clientlib, CLIENTDLL, sizeof( SI.clientlib ) ); +#else + Q_strncpy( SI.clientlib, GI->client_lib, sizeof( SI.clientlib ) ); +#endif + } + FS_Rescan(); // create new filesystem Host_InitDecals (); // reload decals diff --git a/engine/common/host.c b/engine/common/host.c index 0e02b0e9..3b2e781f 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -116,11 +116,13 @@ void Host_EndGame( qboolean abort, const char *message, ... ) MsgDev( D_INFO, "Host_EndGame: %s\n", string ); SV_Shutdown( "\n" ); +#ifndef XASH_DEDICATED CL_Disconnect(); // recreate world if needs CL_ClearEdicts (); - +#endif + // release all models Mod_FreeAll(); @@ -412,17 +414,20 @@ double Host_CalcFPS( void ) double fps = 0.0; // NOTE: we should play demos with same fps as it was recorded +#ifndef XASH_DEDICATED if( CL_IsPlaybackDemo() || CL_IsRecordDemo( )) fps = CL_GetDemoFramerate(); - else if( Host_IsLocalGame( )) + else +#endif + if( Host_IsLocalGame( )) fps = host_maxfps->value; else { fps = host_maxfps->value; if( fps == 0.0 ) fps = HOST_FPS; // default for multiplayer - fps = bound( MIN_FPS, fps, MAX_FPS ); } +#ifndef XASH_DEDICATED // probably left part of this condition is redundant :-) if( host.type != HOST_DEDICATED && Host_IsLocalGame( ) && !CL_IsTimeDemo( )) { @@ -434,6 +439,7 @@ double Host_CalcFPS( void ) else fps = 60.0; // default } } +#endif return fps; } @@ -962,8 +968,10 @@ void EXPORT Host_Shutdown( void ) if( host.status != HOST_ERR_FATAL ) host.status = HOST_SHUTDOWN; // prepare host to normal shutdown if( !host.change_game ) Q_strncpy( host.finalmsg, "Server shutdown", sizeof( host.finalmsg )); +#ifndef XASH_DEDICATED if( host.type == HOST_NORMAL ) Host_WriteConfig(); +#endif SV_Shutdown( "" ); CL_Shutdown(); diff --git a/engine/common/infostring.c b/engine/common/infostring.c index fd299ac1..3e65072a 100644 --- a/engine/common/infostring.c +++ b/engine/common/infostring.c @@ -130,6 +130,7 @@ qboolean Info_IsValid( const char *s ) return true; } +#ifndef XASH_DEDICATED /* ============== Info_WriteVars @@ -177,6 +178,7 @@ void Info_WriteVars( file_t *f ) s++; } } +#endif // XASH_DEDICATED /* =============== diff --git a/engine/common/launcher.c b/engine/common/launcher.c new file mode 100644 index 00000000..fe74e73e --- /dev/null +++ b/engine/common/launcher.c @@ -0,0 +1,109 @@ +/* +launcher.c - direct xash3d launcher +Copyright (C) 2015 Mittorn + +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 3 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. +*/ + +#ifdef SINGLE_BINARY + +#include +#include +#ifdef XASH_SDLMAIN +#include "SDL.h" +#endif + + +#ifdef __EMSCRIPTEN__ +#include +#endif +typedef void (*pfnChangeGame)( const char *progname ); + +char szGameDir[128]; // safe place to keep gamedir +int g_iArgc; + +void Host_Shutdown( void ); +void Launcher_ChangeGame( const char *progname ); +void *Com_LoadLibrary( char *, int ); +int Host_Main( int szArgc, char **szArgv, const char *szGameDir, int chg, pfnChangeGame callback ); + +char **g_pszArgv; + +void Launcher_ChangeGame( const char *progname ) +{ + strncpy( szGameDir, progname, sizeof( szGameDir ) - 1 ); + Host_Shutdown( ); + exit( Host_Main( g_iArgc, g_pszArgv, szGameDir, 1, &Launcher_ChangeGame ) ); +} + +#ifdef XASH_NOCONHOST +#include +int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int nShow) +{ + int szArgc; + char **szArgv; + LPWSTR* lpArgv = CommandLineToArgvW(GetCommandLineW(), &szArgc); + int size, i = 0; + szArgv = (char**)malloc(szArgc*sizeof(char*)); + for (; i < szArgc; ++i) + { + size = wcslen(lpArgv[i]) + 1; + szArgv[i] = (char*)malloc(size); + wcstombs(szArgv[i], lpArgv[i], size); + } + LocalFree(lpArgv); + main( szArgc, szArgv ); +} +#endif +int main( int argc, char** argv ) +{ + char gamedir_buf[32] = ""; + const char *gamedir = getenv("XASH3D_GAMEDIR"); + + if( !gamedir ) + { + gamedir = "valve"; + } + else + { + strncpy( gamedir_buf, gamedir, 32 ); + gamedir = gamedir_buf; + } + +#ifdef __EMSCRIPTEN__ +#ifdef EMSCRIPTEN_LIB_FS + // For some unknown reason emscripten refusing to load libraries later + Com_LoadLibrary("menu", 0 ); + Com_LoadLibrary("server", 0 ); + Com_LoadLibrary("client", 0 ); +#endif +#ifdef XASH_DEDICATED + // NodeJS support for debug + EM_ASM(try{ + FS.mkdir('/xash'); + FS.mount(NODEFS, { root: '.'}, '/xash' ); + FS.chdir('/xash'); + }catch(e){};); +#endif +#endif + + g_iArgc = argc; + g_pszArgv = argv; +#if TARGET_OS_IPHONE + { + void IOS_LaunchDialog( void ); + IOS_LaunchDialog(); + } +#endif + return Host_Main( g_iArgc, g_pszArgv, gamedir, 0, &Launcher_ChangeGame ); +} + +#endif diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index f63dac20..e99dedcf 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -1778,11 +1778,13 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) if( bmod->isworld ) { +#ifndef XASH_DEDICATED // release old sky layers first GL_FreeTexture( tr.solidskyTexture ); GL_FreeTexture( tr.alphaskyTexture ); tr.solidskyTexture = 0; tr.alphaskyTexture = 0; +#endif } if( !bmod->texdatasize ) @@ -1805,8 +1807,10 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) loadmodel->textures[i] = tx; Q_strncpy( tx->name, "*default", sizeof( tx->name )); +#ifndef XASH_DEDICATED tx->gl_texturenum = tr.defaultTexture; tx->width = tx->height = 16; +#endif continue; // missed } @@ -1851,6 +1855,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) if( remaining >= 770 ) custom_palette = true; } +#ifndef XASH_DEDICATED // check for multi-layered sky texture (quake1 specific) if( bmod->isworld && !Q_strncmp( mt->name, "sky", 3 ) && (( mt->width / mt->height ) == 2 )) { @@ -1943,6 +1948,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) if( src ) Mem_Free( src ); } } +#endif } // sequence the animations and detail textures @@ -2224,8 +2230,10 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod ) next_lightofs = 99999999; } +#ifndef XASH_DEDICATED // TODO: Do we need subdivide on server? if( FBitSet( out->flags, SURF_DRAWTURB )) GL_SubdivideSurface( out ); // cut up polygon for warps +#endif } // now we have enough data to trying determine samplecount per lightmap pixel @@ -2794,6 +2802,7 @@ void Mod_UnloadBrushModel( model_t *mod ) if( mod->name[0] != '*' ) { +#ifndef XASH_DEDICATED for( i = 0; i < mod->numtextures; i++ ) { tx = mod->textures[i]; @@ -2803,6 +2812,7 @@ void Mod_UnloadBrushModel( model_t *mod ) GL_FreeTexture( tx->gl_texturenum ); // main texture GL_FreeTexture( tx->fb_texturenum ); // luma texture } +#endif Mem_FreePool( &mod->mempool ); } diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index 37bd8e86..ca826d66 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -396,6 +396,247 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p if( pseqdesc->motiontype & STUDIO_Z ) pos[pseqdesc->motionbone][2] = 0.0f; } +/* +==================== +StudioCalcBoneQuaternion + +==================== +*/ +void R_StudioCalcBoneQuaternion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec4_t q ) +{ + vec3_t angles1; + vec3_t angles2; + int j, k; + + for( j = 0; j < 3; j++ ) + { + if( !panim || panim->offset[j+3] == 0 ) + { + angles2[j] = angles1[j] = pbone->value[j+3]; // default; + } + else + { + mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]); + + k = frame; + + // debug + if( panimvalue->num.total < panimvalue->num.valid ) + k = 0; + + // find span of values that includes the frame we want + while( panimvalue->num.total <= k ) + { + k -= panimvalue->num.total; + panimvalue += panimvalue->num.valid + 1; + + // debug + if( panimvalue->num.total < panimvalue->num.valid ) + k = 0; + } + + // bah, missing blend! + if( panimvalue->num.valid > k ) + { + angles1[j] = panimvalue[k+1].value; + + if( panimvalue->num.valid > k + 1 ) + { + angles2[j] = panimvalue[k+2].value; + } + else + { + if( panimvalue->num.total > k + 1 ) + angles2[j] = angles1[j]; + else angles2[j] = panimvalue[panimvalue->num.valid+2].value; + } + } + else + { + angles1[j] = panimvalue[panimvalue->num.valid].value; + if( panimvalue->num.total > k + 1 ) + angles2[j] = angles1[j]; + else angles2[j] = panimvalue[panimvalue->num.valid+2].value; + } + + angles1[j] = pbone->value[j+3] + angles1[j] * pbone->scale[j+3]; + angles2[j] = pbone->value[j+3] + angles2[j] * pbone->scale[j+3]; + } + + if( pbone->bonecontroller[j+3] != -1 && adj != NULL ) + { + angles1[j] += adj[pbone->bonecontroller[j+3]]; + angles2[j] += adj[pbone->bonecontroller[j+3]]; + } + } + + if( !VectorCompare( angles1, angles2 )) + { + vec4_t q1, q2; + + AngleQuaternion( angles1, q1, true ); + AngleQuaternion( angles2, q2, true ); + QuaternionSlerp( q1, q2, s, q ); + } + else + { + AngleQuaternion( angles1, q, true ); + } +} + +/* +==================== +StudioCalcBonePosition + +==================== +*/ +void R_StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec3_t pos ) +{ + vec3_t origin1; + vec3_t origin2; + int j, k; + + for( j = 0; j < 3; j++ ) + { + if( !panim || panim->offset[j] == 0 ) + { + origin2[j] = origin1[j] = pbone->value[j]; // default; + } + else + { + mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]); + + k = frame; + + // debug + if( panimvalue->num.total < panimvalue->num.valid ) + k = 0; + + // find span of values that includes the frame we want + while( panimvalue->num.total <= k ) + { + k -= panimvalue->num.total; + panimvalue += panimvalue->num.valid + 1; + + // debug + if( panimvalue->num.total < panimvalue->num.valid ) + k = 0; + } + + // bah, missing blend! + if( panimvalue->num.valid > k ) + { + origin1[j] = panimvalue[k+1].value; + + if( panimvalue->num.valid > k + 1 ) + { + origin2[j] = panimvalue[k+2].value; + } + else + { + if( panimvalue->num.total > k + 1 ) + origin2[j] = origin1[j]; + else origin2[j] = panimvalue[panimvalue->num.valid+2].value; + } + } + else + { + origin1[j] = panimvalue[panimvalue->num.valid].value; + if( panimvalue->num.total > k + 1 ) + origin2[j] = origin1[j]; + else origin2[j] = panimvalue[panimvalue->num.valid+2].value; + } + + origin1[j] = pbone->value[j] + origin1[j] * pbone->scale[j]; + origin2[j] = pbone->value[j] + origin2[j] * pbone->scale[j]; + } + + if( pbone->bonecontroller[j] != -1 && adj != NULL ) + { + origin1[j] += adj[pbone->bonecontroller[j]]; + origin2[j] += adj[pbone->bonecontroller[j]]; + } + } + + if( !VectorCompare( origin1, origin2 )) + { + VectorLerp( origin1, s, origin2, pos ); + } + else + { + VectorCopy( origin1, pos ); + } +} + +/* +==================== +StudioSlerpBones + +==================== +*/ +void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s ) +{ + int i; + + s = bound( 0.0f, s, 1.0f ); + + for( i = 0; i < numbones; i++ ) + { + QuaternionSlerp( q1[i], q2[i], s, q1[i] ); + VectorLerp( pos1[i], s, pos2[i], pos1[i] ); + } +} + +/* +==================== +StudioGetAnim + +==================== +*/ +void *R_StudioGetAnim( studiohdr_t *m_pStudioHeader, model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc ) +{ + mstudioseqgroup_t *pseqgroup; + cache_user_t *paSequences; + size_t filesize; + byte *buf; + + pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup; + if( pseqdesc->seqgroup == 0 ) + return ((byte *)m_pStudioHeader + pseqgroup->data + pseqdesc->animindex); + + paSequences = (cache_user_t *)m_pSubModel->submodels; + + if( paSequences == NULL ) + { + paSequences = (cache_user_t *)Mem_Alloc( com_studiocache, MAXSTUDIOGROUPS * sizeof( cache_user_t )); + m_pSubModel->submodels = (void *)paSequences; + } + + // check for already loaded + if( !Mod_CacheCheck(( cache_user_t *)&( paSequences[pseqdesc->seqgroup] ))) + { + string filepath, modelname, modelpath; + + COM_FileBase( m_pSubModel->name, modelname ); + COM_ExtractFilePath( m_pSubModel->name, modelpath ); + + // NOTE: here we build real sub-animation filename because stupid user may rename model without recompile + Q_snprintf( filepath, sizeof( filepath ), "%s/%s%i%i.mdl", modelpath, modelname, pseqdesc->seqgroup / 10, pseqdesc->seqgroup % 10 ); + + buf = FS_LoadFile( filepath, &filesize, false ); + if( !buf || !filesize ) Host_Error( "StudioGetAnim: can't load %s\n", filepath ); + if( IDSEQGRPHEADER != *(uint *)buf ) Host_Error( "StudioGetAnim: %s is corrupted\n", filepath ); + + Con_Printf( "loading: %s\n", filepath ); + + paSequences[pseqdesc->seqgroup].data = Mem_Alloc( com_studiocache, filesize ); + memcpy( paSequences[pseqdesc->seqgroup].data, buf, filesize ); + Mem_Free( buf ); + } + + return ((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex); +} + /* ==================== StudioSetupBones @@ -806,6 +1047,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded ) phdr = R_StudioLoadHeader( mod, buffer ); if( !phdr ) return; // bad model +#ifndef XASH_DEDICATED if( phdr->numtextures == 0 ) { studiohdr_t *thdr; @@ -821,8 +1063,8 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded ) MsgDev( D_WARN, "Mod_LoadStudioModel: %s missing textures file\n", mod->name ); if( buffer2 ) Mem_Free( buffer2 ); } - else - { + else + { Mod_StudioLoadTextures( mod, thdr ); // give space for textures and skinrefs @@ -857,6 +1099,13 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded ) phdr = (studiohdr_t *)loadmodel->cache.data; // get the new pointer on studiohdr phdr->length = phdr->texturedataindex; // update model size } +#else + // just copy model into memory + loadmodel->cache.data = Mem_Alloc( loadmodel->mempool, phdr->length ); + memcpy( loadmodel->cache.data, buffer, phdr->length ); + + phdr = loadmodel->cache.data; +#endif // setup bounding box if( !VectorCompare( vec3_origin, phdr->bbmin )) @@ -898,7 +1147,9 @@ void Mod_UnloadStudioModel( model_t *mod ) if( mod->type != mod_studio ) return; // not a studio +#ifndef XASH_DEDICATED Mod_StudioUnloadTextures( mod->cache.data ); +#endif Mem_FreePool( &mod->mempool ); memset( mod, 0, sizeof( *mod )); } diff --git a/engine/common/model.c b/engine/common/model.c index 1f0a768d..58449cbc 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -77,7 +77,7 @@ static void Mod_FreeUserData( model_t *mod ) if( !mod->name[0] || mod->name[0] == '*' ) return; - if( host.type == HOST_DEDICATED ) + if( Host_IsDedicated() ) { if( svgame.physFuncs.Mod_ProcessUserData != NULL ) { @@ -85,6 +85,7 @@ static void Mod_FreeUserData( model_t *mod ) svgame.physFuncs.Mod_ProcessUserData( mod, false, NULL ); } } +#ifndef XASH_DEDICATED else { if( clgame.drawFuncs.Mod_ProcessUserData != NULL ) @@ -93,6 +94,7 @@ static void Mod_FreeUserData( model_t *mod ) clgame.drawFuncs.Mod_ProcessUserData( mod, false, NULL ); } } +#endif } /* @@ -115,15 +117,17 @@ static void Mod_FreeModel( model_t *mod ) case mod_sprite: Mod_UnloadSpriteModel( mod ); break; +#ifndef XASH_DEDICATED + case mod_alias: + Mod_UnloadAliasModel( mod ); + break; +#endif case mod_studio: Mod_UnloadStudioModel( mod ); break; case mod_brush: Mod_UnloadBrushModel( mod ); break; - case mod_alias: - Mod_UnloadAliasModel( mod ); - break; } memset( mod, 0, sizeof( *mod )); @@ -302,9 +306,12 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash ) case IDSPRITEHEADER: Mod_LoadSpriteModel( mod, buf, &loaded, 0 ); break; + // TODO: Load alias models on dedicated too? +#ifndef XASH_DEDICATED case IDALIASHEADER: Mod_LoadAliasModel( mod, buf, &loaded ); break; +#endif case Q1BSP_VERSION: case HLBSP_VERSION: case QBSP2_VERSION: @@ -332,7 +339,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash ) if( world.loading ) SetBits( mod->flags, MODEL_WORLD ); // mark worldmodel - if( host.type == HOST_DEDICATED ) + if( Host_IsDedicated() ) { if( svgame.physFuncs.Mod_ProcessUserData != NULL ) { @@ -340,6 +347,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash ) svgame.physFuncs.Mod_ProcessUserData( mod, true, buf ); } } +#ifndef XASH_DEDICATED else { if( clgame.drawFuncs.Mod_ProcessUserData != NULL ) @@ -348,6 +356,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash ) clgame.drawFuncs.Mod_ProcessUserData( mod, true, buf ); } } +#endif } p = &mod_crcinfo[mod - mod_known]; diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index b471eb11..e4f1a075 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -1180,6 +1180,7 @@ Netchan_UpdateProgress */ void Netchan_UpdateProgress( netchan_t *chan ) { +#ifndef XASH_DEDICATED fragbuf_t *p; int i, c = 0; int total = 0; @@ -1256,6 +1257,7 @@ void Netchan_UpdateProgress( netchan_t *chan ) } scr_download->value = bestpercent; +#endif // XASH_DEDICATED } /* diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index abfd9100..928c9fc1 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -1798,6 +1798,7 @@ Can go from either a baseline or a previous packet_entity */ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, qboolean player, float timebase ) { +#ifndef XASH_DEDICATED delta_info_t *dt = NULL; delta_t *pField; int i, fRemoveType; @@ -1877,7 +1878,7 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state { Delta_ReadField( msg, pField, from, to, timebase ); } - +#endif // XASH_DEDICATED // message parsed return true; } diff --git a/engine/common/pm_debug.c b/engine/common/pm_debug.c index 87f36c7f..22f52db6 100644 --- a/engine/common/pm_debug.c +++ b/engine/common/pm_debug.c @@ -29,6 +29,7 @@ draw line from particles */ void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float life, float zvel ) { +#ifndef XASH_DEDICATED float len, curdist; vec3_t diff, pos; @@ -43,6 +44,7 @@ void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float li CL_Particle( pos, pcolor, life, 0, zvel ); curdist += 2.0f; } +#endif // XASH_DEDICATED } /* @@ -67,6 +69,7 @@ PM_DrawBBox */ void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int pcolor, float life ) { +#ifndef XASH_DEDICATED vec3_t p[8], tmp; float gap = BOX_GAP; int i; @@ -85,4 +88,5 @@ void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int { PM_DrawRectangle( p[boxpnt[i][1]], p[boxpnt[i][0]], p[boxpnt[i][2]], p[boxpnt[i][3]], pcolor, life ); } +#endif // XASH_DEDICATED } \ No newline at end of file diff --git a/engine/common/pm_trace.c b/engine/common/pm_trace.c index a925b84f..db93e856 100644 --- a/engine/common/pm_trace.c +++ b/engine/common/pm_trace.c @@ -461,7 +461,9 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int // run custom sweep callback if( pmove->server || Host_IsLocalClient( )) SV_ClipPMoveToEntity( pe, start, mins, maxs, end, &trace_bbox ); +#ifndef XASH_DEDICATED else CL_ClipPMoveToEntity( pe, start, mins, maxs, end, &trace_bbox ); +#endif } else if( hullcount == 1 ) { @@ -628,7 +630,9 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p // run custom sweep callback if( pmove->server || Host_IsLocalClient( )) SV_ClipPMoveToEntity( pe, pos, mins, maxs, pos, &trace ); +#ifndef XASH_DEDICATED else CL_ClipPMoveToEntity( pe, pos, mins, maxs, pos, &trace ); +#endif // if we inside the custom hull if( trace.allsolid ) diff --git a/engine/common/sys_con.c b/engine/common/sys_con.c index fcc356a8..eb4ad095 100644 --- a/engine/common/sys_con.c +++ b/engine/common/sys_con.c @@ -221,3 +221,76 @@ void Sys_PrintLog( const char *pMsg ) fprintf( s_ld.logfile, "%s %s", logtime, pMsg ); fflush( s_ld.logfile ); } + +/* +============================================================================= + +CONSOLE PRINT + +============================================================================= +*/ +/* +============= +Con_Printf + +============= +*/ +void Con_Printf( char *szFmt, ... ) +{ + static char buffer[MAX_PRINT_MSG]; + va_list args; + + if( !host.allow_console ) + return; + + va_start( args, szFmt ); + Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ); + va_end( args ); + + Sys_Print( buffer ); +} + +/* +============= +Con_DPrintf + +============= +*/ +void Con_DPrintf( char *szFmt, ... ) +{ + static char buffer[MAX_PRINT_MSG]; + va_list args; + + if( host_developer.value < DEV_NORMAL ) + return; + + va_start( args, szFmt ); + Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ); + va_end( args ); + + if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' ) + return; // hlrally spam + + Sys_Print( buffer ); +} + +/* +============= +Con_Reportf + +============= +*/ +void Con_Reportf( char *szFmt, ... ) +{ + static char buffer[MAX_PRINT_MSG]; + va_list args; + + if( host_developer.value < DEV_EXTENDED ) + return; + + va_start( args, szFmt ); + Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ); + va_end( args ); + + Sys_Print( buffer ); +} \ No newline at end of file diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 5e05fc52..4f7eb1f0 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -584,11 +584,13 @@ void SV_RestartAmbientSounds( void ) SV_StartSound( pfnPEntityOfEntIndex( si->entnum ), CHAN_STATIC, si->name, si->volume, si->attenuation, 0, si->pitch ); } +#ifndef XASH_DEDICATED // TODO: ??? // restart soundtrack if( S_StreamGetCurrentState( curtrack, looptrack, &position )) { SV_StartMusic( curtrack, looptrack, position ); } +#endif } /* diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 92d8c683..d02dc485 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -645,9 +645,10 @@ qboolean SV_InitGame( void ) return true; // already initialized ? // first initialize? - if( !SV_LoadProgs( GI->game_dll )) + COM_ResetLibraryError(); + if( !SV_LoadProgs( SI.gamedll )) { - Con_Printf( S_ERROR "can't initialize %s\n", GI->game_dll ); + Con_Printf( S_ERROR "can't initialize %s: %s\n", SI.gamedll, COM_GetLibraryError() ); return false; // failed to loading server.dll } diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 27bd96d6..500c7483 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -21,7 +21,9 @@ GNU General Public License for more details. #include "gl_export.h" typedef int (*PHYSICAPI)( int, server_physics_api_t*, physics_interface_t* ); +#ifndef XASH_DEDICATED extern triangleapi_t gTriApi; +#endif /* pushmove objects do not obey gravity, and do not interact with each other or trigger fields, @@ -2004,10 +2006,17 @@ static server_physics_api_t gPhysicsAPI = SV_GetHeadNode, SV_ServerState, Host_Error, +#ifndef XASH_DEDICATED &gTriApi, // ouch! pfnDrawConsoleString, pfnDrawSetTextColor, pfnDrawConsoleStringLen, +#else + NULL, // ouch! ouch! + NULL, // ouch! ouch! + NULL, // ouch! ouch! + NULL, // ouch! ouch! +#endif Con_NPrintf, Con_NXPrintf, SV_GetLightStyle, diff --git a/engine/server/sv_pmove.c b/engine/server/sv_pmove.c index 86db26b5..4acff04a 100644 --- a/engine/server/sv_pmove.c +++ b/engine/server/sv_pmove.c @@ -323,6 +323,27 @@ void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3 SV_AddLaddersToPmove( node->children[1], pmove_mins, pmove_maxs ); } +static void pfnParticle( float *origin, int color, float life, int zpos, int zvel ) +{ + int v; + + if( !origin ) + { + MsgDev( D_ERROR, "SV_StartParticle: NULL origin. Ignored\n" ); + return; + } + + MSG_WriteByte( &sv.reliable_datagram, svc_particle ); + MSG_WriteVec3Coord( &sv.reliable_datagram, origin ); + MSG_WriteChar( &sv.reliable_datagram, 0 ); // no x-vel + MSG_WriteChar( &sv.reliable_datagram, 0 ); // no y-vel + v = bound( -128, (zpos * zvel) * 16.0f, 127 ); + MSG_WriteChar( &sv.reliable_datagram, v ); // write z-vel + MSG_WriteByte( &sv.reliable_datagram, 1 ); + MSG_WriteByte( &sv.reliable_datagram, color ); + MSG_WriteByte( &sv.reliable_datagram, bound( 0, life * 8, 255 )); +} + static int pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace ) { return PM_TestPlayerPosition( svgame.pmove, pos, ptrace, NULL ); @@ -564,7 +585,7 @@ void SV_InitClientMove( void ) // common utilities svgame.pmove->PM_Info_ValueForKey = Info_ValueForKey; - svgame.pmove->PM_Particle = CL_Particle; // for local system only + svgame.pmove->PM_Particle = pfnParticle; svgame.pmove->PM_TestPlayerPosition = pfnTestPlayerPosition; svgame.pmove->Con_NPrintf = Con_NPrintf; svgame.pmove->Con_DPrintf = Con_DPrintf; diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index 9858c187..e6ebaaa9 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -1118,8 +1118,10 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int { // sounds won't going across transition header.soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS ); +#ifndef XASH_DEDICATED // music not reqiured to save position: it's just continue playing on a next level S_StreamGetCurrentState( header.introTrack, header.mainTrack, &header.trackPosition ); +#endif } // save viewentity to allow camera works after save\restore @@ -2098,8 +2100,10 @@ void SV_SaveGame( const char *pName ) SaveBuildComment( comment, sizeof( comment )); result = SaveGameSlot( savename, comment ); +#ifndef XASH_DEDICATED if( result && !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) CL_HudMessage( "GAMESAVED" ); // defined in titles.txt +#endif } /*