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.

515 lines
19 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 "pyColor.h"
#include "pyPlayer.h"
#include "pyEnum.h"
// for enums
#include "plNetCommon\plNetCommon.h"
#include "plResMgr\plLocalization.h"
#include "plMessage\plLOSRequestMsg.h"
#include <python.h>
PYTHON_GLOBAL_METHOD_DEFINITION(PtYesNoDialog, args, "Params: selfkey,dialogMessage\nThis will display a Yes/No dialog to the user with the text dialogMessage\n"
"This dialog _has_ to be answered by the user.\n"
"And their answer will be returned in a Notify message.")
{
PyObject* keyObj = NULL;
PyObject* dialogMsgObj = NULL;
if (!PyArg_ParseTuple(args, "OO", &keyObj, &dialogMsgObj))
{
PyErr_SetString(PyExc_TypeError, "PtYesNoDialog expects a ptKey and a string or unicode string");
PYTHON_RETURN_ERROR;
}
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtYesNoDialog expects a ptKey and a string or unicode string");
PYTHON_RETURN_ERROR;
}
pyKey* key = pyKey::ConvertFrom(keyObj);
if (PyUnicode_Check(dialogMsgObj))
{
int len = PyUnicode_GetSize(dialogMsgObj);
wchar_t* text = TRACKED_NEW wchar_t[len + 1];
PyUnicode_AsWideChar((PyUnicodeObject*)dialogMsgObj, text, len);
text[len] = L'\0';
cyMisc::YesNoDialog(*key, text);
delete [] text;
PYTHON_RETURN_NONE;
}
else if (PyString_Check(dialogMsgObj))
{
char* text = PyString_AsString(dialogMsgObj);
cyMisc::YesNoDialog(*key, text);
PYTHON_RETURN_NONE;
}
PyErr_SetString(PyExc_TypeError, "PtYesNoDialog expects a ptKey and a string or unicode string");
PYTHON_RETURN_ERROR;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtRateIt, args, "Params: chronicleName,dialogPrompt,onceFlag\nShows a dialog with dialogPrompt and stores user input rating into chronicleName")
{
char* chronicleName;
char* dialogPrompt;
char onceFlag;
if (!PyArg_ParseTuple(args, "ssb", &chronicleName, &dialogPrompt, &onceFlag))
{
PyErr_SetString(PyExc_TypeError, "PtRateIt expects two strings and a boolean");
PYTHON_RETURN_ERROR;
}
cyMisc::RateIt(chronicleName, dialogPrompt, onceFlag != 0);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtExcludeRegionSet, args, "Params: senderKey,regionKey,state\nThis will set the state of an exclude region\n"
"- 'senderKey' is a ptKey of the PythonFile component\n"
"- 'regionKey' is a ptKey of the exclude region\n"
"- 'state' is either kExRegRelease or kExRegClear")
{
PyObject* senderObj = NULL;
PyObject* regionObj = NULL;
unsigned short stateVal;
if (!PyArg_ParseTuple(args, "OOh", &senderObj, &regionObj, &stateVal))
{
PyErr_SetString(PyExc_TypeError, "PtExcludeRegionSet expects two ptKeys and a short");
PYTHON_RETURN_ERROR;
}
if ((!pyKey::Check(senderObj)) || (!pyKey::Check(regionObj)))
{
PyErr_SetString(PyExc_TypeError, "PtExcludeRegionSet expects two ptKeys and a short");
PYTHON_RETURN_ERROR;
}
pyKey* sender = pyKey::ConvertFrom(senderObj);
pyKey* region = pyKey::ConvertFrom(regionObj);
cyMisc::ExcludeRegionSet(*sender, *region, stateVal);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtExcludeRegionSetNow, args, "Params: senderKey,regionKey,state\nThis will set the state of an exclude region immediately on the server\n"
"- 'senderKey' is a ptKey of the PythonFile component\n"
"- 'regionKey' is a ptKey of the exclude region\n"
"- 'state' is either kExRegRelease or kExRegClear")
{
PyObject* senderObj = NULL;
PyObject* regionObj = NULL;
unsigned short stateVal;
if (!PyArg_ParseTuple(args, "OOh", &senderObj, &regionObj, &stateVal))
{
PyErr_SetString(PyExc_TypeError, "PtExcludeRegionSetNow expects two ptKeys and a short");
PYTHON_RETURN_ERROR;
}
if ((!pyKey::Check(senderObj)) || (!pyKey::Check(regionObj)))
{
PyErr_SetString(PyExc_TypeError, "PtExcludeRegionSetNow expects two ptKeys and a short");
PYTHON_RETURN_ERROR;
}
pyKey* sender = pyKey::ConvertFrom(senderObj);
pyKey* region = pyKey::ConvertFrom(regionObj);
cyMisc::ExcludeRegionSetNow(*sender, *region, stateVal);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtAcceptInviteInGame, args, "Params: friendName,inviteKey\nSends a VaultTask to the server to perform the invite")
{
char* friendName;
char* inviteKey;
if (!PyArg_ParseTuple(args, "ss", &friendName, &inviteKey))
{
PyErr_SetString(PyExc_TypeError, "PtAcceptInviteInGame expects two strings");
PYTHON_RETURN_ERROR;
}
cyMisc::AcceptInviteInGame(friendName, inviteKey);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetTime, "Returns the number of seconds since the game was started.")
{
return PyFloat_FromDouble(cyMisc::GetSeconds());
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetGameTime, "Returns the system game time (frame based) in seconds.")
{
return PyFloat_FromDouble(cyMisc::GetSysSeconds());
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtGetFrameDeltaTime, "Returns the amount of time that has elapsed since last frame.")
{
return PyFloat_FromDouble(cyMisc::GetDelSysSeconds());
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtPageInNode, args, "Params: nodeName, ageName=\"\"\nPages in node, or a list of nodes")
{
PyObject* nodeNameObj = NULL;
char* ageName = NULL;
if (!PyArg_ParseTuple(args, "O|s", &nodeNameObj, &ageName))
{
PyErr_SetString(PyExc_TypeError, "PtPageInNode expects a string or list of strings, and optionally a string");
PYTHON_RETURN_ERROR;
}
std::vector<std::string> nodeNames;
if (PyString_Check(nodeNameObj))
{
nodeNames.push_back(PyString_AsString(nodeNameObj));
}
else if (PyList_Check(nodeNameObj))
{
int num = PyList_Size(nodeNameObj);
for (int i = 0; i < num; i++)
{
PyObject* listItem = PyList_GetItem(nodeNameObj, i);
if (!PyString_Check(listItem))
{
PyErr_SetString(PyExc_TypeError, "PtPageInNode expects a string or list of strings, and optionally a string");
PYTHON_RETURN_ERROR;
}
nodeNames.push_back(PyString_AsString(listItem));
}
}
else
{
PyErr_SetString(PyExc_TypeError, "PtPageInNode expects a string or list of strings, and optionally a string");
PYTHON_RETURN_ERROR;
}
cyMisc::PageInNodes(nodeNames, ageName);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtPageOutNode, args, "Params: nodeName\nPages out a node")
{
char* nodeName;
if (!PyArg_ParseTuple(args, "s", &nodeName))
{
PyErr_SetString(PyExc_TypeError, "PtPageOutNode expects a string");
PYTHON_RETURN_ERROR;
}
cyMisc::PageOutNode(nodeName);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtLimitAvatarLOD, args, "Params: LODlimit\nSets avatar's LOD limit")
{
int lodLimit;
if (!PyArg_ParseTuple(args, "i", &lodLimit))
{
PyErr_SetString(PyExc_TypeError, "PtLimitAvatarLOD expects an integer");
PYTHON_RETURN_ERROR;
}
cyMisc::LimitAvatarLOD(lodLimit);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtFogSetDefColor, args, "Params: color\nSets default fog color")
{
PyObject* colorObj = NULL;
if (!PyArg_ParseTuple(args, "O", &colorObj))
{
PyErr_SetString(PyExc_TypeError, "PtFogSetDefColor expects a ptColor object");
PYTHON_RETURN_ERROR;
}
if (!pyColor::Check(colorObj))
{
PyErr_SetString(PyExc_TypeError, "PtFogSetDefColor expects a ptColor object");
PYTHON_RETURN_ERROR;
}
pyColor* color = pyColor::ConvertFrom(colorObj);
cyMisc::FogSetDefColor(*color);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtFogSetDefLinear, args, "Params: start,end,density\nSet linear fog values")
{
float start, end, density;
if (!PyArg_ParseTuple(args, "fff", &start, &end, &density))
{
PyErr_SetString(PyExc_TypeError, "PtFogSetDefLinear expects three floats");
PYTHON_RETURN_ERROR;
}
cyMisc::FogSetDefLinear(start, end, density);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtFogSetDefExp, args, "Params: end,density\nSet exp fog values")
{
float end, density;
if (!PyArg_ParseTuple(args, "ff", &end, &density))
{
PyErr_SetString(PyExc_TypeError, "PtFogSetDefExp expects three floats");
PYTHON_RETURN_ERROR;
}
cyMisc::FogSetDefExp(end, density);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtFogSetDefExp2, args, "Params: end,density\nSet exp2 fog values")
{
float end, density;
if (!PyArg_ParseTuple(args, "ff", &end, &density))
{
PyErr_SetString(PyExc_TypeError, "PtFogSetDefExp2 expects three floats");
PYTHON_RETURN_ERROR;
}
cyMisc::FogSetDefExp2(end, density);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtLoadDialog, args, "Params: dialogName,selfKey=None,ageName=\"\"\nLoads a GUI dialog by name and optionally set the Notify proc key\n"
"If the dialog is already loaded then it won't load it again")
{
char* dialogName;
PyObject* keyObj = NULL;
char* ageName = NULL;
if (!PyArg_ParseTuple(args, "s|Os", &dialogName, &keyObj, &ageName))
{
PyErr_SetString(PyExc_TypeError, "PtLoadDialog expects a string, and optionally a ptKey and second string");
PYTHON_RETURN_ERROR;
}
if (keyObj)
{
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtLoadDialog expects a string, and optionally a ptKey and second string");
PYTHON_RETURN_ERROR;
}
pyKey* key = pyKey::ConvertFrom(keyObj);
if (ageName)
cyMisc::LoadDialogKA(dialogName, *key, ageName);
else
cyMisc::LoadDialogK(dialogName, *key);
}
else
cyMisc::LoadDialog(dialogName);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtUnloadDialog, args, "Params: dialogName\nThis will unload the GUI dialog by name. If not loaded then nothing will happen")
{
char* dialogName;
if (!PyArg_ParseTuple(args, "s", &dialogName))
{
PyErr_SetString(PyExc_TypeError, "PtUnloadDialog expects a string");
PYTHON_RETURN_ERROR;
}
cyMisc::UnloadDialog(dialogName);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtIsDialogLoaded, args, "Params: dialogName\nTest to see if a GUI dialog is loaded, by name")
{
char* dialogName;
if (!PyArg_ParseTuple(args, "s", &dialogName))
{
PyErr_SetString(PyExc_TypeError, "PtIsDialogLoaded expects a string");
PYTHON_RETURN_ERROR;
}
PYTHON_RETURN_BOOL(cyMisc::IsDialogLoaded(dialogName));
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtShowDialog, args, "Params: dialogName\nShow a GUI dialog by name (does not load dialog)")
{
char* dialogName;
if (!PyArg_ParseTuple(args, "s", &dialogName))
{
PyErr_SetString(PyExc_TypeError, "PtShowDialog expects a string");
PYTHON_RETURN_ERROR;
}
cyMisc::ShowDialog(dialogName);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtHideDialog, args, "Params: dialogName\nHide a GUI dialog by name (does not unload dialog)")
{
char* dialogName;
if (!PyArg_ParseTuple(args, "s", &dialogName))
{
PyErr_SetString(PyExc_TypeError, "PtHideDialog expects a string");
PYTHON_RETURN_ERROR;
}
cyMisc::HideDialog(dialogName);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtGetDialogFromTagID, args, "Params: tagID\nReturns the dialog associated with the tagID")
{
unsigned long tagID;
if (!PyArg_ParseTuple(args, "l", &tagID))
{
PyErr_SetString(PyExc_TypeError, "PtGetDialogFromTagID expects a long");
PYTHON_RETURN_ERROR;
}
return cyMisc::GetDialogFromTagID(tagID);
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtGetDialogFromString, args, "Params: dialogName\nGet a ptGUIDialog from its name")
{
char* dialogName;
if (!PyArg_ParseTuple(args, "s", &dialogName))
{
PyErr_SetString(PyExc_TypeError, "PtHideDialog expects a string");
PYTHON_RETURN_ERROR;
}
return cyMisc::GetDialogFromString(dialogName);
}
PYTHON_GLOBAL_METHOD_DEFINITION_NOARGS(PtIsGUIModal, "Returns true if the GUI is displaying a modal dialog and blocking input")
{
PYTHON_RETURN_BOOL(cyMisc::IsGUIModal());
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtSendPrivateChatList, args, "Params: chatList\nLock the local avatar into private vox messaging, and / or add new members to his chat list")
{
PyObject* chatListObj = NULL;
if (!PyArg_ParseTuple(args, "O", &chatListObj))
{
PyErr_SetString(PyExc_TypeError, "PtSendPrivateChatList expects a list of ptPlayers");
PYTHON_RETURN_ERROR;
}
std::vector<pyPlayer*> chatList;
if (PyList_Check(chatListObj))
{
int listSize = PyList_Size(chatListObj);
for (int i = 0; i < listSize; i++)
{
PyObject* listItem = PyList_GetItem(chatListObj, i);
if (!pyPlayer::Check(listItem))
{
PyErr_SetString(PyExc_TypeError, "PtSendPrivateChatList expects a list of ptPlayers");
PYTHON_RETURN_ERROR;
}
chatList.push_back(pyPlayer::ConvertFrom(listItem));
}
}
else
{
PyErr_SetString(PyExc_TypeError, "PtSendPrivateChatList expects a list of ptPlayers");
PYTHON_RETURN_ERROR;
}
cyMisc::SetPrivateChatList(chatList);
PYTHON_RETURN_NONE;
}
PYTHON_GLOBAL_METHOD_DEFINITION(PtClearPrivateChatList, args, "Params: memberKey\nRemove the local avatar from private vox messaging, and / or clear members from his chat list")
{
PyObject* keyObj = NULL;
if (!PyArg_ParseTuple(args, "O", &keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtClearPrivateChatList expects a ptKey");
PYTHON_RETURN_ERROR;
}
if (!pyKey::Check(keyObj))
{
PyErr_SetString(PyExc_TypeError, "PtClearPrivateChatList expects a ptKey");
PYTHON_RETURN_ERROR;
}
pyKey* key = pyKey::ConvertFrom(keyObj);
cyMisc::ClearPrivateChatList(*key);
PYTHON_RETURN_NONE;
}
///////////////////////////////////////////////////////////////////////////
//
// AddPlasmaMethods - the python method definitions
//
void cyMisc::AddPlasmaMethods2(std::vector<PyMethodDef> &methods)
{
PYTHON_GLOBAL_METHOD(methods, PtYesNoDialog);
PYTHON_GLOBAL_METHOD(methods, PtRateIt);
PYTHON_GLOBAL_METHOD(methods, PtExcludeRegionSet);
PYTHON_GLOBAL_METHOD(methods, PtExcludeRegionSetNow);
PYTHON_GLOBAL_METHOD(methods, PtAcceptInviteInGame);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetTime);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetGameTime);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtGetFrameDeltaTime);
PYTHON_GLOBAL_METHOD(methods, PtPageInNode);
PYTHON_GLOBAL_METHOD(methods, PtPageOutNode);
PYTHON_GLOBAL_METHOD(methods, PtLimitAvatarLOD);
PYTHON_GLOBAL_METHOD(methods, PtFogSetDefColor);
PYTHON_GLOBAL_METHOD(methods, PtFogSetDefLinear);
PYTHON_GLOBAL_METHOD(methods, PtFogSetDefExp);
PYTHON_GLOBAL_METHOD(methods, PtFogSetDefExp2);
PYTHON_GLOBAL_METHOD(methods, PtLoadDialog);
PYTHON_GLOBAL_METHOD(methods, PtUnloadDialog);
PYTHON_GLOBAL_METHOD(methods, PtIsDialogLoaded);
PYTHON_GLOBAL_METHOD(methods, PtShowDialog);
PYTHON_GLOBAL_METHOD(methods, PtHideDialog);
PYTHON_GLOBAL_METHOD(methods, PtGetDialogFromTagID);
PYTHON_GLOBAL_METHOD(methods, PtGetDialogFromString);
PYTHON_GLOBAL_METHOD_NOARGS(methods, PtIsGUIModal);
PYTHON_GLOBAL_METHOD(methods, PtSendPrivateChatList);
PYTHON_GLOBAL_METHOD(methods, PtClearPrivateChatList);
}
void cyMisc::AddPlasmaConstantsClasses(PyObject *m)
{
PYTHON_ENUM_START(PtCCRPetitionType);
PYTHON_ENUM_ELEMENT(PtCCRPetitionType, kGeneralHelp,plNetCommon::PetitionTypes::kGeneralHelp);
PYTHON_ENUM_ELEMENT(PtCCRPetitionType, kBug, plNetCommon::PetitionTypes::kBug);
PYTHON_ENUM_ELEMENT(PtCCRPetitionType, kFeedback, plNetCommon::PetitionTypes::kFeedback);
PYTHON_ENUM_ELEMENT(PtCCRPetitionType, kExploit, plNetCommon::PetitionTypes::kExploit);
PYTHON_ENUM_ELEMENT(PtCCRPetitionType, kHarass, plNetCommon::PetitionTypes::kHarass);
PYTHON_ENUM_ELEMENT(PtCCRPetitionType, kStuck, plNetCommon::PetitionTypes::kStuck);
PYTHON_ENUM_ELEMENT(PtCCRPetitionType, kTechnical, plNetCommon::PetitionTypes::kTechnical);
PYTHON_ENUM_END(m, PtCCRPetitionType);
PYTHON_ENUM_START(PtLanguage);
PYTHON_ENUM_ELEMENT(PtLanguage, kEnglish, plLocalization::kEnglish);
PYTHON_ENUM_ELEMENT(PtLanguage, kFrench, plLocalization::kFrench);
PYTHON_ENUM_ELEMENT(PtLanguage, kGerman, plLocalization::kGerman);
PYTHON_ENUM_ELEMENT(PtLanguage, kSpanish, plLocalization::kSpanish);
PYTHON_ENUM_ELEMENT(PtLanguage, kItalian, plLocalization::kItalian);
PYTHON_ENUM_ELEMENT(PtLanguage, kJapanese, plLocalization::kJapanese);
PYTHON_ENUM_ELEMENT(PtLanguage, kNumLanguages, plLocalization::kNumLanguages);
PYTHON_ENUM_END(m, PtLanguage);
PYTHON_ENUM_START(PtLOSReportType);
PYTHON_ENUM_ELEMENT(PtLOSReportType, kReportHit, plLOSRequestMsg::kReportHit);
PYTHON_ENUM_ELEMENT(PtLOSReportType, kReportMiss, plLOSRequestMsg::kReportMiss);
PYTHON_ENUM_ELEMENT(PtLOSReportType, kReportHitOrMiss, plLOSRequestMsg::kReportHitOrMiss);
PYTHON_ENUM_END(m, PtLOSReportType);
PYTHON_ENUM_START(PtLOSObjectType);
PYTHON_ENUM_ELEMENT(PtLOSObjectType, kClickables, kClickables);
PYTHON_ENUM_ELEMENT(PtLOSObjectType, kCameraBlockers, kCameraBlockers);
PYTHON_ENUM_ELEMENT(PtLOSObjectType, kCustom, kCustom);
PYTHON_ENUM_ELEMENT(PtLOSObjectType, kShootable, kShootable);
PYTHON_ENUM_END(m, PtLOSObjectType);
}