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.

317 lines
10 KiB

/*==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==*/
#include "pyNetClientComm.h"
#include "../pfPython/pyAgeLinkStruct.h"
#include "../pfPython/pyNetServerSessionInfo.h"
#include "../pfPython/pyStatusLog.h"
#include "../plNetCommon/plCreatePlayerFlags.h"
#include "../pnNetCommon/plGenericVar.h"
#include "hsStlUtils.h"
#include "hsTimer.h"
#include <python.h>
////////////////////////////////////////////////////////////////////
class pyNetClientCommCallback : public plNetClientComm::Callback
{
public:
PyObject * fPyObject;
pyNetClientCommCallback( PyObject * pyObject )
: fPyObject( pyObject )
{
Py_XINCREF( fPyObject );
}
~pyNetClientCommCallback()
{
Py_XDECREF( fPyObject );
}
void OperationStarted( UInt32 context )
{
if ( fPyObject )
{
// Call the callback.
PyObject* func = PyObject_GetAttrString( fPyObject, "operationStarted" );
if ( func )
{
if ( PyCallable_Check(func)>0 )
{
PyObject* retVal = PyObject_CallMethod(fPyObject, "operationStarted", "l", context);
Py_XDECREF(retVal);
}
}
}
}
void OperationComplete( UInt32 context, int resultCode )
{
if ( fPyObject )
{
// Pass args.
PyObject* pyArgs = PyObject_GetAttrString( fPyObject, "fCbArgs" );
if ( pyArgs )
{
PyObject* pyDict = PyDict_New();
std::map<UInt16,plCreatable*> args;
fCbArgs.GetItems( args );
for ( std::map<UInt16,plCreatable*>::iterator ii=args.begin(); ii!=args.end(); ++ii )
{
UInt16 key = ii->first;
PyObject* keyObj = PyInt_FromLong(key);
char* strTemp = NULL;
plCreatable* arg = ii->second;
plCreatableGenericValue * genValue = plCreatableGenericValue::ConvertNoRef( arg );
if ( genValue )
{
PyObject* valueObj;
plGenericType & value = genValue->Value();
switch ( value.GetType() )
{
case plGenericType::kInt:
valueObj = PyLong_FromLong((Int32)value);
PyDict_SetItem(pyDict, keyObj, valueObj);
Py_DECREF(valueObj);
break;
case plGenericType::kUInt:
valueObj = PyLong_FromUnsignedLong((UInt32)value);
PyDict_SetItem(pyDict, keyObj, valueObj);
Py_DECREF(valueObj);
break;
case plGenericType::kFloat:
valueObj = PyFloat_FromDouble((float)value);
PyDict_SetItem(pyDict, keyObj, valueObj);
Py_DECREF(valueObj);
break;
case plGenericType::kDouble:
valueObj = PyFloat_FromDouble((double)value);
PyDict_SetItem(pyDict, keyObj, valueObj);
Py_DECREF(valueObj);
break;
case plGenericType::kBool:
if ((bool)value)
valueObj = PyInt_FromLong(1);
else
valueObj = PyInt_FromLong(0);
PyDict_SetItem(pyDict, keyObj, valueObj);
Py_DECREF(valueObj);
break;
case plGenericType::kChar:
strTemp = new char[2];
strTemp[0] = (char)value;
strTemp[1] = 0;
valueObj = PyString_FromString(strTemp);
PyDict_SetItem(pyDict, keyObj, valueObj);
Py_DECREF(valueObj);
delete [] strTemp;
break;
case plGenericType::kString:
valueObj = PyString_FromString((const char*)value);
PyDict_SetItem(pyDict, keyObj, valueObj);
Py_DECREF(valueObj);
break;
case plGenericType::kAny:
break;
case plGenericType::kNone:
break;
}
}
plNetServerSessionInfo * serverInfo = plNetServerSessionInfo::ConvertNoRef( arg );
if ( serverInfo )
{
PyObject* valueObj = pyNetServerSessionInfo::New(*serverInfo);
PyDict_SetItem(pyDict, keyObj, valueObj);
Py_DECREF(valueObj);
}
Py_DECREF(keyObj);
}
PyObject_SetAttrString( fPyObject, "fCbArgs", pyDict );
Py_DECREF(pyDict);
}
// Call the callback.
PyObject* func = PyObject_GetAttrString( fPyObject, "operationComplete" );
if ( func )
{
if ( PyCallable_Check(func)>0 )
{
PyObject* retVal = PyObject_CallMethod(fPyObject, "operationComplete", "li", context, resultCode);
Py_XDECREF(retVal);
}
}
}
delete this;
}
};
////////////////////////////////////////////////////////////////////
// Error handler - throws exception in python script
class pyNetClientCommErrorHandler : public plNetClientComm::ErrorHandler
{
public:
void HandleError( Error err, int result )
{
std::string msg;
xtl::format( msg, "pyNetClientComm: Error: %s", plNetClientComm::ErrorHandler::ErrorStr( err ) );
PyErr_SetString(PyExc_KeyError, msg.c_str());
}
} ThePyNetClientCommErrorHandler;
////////////////////////////////////////////////////////////////////
// pyNetClientComm ----------------------------------------------
pyNetClientComm::pyNetClientComm()
{
fNetClient.SetErrorHandler( &ThePyNetClientCommErrorHandler );
}
// ~pyNetClientComm ----------------------------------------------
pyNetClientComm::~pyNetClientComm()
{
}
// NetAuthenticate ----------------------------------------------
int pyNetClientComm::NetAuthenticate( double maxAuthSecs, PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetAuthenticate( maxAuthSecs, new pyNetClientCommCallback( cbClass ), cbContext );
}
// NetLeave ----------------------------------------------
int pyNetClientComm::NetLeave( UInt8 reason, PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetLeave( reason, new pyNetClientCommCallback( cbClass ), cbContext );
}
// NetPing ----------------------------------------------
int pyNetClientComm::NetPing( int serverType, int timeoutSecs/*=0*/, PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetPing( serverType, timeoutSecs, new pyNetClientCommCallback( cbClass ), cbContext );
}
// NetFindAge ----------------------------------------------
int pyNetClientComm::NetFindAge( const pyAgeLinkStruct* linkInfo, PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetFindAge( linkInfo->GetAgeLink(), new pyNetClientCommCallback( cbClass ), cbContext );
}
// NetGetPlayerList ----------------------------------------------
int pyNetClientComm::NetGetPlayerList( PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetGetPlayerList( new pyNetClientCommCallback( cbClass ), cbContext );
}
// NetSetActivePlayer ----------------------------------------------
int pyNetClientComm::NetSetActivePlayer( UInt32 playerID, const char* playerName, PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetSetActivePlayer( playerID, playerName, 0 /*ccrLevel*/, new pyNetClientCommCallback( cbClass ), cbContext );
}
// NetCreatePlayer ----------------------------------------------
int pyNetClientComm::NetCreatePlayer( const char* playerName, const char* avatarShape, UInt32 createFlags, PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetCreatePlayer( playerName, avatarShape, createFlags, nil, nil, nil, new pyNetClientCommCallback( cbClass ), cbContext );
}
// NetJoinAge ----------------------------------------------
int pyNetClientComm::NetJoinAge( PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetJoinAge( true /*tryP2P*/, true /*allowTimeout*/, new pyNetClientCommCallback( cbClass ), cbContext );
}
// NetSetTimeout ----------------------------------------------
int pyNetClientComm::NetSetTimeout( float timeoutSecs, PyObject* cbClass/*=nil*/, UInt32 cbContext/*=0 */)
{
return fNetClient.NetSetTimeout( timeoutSecs, new pyNetClientCommCallback( cbClass ), cbContext );
}
// SetLogLevel ----------------------------------------------
void pyNetClientComm::SetLogLevel( int logLevel )
{
fNetClient.SetLogLevel( logLevel );
}
// Startup ----------------------------------------------
int pyNetClientComm::Init( bool threaded/*=true */, int logLevel/*=0 */)
{
return fNetClient.Init( threaded, logLevel );
}
// Shutdown ----------------------------------------------
int pyNetClientComm::Fini( float flushMsgsSecs/*=0.f */)
{
return fNetClient.Fini( flushMsgsSecs );
}
// Update ----------------------------------------------
int pyNetClientComm::Update()
{
return fNetClient.Update( hsTimer::GetSeconds() );
}
// SetActiveServer ----------------------------------------------
int pyNetClientComm::SetActiveServer( pyNetServerSessionInfo* nfo )
{
return fNetClient.SetActiveServer( &nfo->ServerInfo() );
}
// SetActiveServer2 ----------------------------------------------
int pyNetClientComm::SetActiveServer2( const char * addr, int port )
{
plNetServerSessionInfo nfo;
nfo.SetServerAddr( addr );
nfo.SetServerPort( port );
return fNetClient.SetActiveServer( &nfo );
}
// SetAuthInfo ----------------------------------------------
int pyNetClientComm::SetAuthInfo( const char* acctName, const char* password )
{
return fNetClient.SetAuthInfo( acctName, password );
}
// SetLogByName ----------------------------------------------
void pyNetClientComm::SetLogByName( const char * name, UInt32 flags )
{
plStatusLog * log = plStatusLogMgr::GetInstance().CreateStatusLog( 80, name,
flags | plStatusLog::kTimestamp | plStatusLog::kDeleteForMe );
fNetClient.SetLog( log );
}
// GetLog ----------------------------------------------
PyObject* pyNetClientComm::GetLog() const
{
return pyStatusLog::New( fNetClient.GetLog() );
}
// SetServerSilenceTime ----------------------------------------------
void pyNetClientComm::SetServerSilenceTime( float secs )
{
fNetClient.SetServerSilenceTime( secs );
}
////////////////////////////////////////////////////////////////////
// End.