summaryrefslogtreecommitdiff
path: root/game/shared/tf/tf_gc_shared.h
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/tf/tf_gc_shared.h')
-rw-r--r--game/shared/tf/tf_gc_shared.h162
1 files changed, 162 insertions, 0 deletions
diff --git a/game/shared/tf/tf_gc_shared.h b/game/shared/tf/tf_gc_shared.h
new file mode 100644
index 0000000..bcbf7ec
--- /dev/null
+++ b/game/shared/tf/tf_gc_shared.h
@@ -0,0 +1,162 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#ifndef _TF_GC_SHARED_H
+#define _TF_GC_SHARED_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "gcsdk/msgprotobuf.h"
+
+using namespace GCSDK;
+
+#define MMLog(...) do { Log( __VA_ARGS__ ); } while(false)
+
+//-----------------------------------------------------------------------------
+// ReliableMessage - A message/job class that retry until confirmed, and be sent
+// In order with other such messages.
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Check for pending messages
+//-----------------------------------------------------------------------------
+static bool BPendingReliableMessages();
+
+//-----------------------------------------------------------------------------
+GCSDK::CGCClientJob *s_pCurrentConfirmJob = NULL;
+CUtlQueue< GCSDK::CGCClientJob * > s_queuePendingConfirmJobs;
+
+template < typename RELIABLE_MSG_CLASS, typename MSG_TYPE, ETFGCMsg E_MSG_TYPE, typename REPLY_TYPE, ETFGCMsg E_REPLY_TYPE>
+class CJobReliableMessageBase : public GCSDK::CGCClientJob
+{
+public:
+ typedef CProtoBufMsg< MSG_TYPE > Msg_t;
+ typedef CProtoBufMsg< REPLY_TYPE > Reply_t;
+
+ CJobReliableMessageBase()
+ : GCSDK::CGCClientJob( GCClientSystem()->GetGCClient() )
+ , m_msg( E_MSG_TYPE )
+ , m_msgReply()
+ {}
+
+ Msg_t &Msg() { return m_msg; }
+ void Enqueue()
+ {
+ static_cast<RELIABLE_MSG_CLASS *>(this)->InitDebugString( m_strDebug );
+ MMLog( "[SendMsgUntilConfirmed] %s queued for %s\n", GetMsgName(), DebugString() );
+
+ if ( !s_pCurrentConfirmJob )
+ {
+ s_pCurrentConfirmJob = this;
+ this->StartJobDelayed( NULL );
+ }
+ else
+ {
+ // Queue, confirm jobs will kick next in queue as necessary
+ s_queuePendingConfirmJobs.Insert( this );
+ }
+ }
+
+ virtual bool BYieldingRunJob( void *pvStartParam )
+ {
+ Assert( s_pCurrentConfirmJob == this );
+ bool bRet = BYieldingRunJobInternal();
+
+ if ( s_queuePendingConfirmJobs.Count() )
+ {
+ // Kick off next job
+ s_pCurrentConfirmJob = s_queuePendingConfirmJobs.RemoveAtHead();
+ s_pCurrentConfirmJob->StartJob( NULL );
+ }
+ else
+ {
+ s_pCurrentConfirmJob = NULL;
+ }
+
+ return bRet;
+ }
+
+ bool BYieldingRunJobInternal()
+ {
+ MMLog( "[SendMsgUntilConfirmed] %s started for %s\n", GetMsgName(), DebugString() );
+
+ // Trigger OnPrepare
+ static_cast<RELIABLE_MSG_CLASS *>(this)->OnPrepare();
+
+ for ( ;; )
+ {
+ BYieldingWaitOneFrame();
+
+ // Create and load the message
+ // continuously attempt to send the message to the GC
+ BYldSendMessageAndGetReply_t result = BYldSendMessageAndGetReplyEx( m_msg, 30, &m_msgReply, E_REPLY_TYPE );
+
+ switch ( result )
+ {
+ case BYLDREPLY_SUCCESS:
+ MMLog( "[SendMsgUntilConfirmed] %s successfully sent for %s\n",
+ GetMsgName(), DebugString() );
+ // Trigger OnReply
+ static_cast<RELIABLE_MSG_CLASS *>(this)->OnReply( m_msgReply );
+ return true;
+ case BYLDREPLY_SEND_FAILED:
+ MMLog( "[SendMsgUntilConfirmed] %s send FAILED for %s -- retrying\n",
+ GetMsgName(), DebugString() );
+ break;
+ case BYLDREPLY_TIMEOUT:
+ MMLog( "[SendMsgUntilConfirmed] %s send TIMEOUT for %s -- retrying\n",
+ GetMsgName(), DebugString() );
+ break;
+ case BYLDREPLY_MSG_TYPE_MISMATCH:
+ MMLog( "[SendMsgUntilConfirmed] %s send TYPE MISMATCH for %s\n",
+ GetMsgName(), DebugString() );
+ Assert( !"Mismatched response type in reliable message" );
+ return true;
+ }
+ }
+ }
+
+protected:
+ // Overrides
+
+ // Must be overridden by reliable message implementers. Debug string is e.g. "Match 12345, Lobby 4"
+ void InitDebugString( CUtlString &debugStr ) {}
+ const char *MsgName() { return "<unknown>"; }
+
+ // Optionally overridden
+ void OnReply( Reply_t &msgReply ) {}
+ // Called before sending, after previous messages in queue have flushed
+ void OnPrepare() {}
+
+private:
+ const char *DebugString() { return m_strDebug.Get(); }
+
+ // Forward to override
+ const char *GetMsgName() { return static_cast<RELIABLE_MSG_CLASS *>(this)->MsgName(); }
+
+ Msg_t m_msg;
+ Reply_t m_msgReply;
+ CUtlString m_strDebug;
+
+ void _static_asserts() {
+ // Ensure we passed an override and provided provided these
+#if __cplusplus >= 201103L && !defined ( OSX ) // (Don't have time to figure out what criteria the OS X toolchain has to not blow this)
+ static_assert( std::is_base_of< decltype( *this ), RELIABLE_MSG_CLASS >::value,
+ "RELIABLE_MSG_CLASS Must be an override of this base" );
+ static_assert( !std::is_same< decltype( &(decltype( *this )::InitDebugString) ),
+ decltype( &RELIABLE_MSG_CLASS::InitDebugString ) >::value && \
+ !std::is_same< decltype( &(decltype( *this )::MsgName) ),
+ decltype( &RELIABLE_MSG_CLASS::MsgName ) >::value,
+ "RELIABLE_MSG_CLASS class must override DebugString and MsgName" );
+#endif // __cplusplus >= 201103L && !defined ( OSX )
+ }
+};
+
+static bool BPendingReliableMessages()
+{
+ Assert( !s_queuePendingConfirmJobs.Count() || s_pCurrentConfirmJob );
+ return !!s_pCurrentConfirmJob || s_queuePendingConfirmJobs.Count();
+}
+
+
+#endif // _TF_GC_SHARED_H
+