From cf8d239dbe92720a24e8968c0b00ec2d4eec060f Mon Sep 17 00:00:00 2001 From: Christopher Schwarz Date: Mon, 12 Oct 2009 19:17:00 +0000 Subject: * (bug 4295) Add an option to view Tremulous news to the main menu --- src/client/cl_main.c | 6 ++-- src/client/cl_ui.c | 51 +++++++++++++++++++++++++++++++++ src/client/client.h | 2 ++ src/qcommon/q_shared.h | 1 + src/ui/ui_local.h | 16 +++++++++++ src/ui/ui_main.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/ui/ui_public.h | 1 + src/ui/ui_syscalls.asm | 1 + src/ui/ui_syscalls.c | 5 ++++ 9 files changed, 159 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 09c42e63..0aafa529 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -1869,11 +1869,13 @@ void CL_DownloadsComplete( void ) { CL_cURL_Shutdown(); if( clc.cURLDisconnected ) { if(clc.downloadRestart) { - FS_Restart(clc.checksumFeed); + if( !clc.activeCURLNotGameRelated ) + FS_Restart(clc.checksumFeed); clc.downloadRestart = qfalse; } clc.cURLDisconnected = qfalse; - CL_Reconnect_f(); + if( !clc.activeCURLNotGameRelated ) + CL_Reconnect_f(); return; } } diff --git a/src/client/cl_ui.c b/src/client/cl_ui.c index 4c1ff9ed..caf55ef0 100644 --- a/src/client/cl_ui.c +++ b/src/client/cl_ui.c @@ -81,6 +81,52 @@ void LAN_SaveServersToCache( void ) { FS_FCloseFile(fileOut); } +/* +==================== +GetNews +==================== +*/ +qboolean GetNews( qboolean begin ) +{ +#ifdef USE_CURL + qboolean finished = qfalse; + fileHandle_t fileIn; + int readSize; + + if( begin ) { // if not already using curl, start the download + if( !clc.downloadCURLM ) { + if(!CL_cURL_Init()) { + Cvar_Set( "cl_newsString", "^1Error: Could not load cURL library" ); + return qtrue; + } + clc.activeCURLNotGameRelated = qtrue; + CL_cURL_BeginDownload("news.dat", + "http://tremulous.net/clientnews.txt"); + return qfalse; + } + } + + if ( !clc.downloadCURLM && FS_SV_FOpenFileRead("news.dat", &fileIn)) { + readSize = FS_Read(clc.newsString, sizeof( clc.newsString ), fileIn); + FS_FCloseFile(fileIn); + clc.newsString[ readSize ] = '\0'; + if( readSize > 0 ) { + finished = qtrue; + clc.cURLUsed = qfalse; + CL_cURL_Shutdown(); + clc.activeCURLNotGameRelated = qfalse; + } + } + if( !finished ) + strcpy( clc.newsString, "Retrieving..." ); +#else + Cvar_Set( "cl_newsString", + "^1You must compile your client with CURL support to use this feature" ); + return qtrue; +#endif + Cvar_Set( "cl_newsString", clc.newsString ); + return finished; +} /* ==================== @@ -907,6 +953,9 @@ intptr_t CL_UISystemCalls( intptr_t *args ) { case UI_LAN_SERVERSTATUS: return LAN_GetServerStatus( VMA(1), VMA(2), args[3] ); + case UI_GETNEWS: + return GetNews( args[1] ); + case UI_LAN_COMPARESERVERS: return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] ); @@ -1059,6 +1108,8 @@ void CL_InitUI( void ) { // reset any CVAR_CHEAT cvars registered by ui if ( !clc.demoplaying && !cl_connectedToCheatServer ) Cvar_SetCheatState(); + + clc.newsString[ 0 ] = '\0'; } /* diff --git a/src/client/client.h b/src/client/client.h index 206d5dd9..a6d61950 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -204,6 +204,7 @@ typedef struct { char downloadURL[MAX_OSPATH]; CURL *downloadCURL; CURLM *downloadCURLM; + qboolean activeCURLNotGameRelated; #endif /* USE_CURL */ int sv_allowDownload; char sv_dlURL[MAX_CVAR_VALUE_STRING]; @@ -213,6 +214,7 @@ typedef struct { int downloadSize; // how many bytes we got char downloadList[MAX_INFO_STRING]; // list of paks we need to download qboolean downloadRestart; // if true, we need to do another FS_Restart because we downloaded a pak + char newsString[ MAX_NEWS_STRING ]; // demo information char demoName[MAX_QPATH]; diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h index 34f3e471..59c5b91d 100644 --- a/src/qcommon/q_shared.h +++ b/src/qcommon/q_shared.h @@ -204,6 +204,7 @@ typedef int clipHandle_t; #define BIG_INFO_KEY 8192 #define BIG_INFO_VALUE 8192 +#define MAX_NEWS_STRING 10000 #define MAX_QPATH 64 // max length of a quake game pathname #ifdef PATH_MAX diff --git a/src/ui/ui_local.h b/src/ui/ui_local.h index 241cb6d8..1f7ecf40 100644 --- a/src/ui/ui_local.h +++ b/src/ui/ui_local.h @@ -41,6 +41,7 @@ int UI_AdjustTimeByGame( int time ); void UI_ClearScores( void ); void UI_LoadArenas( void ); void UI_ServerInfo( void ); +void UI_UpdateNews( qboolean ); void UI_RegisterCvars( void ); void UI_UpdateCvars( void ); @@ -53,6 +54,8 @@ void UI_DrawConnectScreen( qboolean overlay ); #define MAX_DISPLAY_SERVERS 2048 #define MAX_SERVERSTATUS_LINES 128 #define MAX_SERVERSTATUS_TEXT 1024 +#define MAX_NEWS_LINES 50 +#define MAX_NEWS_LINEWIDTH 85 #define MAX_FOUNDPLAYER_SERVERS 16 #define MAX_MODS 64 #define MAX_DEMOS 256 @@ -146,6 +149,15 @@ typedef struct } serverStatusInfo_t; +typedef struct +{ + char text[MAX_NEWS_LINES][MAX_NEWS_LINEWIDTH]; + int numLines; + qboolean refreshActive; + int refreshtime; +} +newsInfo_t; + typedef struct { const char *modName; @@ -262,6 +274,9 @@ typedef struct serverStatus_t serverStatus; + // for showing the game news window + newsInfo_t newsInfo; + // for the showing the status of a server char serverStatusAddress[MAX_ADDRESSLENGTH]; serverStatusInfo_t serverStatusInfo; @@ -365,6 +380,7 @@ int trap_LAN_AddServer( int source, const char *name, const char *addr ); void trap_LAN_RemoveServer( int source, const char *addr ); void trap_LAN_ResetPings( int n ); int trap_LAN_ServerStatus( const char *serverAddress, char *serverStatus, int maxLen ); +qboolean trap_GetNews( qboolean force ); int trap_LAN_CompareServers( int source, int sortKey, int sortDir, int s1, int s2 ); int trap_MemoryRemaining( void ); void trap_R_RegisterFont( const char *pFontname, int pointSize, fontInfo_t *font ); diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c index 3eb63c5d..ab96fa3e 100644 --- a/src/ui/ui_main.c +++ b/src/ui/ui_main.c @@ -1138,6 +1138,8 @@ void UI_Refresh( int realtime ) UI_BuildServerStatus( qfalse ); // refresh find player list UI_BuildFindPlayerList( qfalse ); + // refresh news + UI_UpdateNews( qfalse ); } // draw cursor @@ -2856,6 +2858,8 @@ static void UI_RunMenuScript( char **args ) } else if( Q_stricmp( name, "loadServerInfo" ) == 0 ) UI_ServerInfo(); + else if( Q_stricmp( name, "getNews" ) == 0 ) + UI_UpdateNews( qtrue ); else if( Q_stricmp( name, "saveControls" ) == 0 ) Controls_SetConfig( qtrue ); else if( Q_stricmp( name, "loadControls" ) == 0 ) @@ -3356,6 +3360,8 @@ static int UI_FeederCount( float feederID ) return uiInfo.serverStatus.numFeaturedServers; else if( feederID == FEEDER_SERVERSTATUS ) return uiInfo.serverStatusInfo.numLines; + else if( feederID == FEEDER_NEWS ) + return uiInfo.newsInfo.numLines; else if( feederID == FEEDER_FINDPLAYER ) return uiInfo.numFoundPlayerServers; else if( feederID == FEEDER_PLAYER_LIST ) @@ -3524,6 +3530,13 @@ static const char *UI_FeederItemText( float feederID, int index, int column, qha return uiInfo.serverStatusInfo.lines[index][column]; } } + else if( feederID == FEEDER_NEWS ) + { + if( index >= 0 && index < uiInfo.newsInfo.numLines ) + { + return uiInfo.newsInfo.text[index]; + } + } else if( feederID == FEEDER_FINDPLAYER ) { if( index >= 0 && index < uiInfo.numFoundPlayerServers ) @@ -4473,3 +4486,68 @@ void UI_UpdateCvars( void ) for( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) trap_Cvar_Update( cv->vmCvar ); } + +/* +================= +UI_UpdateNews +================= +*/ +void UI_UpdateNews( qboolean begin ) +{ + char newsString[ MAX_NEWS_STRING ]; + const char *c; + const char *wrapped; + int line = 0; + int linePos = 0; + qboolean finished; + + if( begin && !uiInfo.newsInfo.refreshActive ) { + uiInfo.newsInfo.refreshtime = uiInfo.uiDC.realTime + 10000; + uiInfo.newsInfo.refreshActive = qtrue; + } + else if( !uiInfo.newsInfo.refreshActive ) // do nothing + return; + else if( uiInfo.uiDC.realTime > uiInfo.newsInfo.refreshtime ) { + strcpy( uiInfo.newsInfo.text[ 0 ], + "^1Error: Timed out while contacting the server."); + uiInfo.newsInfo.numLines = 1; + return; + } + + // start the news fetching + finished = trap_GetNews( begin ); + + // parse what comes back. Parse newlines and otherwise chop when necessary + trap_Cvar_VariableStringBuffer( "cl_newsString", newsString, + sizeof( newsString ) ); + + wrapped = Item_Text_Wrap( newsString, .25, 300 ); + + for( c = wrapped; *c != '\0'; ++c ) { + if( linePos == (MAX_NEWS_LINEWIDTH - 1) || *c == '\n' ) { + uiInfo.newsInfo.text[ line ][ linePos ] = '\0'; + + if( line == ( MAX_NEWS_LINES - 1 ) ) + break; + + linePos = 0; + line++; + + if( *c != '\n' ) { + uiInfo.newsInfo.text[ line ][ linePos ] = *c; + linePos++; + } + } else if( isprint( *c ) ) { + uiInfo.newsInfo.text[ line ][ linePos ] = *c; + linePos++; + } + } + + uiInfo.newsInfo.text[ line ] [linePos ] = '\0'; + uiInfo.newsInfo.numLines = line + 1; + + if( finished ) + uiInfo.newsInfo.refreshActive = qfalse; + +} + diff --git a/src/ui/ui_public.h b/src/ui/ui_public.h index 26c6fbd4..bcaf3d5c 100644 --- a/src/ui/ui_public.h +++ b/src/ui/ui_public.h @@ -126,6 +126,7 @@ typedef enum UI_PARSE_FREE_SOURCE, UI_PARSE_READ_TOKEN, UI_PARSE_SOURCE_FILE_AND_LINE, + UI_GETNEWS, UI_MEMSET = 100, UI_MEMCPY, diff --git a/src/ui/ui_syscalls.asm b/src/ui/ui_syscalls.asm index fb37c736..0880d419 100644 --- a/src/ui/ui_syscalls.asm +++ b/src/ui/ui_syscalls.asm @@ -86,6 +86,7 @@ equ trap_Parse_LoadSource -82 equ trap_Parse_FreeSource -83 equ trap_Parse_ReadToken -84 equ trap_Parse_SourceFileAndLine -85 +equ trap_GetNews -86 equ memset -101 diff --git a/src/ui/ui_syscalls.c b/src/ui/ui_syscalls.c index f1d252cd..29938149 100644 --- a/src/ui/ui_syscalls.c +++ b/src/ui/ui_syscalls.c @@ -322,6 +322,11 @@ int trap_LAN_ServerStatus( const char *serverAddress, char *serverStatus, int ma return syscall( UI_LAN_SERVERSTATUS, serverAddress, serverStatus, maxLen ); } +qboolean trap_GetNews( qboolean force ) +{ + return syscall( UI_GETNEWS, force ); +} + void trap_LAN_SaveCachedServers( void ) { syscall( UI_LAN_SAVECACHEDSERVERS ); -- cgit