summaryrefslogtreecommitdiff
path: root/game/shared/motd.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/motd.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/motd.cpp')
-rw-r--r--game/shared/motd.cpp281
1 files changed, 281 insertions, 0 deletions
diff --git a/game/shared/motd.cpp b/game/shared/motd.cpp
new file mode 100644
index 0000000..d9a245b
--- /dev/null
+++ b/game/shared/motd.cpp
@@ -0,0 +1,281 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: motd: Handles a list of message of the day entries
+//
+//=============================================================================
+
+#include "cbase.h"
+#include "motd.h"
+#include "schemainitutils.h"
+#include "rtime.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+using namespace GCSDK;
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+CMOTDEntryDefinition::CMOTDEntryDefinition( void )
+{
+ m_pKVMOTD = NULL;
+ m_PostTime = 0;
+ m_ChangedTime = 0;
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+bool CMOTDEntryDefinition::BInitFromKV( KeyValues *pKVMOTD, CUtlVector<CUtlString> *pVecErrors )
+{
+ m_pKVMOTD = pKVMOTD->MakeCopy();
+
+ const char *pszTime = m_pKVMOTD->GetString( "post_time", NULL );
+ m_PostTime = (pszTime && pszTime[0]) ? CRTime::RTime32FromString(pszTime) : 0;
+
+ pszTime = m_pKVMOTD->GetString( "last_changed_time", NULL );
+ m_ChangedTime = (pszTime && pszTime[0]) ? CRTime::RTime32FromString(pszTime) : 0;
+
+ return SCHEMA_INIT_SUCCESS();
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+const char *CMOTDEntryDefinition::GetTitle( ELanguage eLang )
+{
+ if ( m_pKVMOTD )
+ {
+ // See if we have a localised block for the specified language.
+ const char *pszLanguage = GetLanguageShortName( eLang );
+ if ( pszLanguage && pszLanguage[0] )
+ {
+ const char *pszText = m_pKVMOTD->GetString( CFmtStr( "title_%s", pszLanguage ), NULL );
+ if ( pszText && pszText[0] )
+ return pszText;
+ }
+
+ // Fall back to english
+ return m_pKVMOTD->GetString( "title_english", "No Title" );
+ }
+
+ return "No Title";
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+const char *CMOTDEntryDefinition::GetText( ELanguage eLang )
+{
+ if ( m_pKVMOTD )
+ {
+ // See if we have a localised block for the specified language.
+ const char *pszLanguage = GetLanguageShortName( eLang );
+ if ( pszLanguage && pszLanguage[0] )
+ {
+ const char *pszText = m_pKVMOTD->GetString( CFmtStr( "text_%s", pszLanguage ), NULL );
+ if ( pszText && pszText[0] )
+ return pszText;
+ }
+
+ // Fall back to english
+ return m_pKVMOTD->GetString( "text_english", "No text" );
+ }
+
+ return "No text";
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+const char *CMOTDEntryDefinition::GetHeaderTitle( ELanguage eLang )
+{
+ if ( m_pKVMOTD )
+ {
+ // See if we have a localised block for the specified language.
+ const char *pszLanguage = GetLanguageShortName( eLang );
+ if ( pszLanguage && pszLanguage[0] )
+ {
+ const char *pszText = m_pKVMOTD->GetString( CFmtStr( "header_%s", pszLanguage ), NULL );
+ if ( pszText && pszText[0] )
+ return pszText;
+ }
+
+ // Fall back to english
+ return m_pKVMOTD->GetString( "header_english", "News" );
+ }
+
+ return "News";
+}
+
+// Sort by ID
+int MOTDEntriesListLess( const CMOTDEntryDefinition *pLhs, const CMOTDEntryDefinition *pRhs )
+{
+ // This is stupid, sort by the KeyID instead
+ return ( pLhs->GetNameInt() > pRhs->GetNameInt() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Initializes the loot lists section of the schema
+//-----------------------------------------------------------------------------
+bool CMOTDManager::BInitMOTDEntries( KeyValues *pKVMOTDEntries, CUtlVector<CUtlString> *pVecErrors )
+{
+ m_vecMOTDEntries.RemoveAll();
+
+ RTime32 iPrevTime = 0;
+
+ if ( NULL != pKVMOTDEntries )
+ {
+ FOR_EACH_TRUE_SUBKEY( pKVMOTDEntries, pKVEntry )
+ {
+ const char *listName = pKVEntry->GetName();
+
+ SCHEMA_INIT_CHECK( listName != NULL, "All MOTD entries must have titles." );
+
+ int idx = m_vecMOTDEntries.AddToTail();
+ SCHEMA_INIT_SUBSTEP( m_vecMOTDEntries[idx].BInitFromKV( pKVEntry, pVecErrors ) );
+
+ // Make sure the dates all move forward
+ SCHEMA_INIT_CHECK( m_vecMOTDEntries[idx].GetPostTime() > iPrevTime , "MOTD entry '%s' occurs prior to the previous entry.", m_vecMOTDEntries[idx].GetName() );
+ iPrevTime = m_vecMOTDEntries[idx].GetPostTime();
+ }
+ }
+
+ // Then sort all the MOTDs in order of their changed times, so we can easily send them
+ m_vecMOTDEntries.Sort( MOTDEntriesListLess );
+
+ return SCHEMA_INIT_SUCCESS();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the number of MOTD entries we've got after the specified time
+//-----------------------------------------------------------------------------
+int CMOTDManager::GetNumMOTDAfter( RTime32 iTime )
+{
+ FOR_EACH_VEC( m_vecMOTDEntries, i )
+ {
+ if ( m_vecMOTDEntries[i].GetChangedTime() > iTime )
+ {
+ // We've hit the first MOTD entry after this time. All following posts are assumed after.
+ return (m_vecMOTDEntries.Count() - i);
+ }
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Remove all unused MOTD: Save memory and whatever
+//-----------------------------------------------------------------------------
+void CMOTDManager::PurgeUnusedMOTDEntries( KeyValues *pKVMOTDEntries )
+{
+ // Find the latest entry name and remove all others
+ int iLargest = -1;
+ FOR_EACH_VEC_BACK( m_vecMOTDEntries, i )
+ {
+ int iMOTDindex = m_vecMOTDEntries[i].GetNameInt();
+ if ( iMOTDindex > iLargest )
+ {
+ iLargest = iMOTDindex;
+ }
+ }
+
+ FOR_EACH_VEC_BACK( m_vecMOTDEntries, i )
+ {
+ int iMOTDindex = m_vecMOTDEntries[i].GetNameInt();
+ if ( iMOTDindex < iLargest )
+ {
+ if ( pKVMOTDEntries )
+ {
+ KeyValues *pKey = pKVMOTDEntries->FindKey( m_vecMOTDEntries[i].GetName() );
+ if ( pKey )
+ {
+ pKVMOTDEntries->RemoveSubKey( pKey );
+ }
+ }
+ m_vecMOTDEntries.Remove( i );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the definition for the next blog post after the specified time
+//-----------------------------------------------------------------------------
+CMOTDEntryDefinition *CMOTDManager::GetNextMOTDAfter( RTime32 iTime )
+{
+ FOR_EACH_VEC( m_vecMOTDEntries, i )
+ {
+ if ( m_vecMOTDEntries[i].GetChangedTime() > iTime )
+ return &m_vecMOTDEntries[i];
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CMOTDEntryDefinition *CMOTDManager::GetMOTDByIndex( int iIndex )
+{
+ if ( iIndex < 0 || iIndex > m_vecMOTDEntries.Count() )
+ return NULL;
+ return &m_vecMOTDEntries[iIndex];
+}
+
+
+#ifdef GC_DLL
+
+//-----------------------------------------------------------------------------
+// Handle MOTD requests job.
+//-----------------------------------------------------------------------------
+class CGCMOTDRequest : public CGCGameBaseJob
+{
+public:
+ CGCMOTDRequest( CGCGameBase *pGC ) : CGCGameBaseJob( pGC ) { }
+ bool BYieldingRunJobFromMsg( GCSDK::IMsgNetPacket *pNetPacket );
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Responds to requests from the client for the current MOTD list
+//-----------------------------------------------------------------------------
+bool CGCMOTDRequest::BYieldingRunJobFromMsg( IMsgNetPacket *pNetPacket )
+{
+ CGCMsg< MsgGCMOTDRequest_t > msg( pNetPacket );
+ ELanguage eLang = (ELanguage)msg.Body().m_eLanguage;
+ RTime32 iMOTDTime = msg.Body().m_nLastMOTDRequest;
+
+ // Send the response to the client
+ GCSDK::CGCMsg<MsgGCMOTDRequestResponse_t> msg_response( k_EMsgGCMOTDRequestResponse );
+
+ int iEntries = 0;
+ CMOTDEntryDefinition *pMOTD = m_pGCGameBase->GetMOTDManager().GetNextMOTDAfter( iMOTDTime );
+ while ( pMOTD )
+ {
+ // Stuff this MOTD into the message.
+ msg_response.AddStrData( pMOTD->GetName() );
+ msg_response.AddUintData( pMOTD->GetPostTime() );
+ msg_response.AddStrData( pMOTD->GetTitle( eLang ) );
+ msg_response.AddStrData( pMOTD->GetText( eLang ) );
+ msg_response.AddStrData( pMOTD->GetURL() );
+ msg_response.AddStrData( pMOTD->GetImage() );
+ msg_response.AddIntData( pMOTD->GetHeaderType() );
+ msg_response.AddStrData( pMOTD->GetHeaderTitle( eLang ) );
+ msg_response.AddStrData( pMOTD->GetHeaderIcon() );
+ iEntries++;
+
+ // Move on to the next message.
+ iMOTDTime = pMOTD->GetChangedTime();
+ pMOTD = m_pGCGameBase->GetMOTDManager().GetNextMOTDAfter( iMOTDTime );
+ }
+ msg_response.Body().m_nEntries = iEntries;
+
+ GGCEcon()->BSendGCMsgToClient( msg.Hdr().m_ulSteamID, msg_response );
+
+ return true;
+}
+
+GC_REG_JOB( CGCGameBase, CGCMOTDRequest, "CGCMOTDRequest", k_EMsgGCMOTDRequest, k_EServerTypeGC );
+
+#endif // GC_DLL