/*
* pythonHandler.h
* Class for handling Python <--> mud interactions
* ____ _
* | _ \ ___ __ _| |_ __ ___ ___
* | |_) / _ \/ _` | | '_ ` _ \/ __|
* | _ < __/ (_| | | | | | | \__ \
* |_| \_\___|\__,_|_|_| |_| |_|___/
*
* Permission to use, modify and distribute is granted via the
* Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License
* http://creativecommons.org/licenses/by-nc-sa/3.0/
*
* Copyright (C) 2007-2009 Jason Mitchell, Randi Mitchell
* Contributions by Tim Callahan, Jonathan Hseu
* Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
*
*/
// Mud Includes
#include "mud.h"
#include "pythonHandler.h"
namespace bp = boost::python;
struct BaseRoom_wrapper : BaseRoom, bp::wrapper< BaseRoom > {
BaseRoom_wrapper( )
: BaseRoom( )
, bp::wrapper< BaseRoom >(){
// null constructor
}
void BaseDestroy( ){
BaseRoom::BaseDestroy( );
}
virtual bool flagIsSet( int flag ) const {
bp::override func_flagIsSet = this->get_override( "flagIsSet" );
return func_flagIsSet( flag );
}
virtual ::Fishing const * getFishing( ) const {
bp::override func_getFishing = this->get_override( "getFishing" );
return func_getFishing( );
}
};
BOOST_PYTHON_MODULE(mud) {
class_<Config>("Config", no_init)
.def("getVersion",&Config::getVersion);
class_<Server>("Server", no_init)
.def("findPlayer",&Server::findPlayer,
return_value_policy<reference_existing_object>())
;
class_<MudObject>("MudObject", no_init)
.def("getName", &MudObject::getName)
;
def("dice", &::dice);
// class_<Player, bases<Creature> >("Player", no_init)
// ;
}
//BaseRoom *getRoom() const;
BOOST_PYTHON_MODULE(MudObjects) {
// boost::python::implicitly_convertible<int32_t, int64_t>();
// boost::python::implicitly_convertible<int64_t, int32_t>();
bp::class_< Stat, boost::noncopyable >( "Stat", bp::init< >() )
.def(
"addCur"
, (void ( ::Stat::* )( short int ) )( &::Stat::addCur )
, ( bp::arg("a") ) )
.def(
"addMax"
, (void ( ::Stat::* )( short int ) )( &::Stat::addMax )
, ( bp::arg("a") ) )
.def(
"adjust"
, (int ( ::Stat::* )( int,bool ) )( &::Stat::adjust )
, ( bp::arg("amt"), bp::arg("overMaxOk")=(bool)(false) ) )
.def(
"adjustMax"
, (int ( ::Stat::* )( int ) )( &::Stat::adjustMax )
, ( bp::arg("amt") ) )
.def(
"decrease"
, (int ( ::Stat::* )( int ) )( &::Stat::decrease )
, ( bp::arg("amt") ) )
.def(
"decreaseMax"
, (int ( ::Stat::* )( int ) )( &::Stat::decreaseMax )
, ( bp::arg("amt") ) )
.def(
"getCur"
, (short int ( ::Stat::* )( ) const)( &::Stat::getCur ) )
.def(
"getInitial"
, (short int ( ::Stat::* )( ) const)( &::Stat::getInitial ) )
.def(
"getMax"
, (short int ( ::Stat::* )( ) const)( &::Stat::getMax ) )
.def(
"increase"
, (int ( ::Stat::* )( int,bool ) )( &::Stat::increase )
, ( bp::arg("amt"), bp::arg("overMaxOk")=(bool)(false) ) )
.def(
"increaseMax"
, (int ( ::Stat::* )( int ) )( &::Stat::increaseMax )
, ( bp::arg("amt") ) )
.def(
"load"
, (bool ( ::Stat::* )( ::xmlNodePtr ) )( &::Stat::load )
, ( bp::arg("curNode") ) )
.def(
"restore"
, (int ( ::Stat::* )( ) )( &::Stat::restore ) )
.def(
"save"
, (void ( ::Stat::* )( ::xmlNodePtr,char const * ) const)( &::Stat::save )
, ( bp::arg("parentNode"), bp::arg("statName") ) )
.def(
"setCur"
, (int ( ::Stat::* )( short int ) )( &::Stat::setCur )
, ( bp::arg("newCur") ) )
.def(
"setInitial"
, (void ( ::Stat::* )( short int ) )( &::Stat::setInitial )
, ( bp::arg("i") ) )
.def(
"setMax"
, (int ( ::Stat::* )( short int,bool ) )( &::Stat::setMax )
, ( bp::arg("newMax"), bp::arg("allowZero")=(bool)(false) ) );
{ //::BaseRoom
typedef bp::class_< BaseRoom_wrapper, bp::bases< MudObject >, boost::noncopyable > BaseRoom_exposer_t;
BaseRoom_exposer_t BaseRoom_exposer = BaseRoom_exposer_t( "BaseRoom", bp::no_init );
bp::scope BaseRoom_scope( BaseRoom_exposer );
BaseRoom_exposer.def( bp::init< >() );
{ //::BaseRoom::BaseDestroy
typedef void ( BaseRoom_wrapper::*BaseDestroy_function_type )( ) ;
BaseRoom_exposer.def(
"BaseDestroy"
, BaseDestroy_function_type( &BaseRoom_wrapper::BaseDestroy ) );
}
{ //::BaseRoom::findCreature
typedef ::Creature * ( ::BaseRoom::*findCreature_function_type )( ::Creature *,::bstring const &,bool,bool,bool ) ;
BaseRoom_exposer.def(
"findCreature"
, findCreature_function_type( &::BaseRoom::findCreaturePython )
, ( bp::arg("searcher"), bp::arg("name"), bp::arg("monFirst")=(bool)(true), bp::arg("firstAggro")=(bool)(false), bp::arg("exactMatch")=(bool)(false) )
,return_value_policy<reference_existing_object>());
}
}
class_<Creature, boost::noncopyable, bases<MudObject> >("Creature", no_init)
.def("send", &Creature::bPrint)
.def("getRoom", &Creature::getRoom, return_value_policy<reference_existing_object>())
.def("getName", &Creature::getName)
.def("getClass", &Creature::getClass)
.def("getLevel", &Creature::getLevel)
.def("getAlignment", &Creature::getAlignment)
.def("getArmor", &Creature::getArmor)
.def("getExperience", &Creature::getExperience)
.def("getClan", &Creature::getClan)
//.def("getType", &Creature::getType)
.def("getRace", &Creature::getRace)
.def("getSize", &Creature::getSize)
.def("getAttackPower", &Creature::getAttackPower)
.def("getDescription", &Creature::getDescription)
.def("checkMp", &Creature::checkMp)
.def("subMp", &Creature::subMp)
.def("smashInvis", &Creature::smashInvis)
.def("unhide", &Creature::unhide)
.def("unmist", &Creature::unmist)
.def("flagIsSet", &Creature::flagIsSet)
.def("setFlag", &Creature::setFlag)
.def("clearFlag", &Creature::clearFlag)
.def("toggleFlag", &Creature::toggleFlag)
.def("learnSpell", &Creature::setFlag)
.def("forgetSpell", &Creature::clearFlag)
.def("spellIsKnown", &Creature::spellIsKnown)
.def("learnLanguage", &Creature::learnLanguage)
.def("forgetLanguage", &Creature::forgetLanguage)
.def("languageIsKnown", &Creature::languageIsKnown)
.def("isEffected", &Creature::isEffected)
.def("hasPermEffect", &Creature::hasPermEffect)
// TODO: More effects stuff
.def("knowsSkill", &Creature::knowsSkill)
.def("getSkillLevel", &Creature::getSkillLevel)
.def("getSkillGained", &Creature::getSkillGained)
.def("addSkill", &Creature::addSkill)
.def("remSkill", &Creature::remSkill)
.def("setSkill", &Creature::setSkill)
.def("addExperience", &Creature::addExperience)
.def("subExperience", &Creature::subExperience)
.def("subAlignment", &Creature::subAlignment)
.def("setClass", &Creature::setClass)
.def("setClan", &Creature::setClan)
.def("setRace", &Creature::setRace)
.def("setLevel", &Creature::setLevel)
.def("subAlignment", &Creature::subAlignment)
.def("setSize", &Creature::setSize)
.def("getWeight", &Creature::getWeight)
.def("maxWeight", &Creature::maxWeight)
.def("isVampire", &Creature::isNewVampire)
.def("isWerewolf", &Creature::isNewWerewolf)
.def("isUndead", &Creature::isUndead)
.def("immuneCriticals", &Creature::immuneCriticals)
.def("immuneToPoison", &Creature::immuneToPoison)
.def("immuneToDisease", &Creature::immuneToDisease)
.def("isRace", &Creature::isRace)
.def("getSex", &Creature::getSex)
.def("isBrittle", &Creature::isBrittle)
.def("isBlind", &Creature::isBlind)
.def("isUnconscious", &Creature::isUnconscious)
.def("isBraindead", &Creature::isBraindead)
.def("isHidden", &Creature::isHidden)
.def("isInvisible", &Creature::isInvisible)
.def("isWatcher", &Creature::isWatcher)
.def("isStaff", &Creature::isStaff)
.def("isCt", &Creature::isCt)
.def("isDm", &Creature::isDm)
.def("isAdm", &Creature::isAdm)
.def("isPet", &Creature::isPet)
.def_readonly( "hp", &Creature::hp )
.def_readonly( "mp", &Creature::mp )
;
// .def("checkDie", &Creature::checkDie)
// .def("checkDieRobJail", &Creature::checkDieRobJail)
// .def("die", &Creature::die)
// .def("", &Creature::)
;
class_<Player, bases<Creature> >("Player", no_init)
;
class_<Object, bases<MudObject> >("Object", no_init)
.def("getType", &Object::getType)
.def("getWearflag", &Object::getWearflag)
.def("getShotsmax", &Object::getShotsmax)
.def("getShotscur", &Object::getShotscur)
.def("flagIsSet", &Object::flagIsSet)
.def("setFlag", &Object::setFlag)
.def("clearFlag", &Object::clearFlag)
.def("toggleFlag", &Object::toggleFlag)
;
// class_<BaseRoom, boost::noncopyable, bases<MudObject> >("BaseRoom", no_init)
// .def("findCreature", &BaseRoom::findCreature, return_value_policy<reference_existing_object>())
// ;
}
// This handles bstring to PythonString conversions
struct bstringToPythonStr {
static PyObject* convert(bstring const& s) {
return boost::python::incref(boost::python::object((std::string)(s)).ptr());
}
};
struct bstringFromPythonStr {
bstringFromPythonStr() {
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id<bstring>());
}
static void* convertible(PyObject* objPtr)
{
if(!PyString_Check(objPtr))
return 0;
return objPtr;
}
static void construct( PyObject* objPtr, boost::python::converter::rvalue_from_python_stage1_data* data)
{
const char* value = PyString_AsString(objPtr);
if (value == 0)
boost::python::throw_error_already_set();
void* storage = ((boost::python::converter::rvalue_from_python_storage<bstring>*)data)->storage.bytes;
new (storage) bstring(value);
data->convertible = storage;
}
};
// This will just test python for now
bool Server::initPython() {
try {
pythonHandler = new PythonHandler();
// Setup the bstring --> pythonStr converter
boost::python::to_python_converter<bstring, bstringToPythonStr>();
// And the pythonStr --> bstring converter
bstringFromPythonStr();
// ********************************************************
// * Module Initializations
// * Put any modules you would like available system wide
// * here, before Python is initialized below
PyImport_AppendInittab( "mud", &initmud );
PyImport_AppendInittab( "MudObjects", &initMudObjects );
// Now that we've imported the modules we want, initalize python and setup the main module
Py_Initialize();
object main_module((handle<>(borrowed(PyImport_AddModule("__main__")))));
pythonHandler->mainNamespace = main_module.attr("__dict__");
// Now import the modules we setup above
object mudModule( (handle<>(PyImport_ImportModule("mud"))) );
pythonHandler->mainNamespace["mud"] = mudModule;
object mudObjectsModule( (handle<>(PyImport_ImportModule("MudObjects"))) );
pythonHandler->mainNamespace["MudObjectsSystem"] = mudObjectsModule;
// Add in any objects we want
scope(mudModule).attr("gConfig") = ptr(gConfig); // Make the gConfig object available
scope(mudModule).attr("gServer") = ptr(gServer); // Make the gServer object available
// Run a python test command here
runPython("import sys\nprint \"Python Initialized! Running Version \" + mud.gConfig.getVersion()");
} catch( error_already_set) {
PyErr_Print();
}
return(true);
}
bool Server::cleanUpPython() {
Py_Finalize();
return(true);
}
// RunPython:
// pyScript: The script to be run
// actor: The actor of the script.
// target: The target of the script
bool Server::runPython(bstring pyScript, bstring args, MudObject *actor, MudObject *target) {
// TODO: Make sure python is initiliazed first
// Setup the local name space
object localNamespace( (handle<>(PyDict_New())));
localNamespace["args"] = args;
if(actor != NULL) {
Monster *mActor;
Player *pActor;
Object *oActor;
Room *rActor;
if((mActor = actor->getMonster())) {
localNamespace["actor"] = ptr(mActor);
} else if((pActor = actor->getPlayer())) {
localNamespace["actor"] = ptr(pActor);
} else if((oActor = actor->getObject())) {
localNamespace["actor"] = ptr(oActor);
} else if((rActor = actor->getRoom())) {
localNamespace["actor"] = ptr(rActor);
} else {
localNamespace["actor"] = ptr(actor);
}
}
if(target != NULL) {
Monster *mTarget;
Player *pTarget;
Object *oTarget;
Room *rTarget;
if((mTarget = target->getMonster())) {
localNamespace["target"] = ptr(mTarget);
} else if((pTarget = target->getPlayer())) {
localNamespace["target"] = ptr(pTarget);
} else if((oTarget = target->getObject())) {
localNamespace["target"] = ptr(oTarget);
} else if((rTarget = target->getRoom())) {
localNamespace["target"] = ptr(rTarget);
} else {
localNamespace["target"] = ptr(target);
}
}
try {
// Run a python test command here
handle<> ignored((
PyRun_String( pyScript.c_str(),
Py_file_input,
pythonHandler->mainNamespace.ptr(),
localNamespace.ptr() ) ));
}
catch( error_already_set) {
PyErr_Print();
return(false);
}
return(true);
}