📄 rpggameconnection.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "core/dnet.h"
#include "console/consoleTypes.h"
#include "console/simBase.h"
#include "core/bitStream.h"
#include "sim/pathManager.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneLighting.h"
#include "audio/audioDataBlock.h"
#include "game/game.h"
#include "game/shapeBase.h"
#include "game/auth.h"
#include "util/safeDelete.h"
#include "server/conn/RPGGameConnection.h"
#include "game/gameConnectionEvents.h"
//----------------------------------------------------------------------------
#define MAX_MOVE_PACKET_SENDS 4
#define ControlRequestTime 5000
const U32 GameConnection::CurrentProtocolVersion = 12;
const U32 GameConnection::MinRequiredProtocolVersion = 12;
//----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GameConnection);
S32 GameConnection::mLagThresholdMS = 0;
//----------------------------------------------------------------------------
GameConnection::GameConnection()
{
mLagging = false;
mControlObject = NULL;
mCameraObject = NULL;
mLastMoveAck = 0;
mLastClientMove = 0;
mFirstMoveIndex = 0;
mMoveCredit = MaxMoveCount;
mDataBlockModifiedKey = 0;
mMaxDataBlockModifiedKey = 0;
mAuthInfo = NULL;
mLastControlObjectChecksum = 0;
mConnectArgc = 0;
for(U32 i = 0; i < MaxConnectArgs; i++)
mConnectArgv[i] = 0;
mJoinPassword = NULL;
mMissionCRC = 0xffffffff;
mDamageFlash = mWhiteOut = 0;
mCameraPos = 0;
mCameraSpeed = 10;
mCameraFov = 90.f;
mUpdateCameraFov = false;
mAIControlled = false;
mDisconnectReason[0] = 0;
//blackout vars
mBlackOut = 0.0f;
mBlackOutTimeMS = 0;
mBlackOutStartTimeMS = 0;
mFadeToBlack = false;
// first person
mFirstPerson = false;
mUpdateFirstPerson = false;
}
GameConnection::~GameConnection()
{
delete mAuthInfo;
for(U32 i = 0; i < mConnectArgc; i++)
dFree(mConnectArgv[i]);
dFree(mJoinPassword);
}
//----------------------------------------------------------------------------
bool GameConnection::canRemoteCreate()
{
return true;
}
void GameConnection::setConnectArgs(U32 argc, const char **argv)
{
if(argc > MaxConnectArgs)
argc = MaxConnectArgs;
mConnectArgc = argc;
for(U32 i = 0; i < mConnectArgc; i++)
mConnectArgv[i] = dStrdup(argv[i]);
}
void GameConnection::setJoinPassword(const char *password)
{
mJoinPassword = dStrdup(password);
}
ConsoleMethod(GameConnection, setJoinPassword, void, 3, 3, "")
{
object->setJoinPassword(argv[2]);
}
ConsoleMethod(GameConnection, setConnectArgs, void, 3, 17, "")
{
object->setConnectArgs(argc - 2, argv + 2);
}
void GameConnection::onTimedOut()
{
if(isConnectionToServer())
{
Con::printf("Connection to server timed out");
Con::executef(this, 1, "onConnectionTimedOut");
}
else
{
Con::printf("Client %d timed out.", getId());
setDisconnectReason("TimedOut");
}
}
void GameConnection::onConnectionEstablished(bool isInitiator)
{
if(isInitiator)
{
setGhostFrom(false);
setGhostTo(true);
setSendingEvents(true);
setTranslatesStrings(true);
setIsConnectionToServer();
mServerConnection = this;
Con::printf("Connection established %d", getId());
Con::executef(this, 1, "onConnectionAccepted");
}
else
{
setGhostFrom(true);
setGhostTo(false);
setSendingEvents(true);
setTranslatesStrings(true);
Sim::getClientGroup()->addObject(this);
const char *argv[MaxConnectArgs + 2];
argv[0] = "onConnect";
for(U32 i = 0; i < mConnectArgc; i++)
argv[i + 2] = mConnectArgv[i];
Con::execute(this, mConnectArgc + 2, argv);
}
}
void GameConnection::onConnectTimedOut()
{
Con::executef(this, 1, "onConnectRequestTimedOut");
}
void GameConnection::onDisconnect(const char *reason)
{
if(isConnectionToServer())
{
Con::printf("Connection with server lost.");
Con::executef(this, 2, "onConnectionDropped", reason);
}
else
{
Con::printf("Client %d disconnected.", getId());
setDisconnectReason(reason);
}
}
void GameConnection::onConnectionRejected(const char *reason)
{
Con::executef(this, 2, "onConnectRequestRejected", reason);
}
void GameConnection::handleStartupError(const char *errorString)
{
Con::executef(this, 2, "onConnectRequestRejected", errorString);
}
void GameConnection::writeConnectAccept(BitStream *stream)
{
Parent::writeConnectAccept(stream);
stream->write(getProtocolVersion());
}
bool GameConnection::readConnectAccept(BitStream *stream, const char **errorString)
{
if(!Parent::readConnectAccept(stream, errorString))
return false;
U32 protocolVersion;
stream->read(&protocolVersion);
if(protocolVersion < MinRequiredProtocolVersion || protocolVersion > CurrentProtocolVersion)
{
*errorString = "CHR_PROTOCOL"; // this should never happen unless someone is faking us out.
return false;
}
return true;
}
void GameConnection::writeConnectRequest(BitStream *stream)
{
Parent::writeConnectRequest(stream);
stream->writeString(GameString);
stream->write(CurrentProtocolVersion);
stream->write(MinRequiredProtocolVersion);
stream->writeString(mJoinPassword);
stream->write(mConnectArgc);
for(U32 i = 0; i < mConnectArgc; i++)
stream->writeString(mConnectArgv[i]);
}
bool GameConnection::readConnectRequest(BitStream *stream, const char **errorString)
{
if(!Parent::readConnectRequest(stream, errorString))
return false;
U32 currentProtocol, minProtocol;
char gameString[256];
stream->readString(gameString);
if(dStrcmp(gameString, GameString))
{
*errorString = "CHR_GAME";
return false;
}
stream->read(¤tProtocol);
stream->read(&minProtocol);
char joinPassword[256];
stream->readString(joinPassword);
if(currentProtocol < MinRequiredProtocolVersion)
{
*errorString = "CHR_PROTOCOL_LESS";
return false;
}
if(minProtocol > CurrentProtocolVersion)
{
*errorString = "CHR_PROTOCOL_GREATER";
return false;
}
setProtocolVersion(currentProtocol < CurrentProtocolVersion ? currentProtocol : CurrentProtocolVersion);
const char *serverPassword = Con::getVariable("Pref::Server::Password");
if(serverPassword[0])
{
if(dStrcmp(joinPassword, serverPassword))
{
*errorString = "CHR_PASSWORD";
return false;
}
}
stream->read(&mConnectArgc);
if(mConnectArgc > MaxConnectArgs)
{
*errorString = "CR_INVALID_ARGS";
return false;
}
const char *connectArgv[MaxConnectArgs + 3];
for(U32 i = 0; i < mConnectArgc; i++)
{
char argString[256];
stream->readString(argString);
mConnectArgv[i] = dStrdup(argString);
connectArgv[i + 3] = mConnectArgv[i];
}
connectArgv[0] = "onConnectRequest";
char buffer[256];
Net::addressToString(getNetAddress(), buffer);
connectArgv[2] = buffer;
const char *ret = Con::execute(this, mConnectArgc + 3, connectArgv);
if(ret[0])
{
*errorString = ret;
return false;
}
return true;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void GameConnection::connectionError(const char *errorString)
{
if(isConnectionToServer())
{
Con::printf("Connection error: %s.", errorString);
Con::executef(this, 2, "onConnectionError", errorString);
}
else
{
Con::printf("Client %d packet error: %s.", getId(), errorString);
setDisconnectReason("Packet Error.");
}
deleteObject();
}
void GameConnection::setAuthInfo(const AuthInfo *info)
{
mAuthInfo = new AuthInfo;
*mAuthInfo = *info;
}
const AuthInfo *GameConnection::getAuthInfo()
{
return mAuthInfo;
}
//----------------------------------------------------------------------------
void GameConnection::setControlObject(ShapeBase *obj)
{
if(mControlObject == obj)
return;
if(mControlObject && mControlObject != mCameraObject)
mControlObject->setControllingClient(0);
if(obj)
{
// Nothing else is permitted to control this object.
if (ShapeBase* coo = obj->getControllingObject())
coo->setControlObject(0);
if (GameConnection *con = obj->getControllingClient())
{
if(this != con)
{
// was it controlled via camera or control
if(con->getControlObject() == obj)
con->setControlObject(0);
else
con->setCameraObject(0);
}
}
// We are now the controlling client of this object.
obj->setControllingClient(this);
}
// Okay, set our control object.
mControlObject = obj;
if(mCameraObject.isNull())
setScopeObject(mControlObject);
}
void GameConnection::setCameraObject(ShapeBase *obj)
{
if(mCameraObject == obj)
return;
if(mCameraObject && mCameraObject != mControlObject)
mCameraObject->setControllingClient(0);
if(obj)
{
// nothing else is permitted to control this object
if(ShapeBase *coo = obj->getControllingObject())
coo->setControlObject(0);
if(GameConnection *con = obj->getControllingClient())
{
if(this != con)
{
// was it controlled via camera or control
if(con->getControlObject() == obj)
con->setControlObject(0);
else
con->setCameraObject(0);
}
}
// we are now the controlling client of this object
obj->setControllingClient(this);
}
// Okay, set our camera object.
mCameraObject = obj;
if(mCameraObject.isNull())
setScopeObject(mControlObject);
else
{
setScopeObject(mCameraObject);
// if this is a client then set the fov and active image
if(isConnectionToServer())
{
F32 fov = mCameraObject->getDefaultCameraFov();
GameSetCameraFov(fov);
}
}
}
ShapeBase* GameConnection::getCameraObject()
{
// If there is no camera object, or if we're first person, return
// the control object.
if( !mControlObject.isNull() && (mCameraObject.isNull() || mFirstPerson))
return mControlObject;
return mCameraObject;
}
static S32 sChaseQueueSize = 0;
static MatrixF* sChaseQueue = 0;
static S32 sChaseQueueHead = 0;
static S32 sChaseQueueTail = 0;
bool GameConnection::getControlCameraTransform(F32 dt, MatrixF* mat)
{
ShapeBase* obj = getCameraObject();
if(!obj)
return false;
ShapeBase* cObj = obj;
while((cObj = cObj->getControlObject()) != 0)
{
if(cObj->useObjsEyePoint())
obj = cObj;
}
if (dt)
{
if (mFirstPerson || obj->onlyFirstPerson())
{
if (mCameraPos > 0)
if ((mCameraPos -= mCameraSpeed * dt) <= 0)
mCameraPos = 0;
}
else
{
if (mCameraPos < 1)
if ((mCameraPos += mCameraSpeed * dt) > 1)
mCameraPos = 1;
}
}
if (!sChaseQueueSize || mFirstPerson || obj->onlyFirstPerson())
obj->getCameraTransform(&mCameraPos,mat);
else
{
MatrixF& hm = sChaseQueue[sChaseQueueHead];
MatrixF& tm = sChaseQueue[sChaseQueueTail];
obj->getCameraTransform(&mCameraPos,&hm);
*mat = tm;
if (dt)
{
if ((sChaseQueueHead += 1) >= sChaseQueueSize)
sChaseQueueHead = 0;
if (sChaseQueueHead == sChaseQueueTail)
if ((sChaseQueueTail += 1) >= sChaseQueueSize)
sChaseQueueTail = 0;
}
}
return true;
}
bool GameConnection::getControlCameraFov(F32 * fov)
{
//find the last control object in the chain (client->player->turret->whatever...)
ShapeBase *obj = getCameraObject();
ShapeBase *cObj = NULL;
while (obj)
{
cObj = obj;
obj = obj->getControlObject();
}
if (cObj)
{
*fov = cObj->getCameraFov();
return(true);
}
return(false);
}
bool GameConnection::isValidControlCameraFov(F32 fov)
{
//find the last control object in the chain (client->player->turret->whatever...)
ShapeBase *obj = getCameraObject();
ShapeBase *cObj = NULL;
while (obj)
{
cObj = obj;
obj = obj->getControlObject();
}
return cObj ? cObj->isValidCameraFov(fov) : NULL;
}
bool GameConnection::setControlCameraFov(F32 fov)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -