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.
814 lines
21 KiB
814 lines
21 KiB
14 years ago
|
/*==LICENSE==*
|
||
|
|
||
|
CyanWorlds.com Engine - MMOG client, server and tools
|
||
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||
|
or by snail mail at:
|
||
|
Cyan Worlds, Inc.
|
||
|
14617 N Newport Hwy
|
||
|
Mead, WA 99021
|
||
|
|
||
|
*==LICENSE==*/
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* $/Plasma20/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
#include "../Pch.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
// This file excluded from pre-compiled header because it is auto-generated by the build server.
|
||
|
#include "pnNetBase/pnNbGameKey.hpp"
|
||
|
|
||
|
namespace Ngl { namespace Game {
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Private
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
struct CliGmConn : AtomicRef {
|
||
|
LINK(CliGmConn) link;
|
||
|
|
||
|
CCritSect critsect;
|
||
|
AsyncSocket sock;
|
||
|
AsyncCancelId cancelId;
|
||
|
NetCli * cli;
|
||
|
NetAddress addr;
|
||
|
unsigned seq;
|
||
|
bool abandoned;
|
||
|
|
||
|
// ping
|
||
|
AsyncTimer * pingTimer;
|
||
|
unsigned pingSendTimeMs;
|
||
|
unsigned lastHeardTimeMs;
|
||
|
|
||
|
CliGmConn ();
|
||
|
~CliGmConn ();
|
||
|
|
||
|
void Send (const unsigned_ptr fields[], unsigned count);
|
||
|
};
|
||
|
|
||
|
|
||
|
//============================================================================
|
||
|
// JoinAgeRequestTrans
|
||
|
//============================================================================
|
||
|
struct JoinAgeRequestTrans : NetGameTrans {
|
||
|
FNetCliGameJoinAgeRequestCallback m_callback;
|
||
|
void * m_param;
|
||
|
// sent
|
||
|
unsigned m_ageMcpId;
|
||
|
Uuid m_accountUuid;
|
||
|
unsigned m_playerInt;
|
||
|
|
||
|
JoinAgeRequestTrans (
|
||
|
unsigned ageMcpId,
|
||
|
const Uuid & accountUuid,
|
||
|
unsigned playerInt,
|
||
|
FNetCliGameJoinAgeRequestCallback callback,
|
||
|
void * param
|
||
|
);
|
||
|
|
||
|
bool Send ();
|
||
|
void Post ();
|
||
|
bool Recv (
|
||
|
const byte msg[],
|
||
|
unsigned bytes
|
||
|
);
|
||
|
};
|
||
|
|
||
|
//============================================================================
|
||
|
// RcvdPropagatedBufferTrans
|
||
|
//============================================================================
|
||
|
struct RcvdPropagatedBufferTrans : NetNotifyTrans {
|
||
|
|
||
|
unsigned bufferType;
|
||
|
unsigned bufferBytes;
|
||
|
byte * bufferData;
|
||
|
|
||
|
RcvdPropagatedBufferTrans () : NetNotifyTrans(kGmRcvdPropagatedBufferTrans) {}
|
||
|
~RcvdPropagatedBufferTrans ();
|
||
|
void Post ();
|
||
|
};
|
||
|
|
||
|
//============================================================================
|
||
|
// RcvdGameMgrMsgTrans
|
||
|
//============================================================================
|
||
|
struct RcvdGameMgrMsgTrans : NetNotifyTrans {
|
||
|
|
||
|
unsigned bufferBytes;
|
||
|
byte * bufferData;
|
||
|
|
||
|
RcvdGameMgrMsgTrans () : NetNotifyTrans(kGmRcvdGameMgrMsgTrans) {}
|
||
|
~RcvdGameMgrMsgTrans ();
|
||
|
void Post ();
|
||
|
};
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Private data
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
enum {
|
||
|
kPerfConnCount,
|
||
|
kPingDisabled,
|
||
|
kNumPerf
|
||
|
};
|
||
|
|
||
|
static bool s_running;
|
||
|
static CCritSect s_critsect;
|
||
|
static LISTDECL(CliGmConn, link) s_conns;
|
||
|
static CliGmConn * s_active;
|
||
|
static FNetCliGameRecvBufferHandler s_bufHandler;
|
||
|
static FNetCliGameRecvGameMgrMsgHandler s_gameMgrMsgHandler;
|
||
|
static long s_perf[kNumPerf];
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Internal functions
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//===========================================================================
|
||
|
static unsigned GetNonZeroTimeMs () {
|
||
|
if (unsigned ms = TimeGetMs())
|
||
|
return ms;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static CliGmConn * GetConnIncRef_CS (const char tag[]) {
|
||
|
if (CliGmConn * conn = s_active)
|
||
|
if (conn->cli) {
|
||
|
conn->IncRef(tag);
|
||
|
return conn;
|
||
|
}
|
||
|
return nil;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static CliGmConn * GetConnIncRef (const char tag[]) {
|
||
|
CliGmConn * conn;
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
conn = GetConnIncRef_CS(tag);
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
return conn;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static void UnlinkAndAbandonConn_CS (CliGmConn * conn) {
|
||
|
s_conns.Unlink(conn);
|
||
|
conn->abandoned = true;
|
||
|
if (conn->cancelId) {
|
||
|
AsyncSocketConnectCancel(nil, conn->cancelId);
|
||
|
conn->cancelId = 0;
|
||
|
}
|
||
|
else if (conn->sock) {
|
||
|
AsyncSocketDisconnect(conn->sock, true);
|
||
|
}
|
||
|
else {
|
||
|
conn->DecRef("Lifetime");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static bool ConnEncrypt (ENetError error, void * param) {
|
||
|
CliGmConn * conn = (CliGmConn *) param;
|
||
|
|
||
|
if (IS_NET_SUCCESS(error)) {
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
SWAP(s_active, conn);
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
}
|
||
|
|
||
|
return IS_NET_SUCCESS(error);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static void NotifyConnSocketConnect (CliGmConn * conn) {
|
||
|
|
||
|
conn->TransferRef("Connecting", "Connected");
|
||
|
conn->cli = NetCliConnectAccept(
|
||
|
conn->sock,
|
||
|
kNetProtocolCli2Game,
|
||
|
true,
|
||
|
ConnEncrypt,
|
||
|
0,
|
||
|
nil,
|
||
|
conn
|
||
|
);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static void NotifyConnSocketConnectFailed (CliGmConn * conn) {
|
||
|
bool notify;
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
conn->cancelId = 0;
|
||
|
s_conns.Unlink(conn);
|
||
|
|
||
|
notify
|
||
|
= s_running
|
||
|
&& !conn->abandoned
|
||
|
&& (!s_active || conn == s_active);
|
||
|
|
||
|
if (conn == s_active)
|
||
|
s_active = nil;
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
|
||
|
NetTransCancelByConnId(conn->seq, kNetErrTimeout);
|
||
|
conn->DecRef("Connecting");
|
||
|
conn->DecRef("Lifetime");
|
||
|
|
||
|
if (notify)
|
||
|
ReportNetError(kNetProtocolCli2Game, kNetErrConnectFailed);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static void NotifyConnSocketDisconnect (CliGmConn * conn) {
|
||
|
|
||
|
bool notify;
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
s_conns.Unlink(conn);
|
||
|
|
||
|
notify
|
||
|
= s_running
|
||
|
&& !conn->abandoned
|
||
|
&& (!s_active || conn == s_active);
|
||
|
|
||
|
if (conn == s_active)
|
||
|
s_active = nil;
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
|
||
|
// Cancel all transactions in process on this connection.
|
||
|
NetTransCancelByConnId(conn->seq, kNetErrTimeout);
|
||
|
conn->DecRef("Connected");
|
||
|
conn->DecRef("Lifetime");
|
||
|
|
||
|
if (notify)
|
||
|
ReportNetError(kNetProtocolCli2Game, kNetErrDisconnected);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static bool NotifyConnSocketRead (CliGmConn * conn, AsyncNotifySocketRead * read) {
|
||
|
// TODO: Only dispatch messages from the active game server
|
||
|
conn->lastHeardTimeMs = GetNonZeroTimeMs();
|
||
|
bool result = NetCliDispatch(conn->cli, read->buffer, read->bytes, nil);
|
||
|
read->bytesProcessed += read->bytes;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static bool SocketNotifyCallback (
|
||
|
AsyncSocket sock,
|
||
|
EAsyncNotifySocket code,
|
||
|
AsyncNotifySocket * notify,
|
||
|
void ** userState
|
||
|
) {
|
||
|
bool result = true;
|
||
|
CliGmConn * conn;
|
||
|
|
||
|
switch (code) {
|
||
|
case kNotifySocketConnectSuccess:
|
||
|
conn = (CliGmConn *) notify->param;
|
||
|
*userState = conn;
|
||
|
conn->TransferRef("Connecting", "Connected");
|
||
|
bool abandoned;
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
conn->sock = sock;
|
||
|
conn->cancelId = 0;
|
||
|
abandoned = conn->abandoned;
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
if (abandoned)
|
||
|
AsyncSocketDisconnect(sock, true);
|
||
|
else
|
||
|
NotifyConnSocketConnect(conn);
|
||
|
break;
|
||
|
|
||
|
case kNotifySocketConnectFailed:
|
||
|
conn = (CliGmConn *) notify->param;
|
||
|
NotifyConnSocketConnectFailed(conn);
|
||
|
break;
|
||
|
|
||
|
case kNotifySocketDisconnect:
|
||
|
conn = (CliGmConn *) *userState;
|
||
|
NotifyConnSocketDisconnect(conn);
|
||
|
break;
|
||
|
|
||
|
case kNotifySocketRead:
|
||
|
conn = (CliGmConn *) *userState;
|
||
|
result = NotifyConnSocketRead(conn, (AsyncNotifySocketRead *) notify);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static void Connect (
|
||
|
const NetAddress & addr
|
||
|
) {
|
||
|
CliGmConn * conn = NEWZERO(CliGmConn);
|
||
|
conn->addr = addr;
|
||
|
conn->seq = ConnNextSequence();
|
||
|
conn->lastHeardTimeMs = GetNonZeroTimeMs();
|
||
|
|
||
|
conn->IncRef("Lifetime");
|
||
|
conn->IncRef("Connecting");
|
||
|
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
while (CliGmConn * conn = s_conns.Head())
|
||
|
UnlinkAndAbandonConn_CS(conn);
|
||
|
s_conns.Link(conn);
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
|
||
|
Cli2Game_Connect connect;
|
||
|
connect.hdr.connType = kConnTypeCliToGame;
|
||
|
connect.hdr.hdrBytes = sizeof(connect.hdr);
|
||
|
connect.hdr.buildId = BuildId();
|
||
|
connect.hdr.buildType = BuildType();
|
||
|
connect.hdr.branchId = BranchId();
|
||
|
connect.hdr.productId = ProductId();
|
||
|
connect.data.dataBytes = sizeof(connect.data);
|
||
|
|
||
|
AsyncSocketConnect(
|
||
|
&conn->cancelId,
|
||
|
addr,
|
||
|
SocketNotifyCallback,
|
||
|
conn,
|
||
|
&connect,
|
||
|
sizeof(connect),
|
||
|
0,
|
||
|
0
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* CliGmConn
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//============================================================================
|
||
|
CliGmConn::CliGmConn () {
|
||
|
AtomicAdd(&s_perf[kPerfConnCount], 1);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
CliGmConn::~CliGmConn () {
|
||
|
if (cli)
|
||
|
NetCliDelete(cli, true);
|
||
|
AtomicAdd(&s_perf[kPerfConnCount], -1);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void CliGmConn::Send (const unsigned_ptr fields[], unsigned count) {
|
||
|
critsect.Enter();
|
||
|
{
|
||
|
NetCliSend(cli, fields, count);
|
||
|
NetCliFlush(cli);
|
||
|
}
|
||
|
critsect.Leave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Cli2Game protocol
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//============================================================================
|
||
|
static bool Recv_PingReply (
|
||
|
const byte msg[],
|
||
|
unsigned bytes,
|
||
|
void * param
|
||
|
) {
|
||
|
ref(msg);
|
||
|
ref(bytes);
|
||
|
ref(param);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static bool Recv_JoinAgeReply (
|
||
|
const byte msg[],
|
||
|
unsigned bytes,
|
||
|
void * param
|
||
|
) {
|
||
|
ref(bytes);
|
||
|
ref(param);
|
||
|
|
||
|
const Game2Cli_JoinAgeReply & reply = *(const Game2Cli_JoinAgeReply *)msg;
|
||
|
if (sizeof(reply) != bytes)
|
||
|
return false;
|
||
|
|
||
|
NetTransRecv(reply.transId, msg, bytes);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static bool Recv_PropagateBuffer (
|
||
|
const byte msg[],
|
||
|
unsigned bytes,
|
||
|
void * param
|
||
|
) {
|
||
|
ref(bytes);
|
||
|
ref(param);
|
||
|
|
||
|
const Game2Cli_PropagateBuffer & reply = *(const Game2Cli_PropagateBuffer *)msg;
|
||
|
|
||
|
RcvdPropagatedBufferTrans * trans = NEW(RcvdPropagatedBufferTrans);
|
||
|
trans->bufferType = reply.type;
|
||
|
trans->bufferBytes = reply.bytes;
|
||
|
trans->bufferData = (byte *)ALLOC(reply.bytes);
|
||
|
MemCopy(trans->bufferData, reply.buffer, reply.bytes);
|
||
|
NetTransSend(trans);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
static bool Recv_GameMgrMsg (
|
||
|
const byte msg[],
|
||
|
unsigned bytes,
|
||
|
void * param
|
||
|
) {
|
||
|
ref(bytes);
|
||
|
ref(param);
|
||
|
|
||
|
const Game2Cli_GameMgrMsg & reply = *(const Game2Cli_GameMgrMsg *)msg;
|
||
|
|
||
|
RcvdGameMgrMsgTrans * trans = NEW(RcvdGameMgrMsgTrans);
|
||
|
trans->bufferBytes = reply.bytes;
|
||
|
trans->bufferData = (byte *)ALLOC(reply.bytes);
|
||
|
MemCopy(trans->bufferData, reply.buffer, reply.bytes);
|
||
|
NetTransSend(trans);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//============================================================================
|
||
|
// Send/Recv protocol handler init
|
||
|
//============================================================================
|
||
|
#define MSG(s) kNetMsg_Cli2Game_##s
|
||
|
static NetMsgInitSend s_send[] = {
|
||
|
{ MSG(PingRequest), },
|
||
|
{ MSG(JoinAgeRequest), },
|
||
|
{ MSG(PropagateBuffer), },
|
||
|
{ MSG(GameMgrMsg), },
|
||
|
};
|
||
|
#undef MSG
|
||
|
|
||
|
#define MSG(s) kNetMsg_Game2Cli_##s, Recv_##s
|
||
|
static NetMsgInitRecv s_recv[] = {
|
||
|
{ MSG(PingReply) },
|
||
|
{ MSG(JoinAgeReply), },
|
||
|
{ MSG(PropagateBuffer), },
|
||
|
{ MSG(GameMgrMsg), },
|
||
|
};
|
||
|
#undef MSG
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* JoinAgeRequestTrans
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//============================================================================
|
||
|
JoinAgeRequestTrans::JoinAgeRequestTrans (
|
||
|
unsigned ageMcpId,
|
||
|
const Uuid & accountUuid,
|
||
|
unsigned playerInt,
|
||
|
FNetCliGameJoinAgeRequestCallback callback,
|
||
|
void * param
|
||
|
) : NetGameTrans(kJoinAgeRequestTrans)
|
||
|
, m_ageMcpId(ageMcpId)
|
||
|
, m_accountUuid(accountUuid)
|
||
|
, m_playerInt(playerInt)
|
||
|
, m_callback(callback)
|
||
|
, m_param(param)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
bool JoinAgeRequestTrans::Send () {
|
||
|
if (!AcquireConn())
|
||
|
return false;
|
||
|
|
||
|
const unsigned_ptr msg[] = {
|
||
|
kCli2Game_JoinAgeRequest,
|
||
|
m_transId,
|
||
|
m_ageMcpId,
|
||
|
(unsigned_ptr) &m_accountUuid,
|
||
|
m_playerInt,
|
||
|
};
|
||
|
|
||
|
m_conn->Send(msg, arrsize(msg));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void JoinAgeRequestTrans::Post () {
|
||
|
m_callback(
|
||
|
m_result,
|
||
|
m_param
|
||
|
);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
bool JoinAgeRequestTrans::Recv (
|
||
|
const byte msg[],
|
||
|
unsigned bytes
|
||
|
) {
|
||
|
ref(bytes);
|
||
|
|
||
|
const Game2Cli_JoinAgeReply & reply = *(const Game2Cli_JoinAgeReply *) msg;
|
||
|
m_result = reply.result;
|
||
|
m_state = kTransStateComplete;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* RcvdPropagatedBufferTrans
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//============================================================================
|
||
|
RcvdPropagatedBufferTrans::~RcvdPropagatedBufferTrans () {
|
||
|
FREE(bufferData);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void RcvdPropagatedBufferTrans::Post () {
|
||
|
if (s_bufHandler)
|
||
|
s_bufHandler(bufferType, bufferBytes, bufferData);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* RcvdGameMgrMsgTrans
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//============================================================================
|
||
|
RcvdGameMgrMsgTrans::~RcvdGameMgrMsgTrans () {
|
||
|
FREE(bufferData);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void RcvdGameMgrMsgTrans::Post () {
|
||
|
if (s_gameMgrMsgHandler)
|
||
|
s_gameMgrMsgHandler((GameMsgHeader *)bufferData);
|
||
|
}
|
||
|
|
||
|
|
||
|
} using namespace Game;
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* NetGameTrans
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//============================================================================
|
||
|
NetGameTrans::NetGameTrans (ETransType transType)
|
||
|
: NetTrans(kNetProtocolCli2Game, transType)
|
||
|
, m_conn(nil)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
NetGameTrans::~NetGameTrans () {
|
||
|
ReleaseConn();
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
bool NetGameTrans::AcquireConn () {
|
||
|
if (!m_conn)
|
||
|
m_conn = GetConnIncRef("AcquireConn");
|
||
|
return m_conn != nil;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void NetGameTrans::ReleaseConn () {
|
||
|
if (m_conn) {
|
||
|
m_conn->DecRef("AcquireConn");
|
||
|
m_conn = nil;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Protected functions
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//============================================================================
|
||
|
void GameInitialize () {
|
||
|
s_running = true;
|
||
|
NetMsgProtocolRegister(
|
||
|
kNetProtocolCli2Game,
|
||
|
false,
|
||
|
s_send, arrsize(s_send),
|
||
|
s_recv, arrsize(s_recv),
|
||
|
kDhGValue,
|
||
|
BigNum(sizeof(kDhXData), kDhXData),
|
||
|
BigNum(sizeof(kDhNData), kDhNData)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void GameDestroy (bool wait) {
|
||
|
s_running = false;
|
||
|
s_bufHandler = nil;
|
||
|
s_gameMgrMsgHandler = nil;
|
||
|
|
||
|
NetTransCancelByProtocol(
|
||
|
kNetProtocolCli2Game,
|
||
|
kNetErrRemoteShutdown
|
||
|
);
|
||
|
NetMsgProtocolDestroy(
|
||
|
kNetProtocolCli2Game,
|
||
|
false
|
||
|
);
|
||
|
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
while (CliGmConn * conn = s_conns.Head())
|
||
|
UnlinkAndAbandonConn_CS(conn);
|
||
|
s_active = nil;
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
|
||
|
if (!wait)
|
||
|
return;
|
||
|
|
||
|
while (s_perf[kPerfConnCount]) {
|
||
|
NetTransUpdate();
|
||
|
AsyncSleep(10);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
bool GameQueryConnected () {
|
||
|
bool result;
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
if (nil != (result = s_active))
|
||
|
result &= (nil != s_active->cli);
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
unsigned GameGetConnId () {
|
||
|
unsigned connId;
|
||
|
s_critsect.Enter();
|
||
|
connId = (s_active) ? s_active->seq : 0;
|
||
|
s_critsect.Leave();
|
||
|
return connId;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void GamePingEnable (bool enable) {
|
||
|
s_perf[kPingDisabled] = !enable;
|
||
|
}
|
||
|
|
||
|
} using namespace Ngl;
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Exported functions
|
||
|
*
|
||
|
***/
|
||
|
|
||
|
//============================================================================
|
||
|
void NetCliGameStartConnect (
|
||
|
const NetAddressNode & node
|
||
|
) {
|
||
|
NetAddress addr;
|
||
|
NetAddressFromNode(node, kNetDefaultClientPort, &addr);
|
||
|
Connect(addr);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void NetCliGameDisconnect () {
|
||
|
|
||
|
s_critsect.Enter();
|
||
|
{
|
||
|
while (CliGmConn * conn = s_conns.Head())
|
||
|
UnlinkAndAbandonConn_CS(conn);
|
||
|
s_active = nil;
|
||
|
}
|
||
|
s_critsect.Leave();
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void NetCliGameJoinAgeRequest (
|
||
|
unsigned ageMcpId,
|
||
|
const Uuid & accountUuid,
|
||
|
unsigned playerInt,
|
||
|
FNetCliGameJoinAgeRequestCallback callback,
|
||
|
void * param
|
||
|
) {
|
||
|
JoinAgeRequestTrans * trans = NEWZERO(JoinAgeRequestTrans)(
|
||
|
ageMcpId,
|
||
|
accountUuid,
|
||
|
playerInt,
|
||
|
callback,
|
||
|
param
|
||
|
);
|
||
|
NetTransSend(trans);
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void NetCliGameSetRecvBufferHandler (
|
||
|
FNetCliGameRecvBufferHandler handler
|
||
|
) {
|
||
|
s_bufHandler = handler;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void NetCliGamePropagateBuffer (
|
||
|
unsigned type,
|
||
|
unsigned bytes,
|
||
|
const byte buffer[]
|
||
|
) {
|
||
|
CliGmConn * conn = GetConnIncRef("PropBuffer");
|
||
|
if (!conn)
|
||
|
return;
|
||
|
|
||
|
const unsigned_ptr msg[] = {
|
||
|
kCli2Game_PropagateBuffer,
|
||
|
type,
|
||
|
bytes,
|
||
|
(unsigned_ptr) buffer,
|
||
|
};
|
||
|
|
||
|
conn->Send(msg, arrsize(msg));
|
||
|
|
||
|
conn->DecRef("PropBuffer");
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void NetCliGameSetRecvGameMgrMsgHandler (FNetCliGameRecvGameMgrMsgHandler handler) {
|
||
|
s_gameMgrMsgHandler = handler;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
void NetCliGameSendGameMgrMsg (GameMsgHeader * msgHdr) {
|
||
|
CliGmConn * conn = GetConnIncRef("GameMgrMsg");
|
||
|
if (!conn)
|
||
|
return;
|
||
|
|
||
|
const unsigned_ptr msg[] = {
|
||
|
kCli2Game_GameMgrMsg,
|
||
|
msgHdr->messageBytes,
|
||
|
(unsigned_ptr) msgHdr,
|
||
|
};
|
||
|
|
||
|
conn->Send(msg, arrsize(msg));
|
||
|
|
||
|
conn->DecRef("GameMgrMsg");
|
||
|
}
|