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.

540 lines
20 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 "cyMisc.h"
#include "pyGlueHelpers.h"
#include "pyKey.h"
#include "pyPlayer.h"
#include "hsUtils.h"
#include <Python.h>
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetAgeName, "DEPRECIATED - use ptDniInfoSource instead")
{
return PyString_FromString(cyMisc::GetAgeName());
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetAgeInfo, "Returns ptAgeInfoStruct of the current Age")
{
return cyMisc::GetAgeInfo();
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetAgeTime, "DEPRECIATED - use ptDniInfoSource instead")
{
return PyLong_FromUnsignedLong(cyMisc::GetAgeTime());
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetPrevAgeName, "Returns filename of previous age visited")
{
return PyString_FromString(cyMisc::GetPrevAgeName());
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetPrevAgeInfo, "Returns ptAgeInfoStruct of previous age visited")
{
return cyMisc::GetPrevAgeInfo();
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetDniTime, "Returns current D'Ni time")
{
return PyLong_FromUnsignedLong((unsigned long)cyMisc::GetDniTime());
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetServerTime, "Returns the current time on the server (which is GMT)")
{
return PyLong_FromUnsignedLong((unsigned long)cyMisc::GetServerTime());
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtGMTtoDniTime, args, "Params: gtime\nConverts GMT time (passed in) to D'Ni time")
{
unsigned long gtime;
if (!PyArg_ParseTuple(args, "l", &gtime))
{
PyErr_SetString(PyExc_TypeError, "PtGMTtoDniTime expects a long");
PYTHON_RETURN_ERROR;
}
return PyLong_FromUnsignedLong((unsigned long)cyMisc::ConvertGMTtoDni(gtime));
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtGetClientName, args, "Params: avatarKey=None\nThis will return the name of the client that is owned by the avatar\n"
"- avatarKey is the ptKey of the avatar to get the client name of.\n"
"If avatarKey is omitted then the local avatar is used")
{
PyObject* keyObj = NULL;
if (!PyArg_ParseTuple(args, "|O", &keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtGetClientName expects an optional ptKey");
PYTHON_RETURN_ERROR;
}
if (keyObj != NULL)
{
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtGetClientName expects a ptKey");
PYTHON_RETURN_ERROR;
}
pyKey* key = pyKey::ConvertFrom(keyObj);
return PyString_FromString(cyMisc::GetClientName(*key));
}
else
return PyString_FromString(cyMisc::GetLocalClientName());
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetLocalAvatar, "This will return a ptSceneobject of the local avatar\n"
"- if there is no local avatar a NameError exception will happen.")
{
return cyMisc::GetLocalAvatar();
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetLocalPlayer, "Returns a ptPlayer object of the local player")
{
return cyMisc::GetLocalPlayer();
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetPlayerList, "Returns a list of ptPlayer objects of all the remote players")
{
std::vector<PyObject*> playerList = cyMisc::GetPlayerList();
PyObject* retVal = PyList_New(playerList.size());
for (int i = 0; i < playerList.size(); i++)
PyList_SetItem(retVal, i, playerList[i]); // steals the ref
return retVal;
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetPlayerListDistanceSorted, "Returns a list of ptPlayers, sorted by distance")
{
std::vector<PyObject*> playerList = cyMisc::GetPlayerListDistanceSorted();
PyObject* retVal = PyList_New(playerList.size());
for (int i = 0; i < playerList.size(); i++)
PyList_SetItem(retVal, i, playerList[i]); // steals the ref
return retVal;
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtMaxListenListSize, "Returns the maximum listen number of players")
{
return PyLong_FromUnsignedLong(cyMisc::GetMaxListenListSize());
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtMaxListenDistSq, "Returns the maximum distance (squared) of the listen range")
{
return PyFloat_FromDouble(cyMisc::GetMaxListenDistSq());
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtGetAvatarKeyFromClientID, args, "Params: clientID\nFrom an integer that is the clientID, find the avatar and return its ptKey")
{
int clientID;
if (!PyArg_ParseTuple(args, "i", &clientID))
{
PyErr_SetString(PyExc_TypeError, "PtGetAvatarKeyFromClientID expects an integer");
PYTHON_RETURN_ERROR;
}
return cyMisc::GetAvatarKeyFromClientID(clientID);
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtGetClientIDFromAvatarKey, args, "Params: avatarKey\nFrom a ptKey that points at an avatar, return the players clientID (integer)")
{
PyObject* keyObj = NULL;
if (!PyArg_ParseTuple(args, "O", &keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtGetClientIDFromAvatarKey expects a ptKey");
PYTHON_RETURN_ERROR;
}
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtGetClientIDFromAvatarKey expects a ptKey");
PYTHON_RETURN_ERROR;
}
pyKey *key = pyKey::ConvertFrom(keyObj);
return PyInt_FromLong(cyMisc::GetClientIDFromAvatarKey(*key));
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetNumRemotePlayers, "Returns the number of remote players in this Age with you.")
{
return PyInt_FromLong(cyMisc::GetNumRemotePlayers());
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtValidateKey, args, "Params: key\nReturns true(1) if 'key' is valid and loaded,\n"
"otherwise returns false(0)")
{
PyObject* keyObj = NULL;
if (!PyArg_ParseTuple(args, "O", &keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtValidateKey expects an object");
PYTHON_RETURN_ERROR;
}
if (!pyKey::Check(keyObj))
{
PYTHON_RETURN_BOOL(false);
}
pyKey* key = pyKey::ConvertFrom(keyObj);
PYTHON_RETURN_BOOL(cyMisc::ValidateKey(*key));
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtSendRTChat, args, "Params: fromPlayer,toPlayerList,message,flags\nSends a realtime chat message to the list of ptPlayers\n"
"If toPlayerList is an empty list, it is a broadcast message")
{
PyObject* fromPlayerObj = NULL;
PyObject* toPlayerListObj = NULL;
PyObject* message = NULL;
unsigned long msgFlags;
if (!PyArg_ParseTuple(args, "OOOl", &fromPlayerObj, &toPlayerListObj, &message, &msgFlags))
{
PyErr_SetString(PyExc_TypeError, "PtSendRTChat expects a ptPlayer, a list of ptPlayers, a string, and a long");
PYTHON_RETURN_ERROR;
}
if (!pyPlayer::Check(fromPlayerObj))
{
PyErr_SetString(PyExc_TypeError, "PtSendRTChat expects a ptPlayer, a list of ptPlayers, a string, and a long");
PYTHON_RETURN_ERROR;
}
pyPlayer* fromPlayer = pyPlayer::ConvertFrom(fromPlayerObj);
std::vector<pyPlayer*> toPlayerList;
if (PyList_Check(toPlayerListObj))
{
int listSize = PyList_Size(toPlayerListObj);
for (int i = 0; i < listSize; i++)
{
PyObject* listItem = PyList_GetItem(toPlayerListObj, i);
if (!pyPlayer::Check(listItem))
{
PyErr_SetString(PyExc_TypeError, "PtSendRTChat expects a ptPlayer, a list of ptPlayers, a string, and a long");
PYTHON_RETURN_ERROR;
}
toPlayerList.push_back(pyPlayer::ConvertFrom(listItem));
}
}
else
{
PyErr_SetString(PyExc_TypeError, "PtSendRTChat expects a ptPlayer, a list of ptPlayers, a string, and a long");
PYTHON_RETURN_ERROR;
}
if (PyString_Check(message))
{
char* msg = PyString_AsString(message);
return PyLong_FromUnsignedLong(cyMisc::SendRTChat(*fromPlayer, toPlayerList, msg, msgFlags));
}
else if (PyUnicode_Check(message))
{
Py_ssize_t size = PyUnicode_GetSize(message);
wchar_t* msg = TRACKED_NEW wchar_t[size + 1]; msg[size] = 0;
PyUnicode_AsWideChar((PyUnicodeObject*)message, msg, size);
UInt32 retval = cyMisc::SendRTChat(*fromPlayer, toPlayerList, msg, msgFlags);
DEL(msg);
return PyLong_FromUnsignedLong(retval);
}
else
{
PyErr_SetString(PyExc_TypeError, "PtSendRTChat expects a ptPlayer, a list of ptPlayers, a string, and a long");
PYTHON_RETURN_ERROR;
}
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtSendKIMessage, args, "Params: command,value\nSends a command message to the KI frontend.\n"
"See PlasmaKITypes.py for list of commands")
{
unsigned long command;
PyObject* val;
if (!PyArg_ParseTuple(args, "lO", &command, &val))
{
PyErr_SetString(PyExc_TypeError, "PtSendKIMessage expects a long and either a float or a string");
PYTHON_RETURN_ERROR;
}
if (PyString_Check(val))
{
char* strValue = PyString_AsString(val);
wchar_t* temp = hsStringToWString(strValue);
cyMisc::SendKIMessageS(command, temp);
delete [] temp;
}
else if (PyUnicode_Check(val))
{
int len = PyUnicode_GetSize(val);
wchar_t* buffer = TRACKED_NEW wchar_t[len + 1];
PyUnicode_AsWideChar((PyUnicodeObject*)val, buffer, len);
buffer[len] = L'\0';
cyMisc::SendKIMessageS(command, buffer);
delete [] buffer;
}
else if (PyFloat_Check(val))
{
float floatValue = (float)PyFloat_AsDouble(val);
cyMisc::SendKIMessage(command, floatValue);
}
else if (PyInt_Check(val))
{
// accepting an int if people get lazy
float floatValue = (float)PyInt_AsLong(val);
cyMisc::SendKIMessage(command, floatValue);
}
else
{
PyErr_SetString(PyExc_TypeError, "PtSendKIMessage expects a long and either a float or a string");
PYTHON_RETURN_ERROR;
}
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtSendKIMessageInt, args, "Params: command,value\nSame as PtSendKIMessage except the value is guaranteed to be a UInt32\n"
"(for things like player IDs)")
{
unsigned long command;
long val;
if (!PyArg_ParseTuple(args, "ll", &command, &val))
{
PyErr_SetString(PyExc_TypeError, "PtSendKIMessageInt expects two longs");
PYTHON_RETURN_ERROR;
}
cyMisc::SendKIMessageI(command, val);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtLoadAvatarModel, args, "Params: modelName, spawnPoint, userStr = \"\"\nLoads an avatar model at the given spawn point. Assigns the user specified string to it.")
{
char* modelName;
PyObject* keyObj = NULL;
PyObject* userStrObj = NULL;
if (!PyArg_ParseTuple(args, "sO|O", &modelName, &keyObj, &userStrObj))
{
PyErr_SetString(PyExc_TypeError, "PtLoadAvatarModel expects a string, a ptKey, and an optional string");
PYTHON_RETURN_ERROR;
}
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtLoadAvatarModel expects a string, a ptKey, and an optional string");
PYTHON_RETURN_ERROR;
}
pyKey* key = pyKey::ConvertFrom(keyObj);
std::string userStr = "";
// convert name from a string or unicode string
if (userStrObj)
{
if (PyUnicode_Check(userStrObj))
{
int len = PyUnicode_GetSize(userStrObj);
wchar_t* buffer = TRACKED_NEW wchar_t[len + 1];
PyUnicode_AsWideChar((PyUnicodeObject*)userStrObj, buffer, len);
buffer[len] = L'\0';
char* temp = hsWStringToString(buffer);
delete [] buffer;
userStr = temp;
delete [] temp;
}
else if (PyString_Check(userStrObj))
userStr = PyString_AsString(userStrObj);
else
{
PyErr_SetString(PyExc_TypeError, "PtLoadAvatarModel expects a string, a ptKey, and an optional string");
PYTHON_RETURN_ERROR;
}
}
return cyMisc::LoadAvatarModel(modelName, *key, userStr.c_str());
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtUnLoadAvatarModel, args, "Params: avatarKey\nUnloads the specified avatar model")
{
PyObject* keyObj = NULL;
if (!PyArg_ParseTuple(args, "O", &keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtUnLoadAvatarModel expects a ptKey");
PYTHON_RETURN_ERROR;
}
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtUnLoadAvatarModel expects a ptKey");
PYTHON_RETURN_ERROR;
}
pyKey* key = pyKey::ConvertFrom(keyObj);
cyMisc::UnLoadAvatarModel(*key);
PYTHON_RETURN_NONE;
}
PYTHON_BASIC_GLOBAL_METHOD_DEFINITION(PtForceCursorHidden, cyMisc::ForceCursorHidden, "Forces the cursor to hide, overriding everything.\n"
"Only call if other methods won't work. The only way to show the cursor after this call is PtForceMouseShown()")
PYTHON_BASIC_GLOBAL_METHOD_DEFINITION(PtForceCursorShown, cyMisc::ForceCursorShown, "Forces the cursor to show, overriding everything.\n"
"Only call if other methods won't work. This is the only way to show the cursor after a call to PtForceMouseHidden()")
PYTHON_GLOBAL_METHOD_DEFINITION(PtGetLocalizedString, args, "Params: name, arguments=None\nReturns the localized string specified by name "
"(format is Age.Set.Name) and substitutes the arguments in the list of strings passed in as arguments.")
{
PyObject* nameObj = NULL;
PyObject* argObj = NULL;
if (!PyArg_ParseTuple(args, "O|O", &nameObj, &argObj))
{
PyErr_SetString(PyExc_TypeError, "PtGetLocalizedString expects a unicode string and a list of unicode strings");
PYTHON_RETURN_ERROR;
}
std::wstring name;
std::vector<std::wstring> argList;
// convert name from a string or unicode string
if (PyUnicode_Check(nameObj))
{
int len = PyUnicode_GetSize(nameObj);
wchar_t* buffer = TRACKED_NEW wchar_t[len + 1];
PyUnicode_AsWideChar((PyUnicodeObject*)nameObj, buffer, len);
buffer[len] = L'\0';
name = buffer;
delete [] buffer;
}
else if (PyString_Check(nameObj))
{
char* temp = PyString_AsString(nameObj);
wchar_t* wTemp = hsStringToWString(temp);
name = wTemp;
delete [] wTemp;
}
else
{
PyErr_SetString(PyExc_TypeError, "PtGetLocalizedString expects a unicode string and a list of unicode strings");
PYTHON_RETURN_ERROR;
}
if (argObj != NULL) // NULL is valid... but won't fill the args vector
{
// convert args from a list of strings or unicode strings
if (!PyList_Check(argObj))
{
PyErr_SetString(PyExc_TypeError, "PtGetLocalizedString expects a unicode string and a list of unicode strings");
PYTHON_RETURN_ERROR;
}
int len = PyList_Size(argObj);
for (int curItem = 0; curItem < len; curItem++)
{
PyObject* item = PyList_GetItem(argObj, curItem);
std::wstring arg = L"INVALID ARG";
if (item == Py_None) // none is allowed, but treated as a blank string
arg = L"";
else if (PyUnicode_Check(item))
{
int strLen = PyUnicode_GetSize(item);
wchar_t* buffer = TRACKED_NEW wchar_t[strLen + 1];
PyUnicode_AsWideChar((PyUnicodeObject*)item, buffer, strLen);
buffer[strLen] = L'\0';
arg = buffer;
delete [] buffer;
}
else if (PyString_Check(item))
{
char* temp = PyString_AsString(item);
wchar_t* wTemp = hsStringToWString(temp);
arg = wTemp;
delete [] wTemp;
}
// everything else won't throw an error, but will show up as INVALID ARG in the string
argList.push_back(arg);
}
}
std::wstring retVal = cyMisc::GetLocalizedString(name, argList);
return PyUnicode_FromWideChar(retVal.c_str(), retVal.length());
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtDumpLogs, args, "Params: folder\nDumps all current log files to the specified folder (a sub-folder to the log folder)")
{
PyObject* folderObj = NULL;
if (!PyArg_ParseTuple(args, "O|O", &folderObj))
{
PyErr_SetString(PyExc_TypeError, "PtDumpLogs expects a unicode or standard string");
PYTHON_RETURN_ERROR;
}
// convert folder from a string or unicode string
if (PyUnicode_Check(folderObj))
{
int len = PyUnicode_GetSize(folderObj);
wchar_t* buffer = TRACKED_NEW wchar_t[len + 1];
PyUnicode_AsWideChar((PyUnicodeObject*)folderObj, buffer, len);
buffer[len] = L'\0';
bool retVal = cyMisc::DumpLogs(buffer);
delete [] buffer;
PYTHON_RETURN_BOOL(retVal);
}
else if (PyString_Check(folderObj))
{
char* temp = PyString_AsString(folderObj);
wchar_t* wTemp = hsStringToWString(temp);
bool retVal = cyMisc::DumpLogs(wTemp);
delete [] wTemp;
PYTHON_RETURN_BOOL(retVal);
}
else
{
PyErr_SetString(PyExc_TypeError, "PtDumpLogs expects a unicode or standard string");
PYTHON_RETURN_ERROR;
}
}
///////////////////////////////////////////////////////////////////////////
//
// AddPlasmaMethods - the python method definitions
//
void cyMisc::AddPlasmaMethods(std::vector<PyMethodDef> &methods)
{
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetAgeName);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetAgeInfo);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetAgeTime);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetPrevAgeName);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetPrevAgeInfo);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetDniTime);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetServerTime);
PYTHON_GLOBAL_METHOD(methods, PtGMTtoDniTime);
PYTHON_GLOBAL_METHOD(methods, PtGetClientName);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetLocalAvatar);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetLocalPlayer);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetPlayerList);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetPlayerListDistanceSorted);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtMaxListenListSize);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtMaxListenDistSq);
PYTHON_GLOBAL_METHOD(methods, PtGetAvatarKeyFromClientID);
PYTHON_GLOBAL_METHOD(methods, PtGetClientIDFromAvatarKey);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetNumRemotePlayers);
PYTHON_GLOBAL_METHOD(methods, PtValidateKey);
PYTHON_GLOBAL_METHOD(methods, PtSendRTChat);
PYTHON_GLOBAL_METHOD(methods, PtSendKIMessage);
PYTHON_GLOBAL_METHOD(methods, PtSendKIMessageInt);
PYTHON_GLOBAL_METHOD(methods, PtLoadAvatarModel);
PYTHON_GLOBAL_METHOD(methods, PtUnLoadAvatarModel);
PYTHON_BASIC_GLOBAL_METHOD(methods, PtForceCursorHidden);
PYTHON_BASIC_GLOBAL_METHOD(methods, PtForceCursorShown);
PYTHON_GLOBAL_METHOD(methods, PtGetLocalizedString);
PYTHON_GLOBAL_METHOD(methods, PtDumpLogs);
AddPlasmaMethods2(methods);
AddPlasmaMethods3(methods);
AddPlasmaMethods4(methods);
}