/* * 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); }