mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-15 13:16:58 +00:00
1
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user