Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
7.2 KiB

  1. //====== Copyright (c), Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: motd: Handles a list of message of the day entries
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "motd.h"
  8. #include "schemainitutils.h"
  9. #include "rtime.h"
  10. using namespace GCSDK;
  11. //-----------------------------------------------------------------------------
  12. //
  13. //-----------------------------------------------------------------------------
  14. CMOTDEntryDefinition::CMOTDEntryDefinition( void )
  15. {
  16. m_pKVMOTD = NULL;
  17. m_PostTime = 0;
  18. m_ChangedTime = 0;
  19. }
  20. //-----------------------------------------------------------------------------
  21. //
  22. //-----------------------------------------------------------------------------
  23. bool CMOTDEntryDefinition::BInitFromKV( KeyValues *pKVMOTD, CUtlVector<CUtlString> *pVecErrors )
  24. {
  25. m_pKVMOTD = pKVMOTD->MakeCopy();
  26. const char *pszTime = m_pKVMOTD->GetString( "post_time", NULL );
  27. m_PostTime = (pszTime && pszTime[0]) ? CRTime::RTime32FromString(pszTime) : 0;
  28. pszTime = m_pKVMOTD->GetString( "last_changed_time", NULL );
  29. m_ChangedTime = (pszTime && pszTime[0]) ? CRTime::RTime32FromString(pszTime) : 0;
  30. return SCHEMA_INIT_SUCCESS();
  31. }
  32. //-----------------------------------------------------------------------------
  33. //
  34. //-----------------------------------------------------------------------------
  35. const char *CMOTDEntryDefinition::GetTitle( ELanguage eLang )
  36. {
  37. if ( m_pKVMOTD )
  38. {
  39. // See if we have a localised block for the specified language.
  40. const char *pszLanguage = GetLanguageShortName( eLang );
  41. if ( pszLanguage && pszLanguage[0] )
  42. {
  43. const char *pszText = m_pKVMOTD->GetString( CFmtStr( "title_%s", pszLanguage ), NULL );
  44. if ( pszText && pszText[0] )
  45. return pszText;
  46. }
  47. // Fall back to english
  48. return m_pKVMOTD->GetString( "title_english", "No Title" );
  49. }
  50. return "No Title";
  51. }
  52. //-----------------------------------------------------------------------------
  53. //
  54. //-----------------------------------------------------------------------------
  55. const char *CMOTDEntryDefinition::GetText( ELanguage eLang )
  56. {
  57. if ( m_pKVMOTD )
  58. {
  59. // See if we have a localised block for the specified language.
  60. const char *pszLanguage = GetLanguageShortName( eLang );
  61. if ( pszLanguage && pszLanguage[0] )
  62. {
  63. const char *pszText = m_pKVMOTD->GetString( CFmtStr( "text_%s", pszLanguage ), NULL );
  64. if ( pszText && pszText[0] )
  65. return pszText;
  66. }
  67. // Fall back to english
  68. return m_pKVMOTD->GetString( "text_english", "No text" );
  69. }
  70. return "No text";
  71. }
  72. // Sorts the MOTD entries in order of the time they last changed
  73. int MOTDEntriesListLess( const CMOTDEntryDefinition *pLhs, const CMOTDEntryDefinition *pRhs )
  74. {
  75. #ifdef TF_GC_DLL
  76. // The GC sorts by changetime
  77. return ( pLhs->GetChangedTime() > pRhs->GetChangedTime() );
  78. #else
  79. // The client sorts by post time
  80. return ( pLhs->GetPostTime() > pRhs->GetPostTime() );
  81. #endif
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose: Initializes the loot lists section of the schema
  85. //-----------------------------------------------------------------------------
  86. bool CMOTDManager::BInitMOTDEntries( KeyValues *pKVMOTDEntries, CUtlVector<CUtlString> *pVecErrors )
  87. {
  88. m_vecMOTDEntries.RemoveAll();
  89. RTime32 iPrevTime = 0;
  90. if ( NULL != pKVMOTDEntries )
  91. {
  92. FOR_EACH_TRUE_SUBKEY( pKVMOTDEntries, pKVEntry )
  93. {
  94. const char *listName = pKVEntry->GetName();
  95. SCHEMA_INIT_CHECK( listName != NULL, CFmtStr( "All MOTD entries must have titles.") );
  96. int idx = m_vecMOTDEntries.AddToTail();
  97. SCHEMA_INIT_SUBSTEP( m_vecMOTDEntries[idx].BInitFromKV( pKVEntry, pVecErrors ) );
  98. // Make sure the dates all move forward
  99. SCHEMA_INIT_CHECK( m_vecMOTDEntries[idx].GetPostTime() > iPrevTime , CFmtStr( "MOTD entry '%s' occurs prior to the previous entry.", m_vecMOTDEntries[idx].GetName() ) );
  100. iPrevTime = m_vecMOTDEntries[idx].GetPostTime();
  101. }
  102. }
  103. // Then sort all the MOTDs in order of their changed times, so we can easily send them
  104. m_vecMOTDEntries.Sort( MOTDEntriesListLess );
  105. return SCHEMA_INIT_SUCCESS();
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Purpose: Returns the number of MOTD entries we've got after the specified time
  109. //-----------------------------------------------------------------------------
  110. int CMOTDManager::GetNumMOTDAfter( RTime32 iTime )
  111. {
  112. FOR_EACH_VEC( m_vecMOTDEntries, i )
  113. {
  114. if ( m_vecMOTDEntries[i].GetChangedTime() > iTime )
  115. {
  116. // We've hit the first MOTD entry after this time. All following posts are assumed after.
  117. return (m_vecMOTDEntries.Count() - i);
  118. }
  119. }
  120. return 0;
  121. }
  122. //-----------------------------------------------------------------------------
  123. // Purpose: Returns the definition for the next blog post after the specified time
  124. //-----------------------------------------------------------------------------
  125. CMOTDEntryDefinition *CMOTDManager::GetNextMOTDAfter( RTime32 iTime )
  126. {
  127. FOR_EACH_VEC( m_vecMOTDEntries, i )
  128. {
  129. if ( m_vecMOTDEntries[i].GetChangedTime() > iTime )
  130. return &m_vecMOTDEntries[i];
  131. }
  132. return NULL;
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Purpose:
  136. //-----------------------------------------------------------------------------
  137. CMOTDEntryDefinition *CMOTDManager::GetMOTDByIndex( int iIndex )
  138. {
  139. if ( iIndex < 0 || iIndex > m_vecMOTDEntries.Count() )
  140. return NULL;
  141. return &m_vecMOTDEntries[iIndex];
  142. }
  143. #ifdef TF_GC_DLL
  144. //-----------------------------------------------------------------------------
  145. // Handle MOTD requests job.
  146. //-----------------------------------------------------------------------------
  147. class CGCMOTDRequest : public CGCGameBaseJob
  148. {
  149. public:
  150. CGCMOTDRequest( CGCGameBase *pGC ) : CGCGameBaseJob( pGC ) { }
  151. bool BYieldingRunJobFromMsg( GCSDK::IMsgNetPacket *pNetPacket );
  152. };
  153. //-----------------------------------------------------------------------------
  154. // Purpose: Responds to requests from the client for the current MOTD list
  155. //-----------------------------------------------------------------------------
  156. bool CGCMOTDRequest::BYieldingRunJobFromMsg( IMsgNetPacket *pNetPacket )
  157. {
  158. CGCMsg< MsgGCMOTDRequest_t > msg( pNetPacket );
  159. ELanguage eLang = (ELanguage)msg.Body().m_eLanguage;
  160. RTime32 iMOTDTime = msg.Body().m_nLastMOTDRequest;
  161. // Send the response to the client
  162. GCSDK::CGCMsg<MsgGCMOTDRequestResponse_t> msg_response( k_EMsgGCMOTDRequestResponse );
  163. int iEntries = 0;
  164. CMOTDEntryDefinition *pMOTD = m_pGCGameBase->GetMOTDManager().GetNextMOTDAfter( iMOTDTime );
  165. while ( pMOTD )
  166. {
  167. // Stuff this MOTD into the message.
  168. msg_response.AddStrData( pMOTD->GetName() );
  169. msg_response.AddUintData( pMOTD->GetPostTime() );
  170. msg_response.AddStrData( pMOTD->GetTitle( eLang ) );
  171. msg_response.AddStrData( pMOTD->GetText( eLang ) );
  172. msg_response.AddStrData( pMOTD->GetURL() );
  173. iEntries++;
  174. // Move on to the next message.
  175. iMOTDTime = pMOTD->GetChangedTime();
  176. pMOTD = m_pGCGameBase->GetMOTDManager().GetNextMOTDAfter( iMOTDTime );
  177. }
  178. msg_response.Body().m_nEntries = iEntries;
  179. GGCTF()->BSendGCMsgToClient( msg.Hdr().m_ulSteamID, msg_response );
  180. return true;
  181. }
  182. GC_REG_JOB( CGCGameBase, CGCMOTDRequest, "CGCMOTDRequest", k_EMsgGCMOTDRequest, k_EServerTypeGC );
  183. #endif // TF_GC_DLL