diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 3547bad2d..c04834788 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -152,14 +152,14 @@ void PerlembParser::ReloadQuests() { spell_quest_status_.clear(); } -void PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, +int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, bool global, std::vector *extra_pointers) { if(!perl) - return; + return 0; if(event >= _LargestEventID) - return; + return 0; bool isPlayerQuest = false; bool isGlobalPlayerQuest = false; @@ -175,7 +175,7 @@ void PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * d const char *sub_name = QuestEventSubroutines[event]; if(!perl->SubExists(package_name.c_str(), sub_name)) { - return; + return 0; } int char_id = 0; @@ -191,58 +191,52 @@ void PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * d ExportEventVariables(package_name, event, objid, data, npcmob, iteminst, mob, extradata, extra_pointers); if(isPlayerQuest || isGlobalPlayerQuest){ - SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr); + return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr); } else if(isItemQuest) { - SendCommands(package_name.c_str(), sub_name, 0, mob, mob, iteminst); + return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, iteminst); } else if(isSpellQuest) { if(mob) { - SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr); + return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr); } else { - SendCommands(package_name.c_str(), sub_name, 0, npcmob, mob, nullptr); + return SendCommands(package_name.c_str(), sub_name, 0, npcmob, mob, nullptr); } } else { - SendCommands(package_name.c_str(), sub_name, objid, npcmob, mob, nullptr); + return SendCommands(package_name.c_str(), sub_name, objid, npcmob, mob, nullptr); } } int PerlembParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { - EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, false, extra_pointers); - return 0; + return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, false, extra_pointers); } int PerlembParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { - EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, true, extra_pointers); - return 0; + return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, true, extra_pointers); } int PerlembParser::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, false, extra_pointers); - return 0; + return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, false, extra_pointers); } int PerlembParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, true, extra_pointers); - return 0; + return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, true, extra_pointers); } int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { - EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, extra_pointers); - return 0; + return EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, extra_pointers); } int PerlembParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers) { - EventCommon(evt, 0, itoa(spell_id), npc, nullptr, client, extra_data, false, extra_pointers); - return 0; + return EventCommon(evt, 0, itoa(spell_id), npc, nullptr, client, extra_data, false, extra_pointers); } bool PerlembParser::HasQuestSub(uint32 npcid, QuestEventID evt) { @@ -621,10 +615,11 @@ void PerlembParser::ExportVar(const char *pkgprefix, const char *varname, const } } -void PerlembParser::SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, ItemInst* iteminst) { +int PerlembParser::SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, ItemInst* iteminst) { if(!perl) - return; + return 0; + int ret_value = 0; if(mob && mob->IsClient()) quest_manager.StartQuest(other, mob->CastToClient(), iteminst); else @@ -671,7 +666,7 @@ void PerlembParser::SendCommands(const char *pkgprefix, const char *event, uint3 #endif //now call the requested sub - perl->dosub(std::string(pkgprefix).append("::").append(event).c_str()); + ret_value = perl->dosub(std::string(pkgprefix).append("::").append(event).c_str()); #ifdef EMBPERL_XS_CLASSES std::string eval_str = (std::string)"$" + (std::string)pkgprefix + (std::string)"::client = undef;"; @@ -697,6 +692,7 @@ void PerlembParser::SendCommands(const char *pkgprefix, const char *event, uint3 } quest_manager.EndQuest(); + return ret_value; } void PerlembParser::MapFunctions() { diff --git a/zone/embparser.h b/zone/embparser.h index 5e0a2c7bf..2540402b2 100644 --- a/zone/embparser.h +++ b/zone/embparser.h @@ -85,9 +85,9 @@ private: void ExportVar(const char *pkgprefix, const char *varname, float value); void ExportVarComplex(const char *pkgprefix, const char *varname, const char *value); - void EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, + int EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, bool global, std::vector *extra_pointers); - void SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, ItemInst *iteminst); + int SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, ItemInst *iteminst); void MapFunctions(); void GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, diff --git a/zone/embperl.cpp b/zone/embperl.cpp index e088ce42c..7bd4db2b5 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -250,56 +250,72 @@ void Embperl::init_eval_file(void) ,FALSE); } -void Embperl::eval_file(const char * packagename, const char * filename) +int Embperl::eval_file(const char * packagename, const char * filename) { std::vector args; args.push_back(packagename); args.push_back(filename); - dosub("main::eval_file", &args); + return dosub("main::eval_file", &args); } -void Embperl::dosub(const char * subname, const std::vector * args, int mode) +int Embperl::dosub(const char * subname, const std::vector * args, int mode) { - in_use = true; - bool err = false; - dSP; /* initialize stack pointer */ - ENTER; /* everything created after here */ - SAVETMPS; /* ...is a temporary variable. */ - PUSHMARK(SP); /* remember the stack pointer */ + dSP; + int ret_value = 0; + int count; + std::string error; + + ENTER; + SAVETMPS; + PUSHMARK(SP); if(args && args->size()) { for(std::vector::const_iterator i = args->begin(); i != args->end(); ++i) - {/* push the arguments onto the perl stack */ + { XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length()))); } } - PUTBACK; /* make local stack pointer global */ - call_pv(subname, mode); /*eval our code*/ - SPAGAIN; /* refresh stack pointer */ + PUTBACK; + + count = call_pv(subname, mode); + SPAGAIN; + if(SvTRUE(ERRSV)) { - err = true; + error = SvPV_nolen(ERRSV); + POPs; } - FREETMPS; /* free temp values */ - LEAVE; /* ...and the XPUSHed "mortal" args.*/ - - in_use = false; - if(err) + else { - errmsg = "Perl runtime error: "; + if(count == 1) { + SV *ret = POPs; + if(SvTYPE(ret) == SVt_IV) { + IV v = SvIV(ret); + ret_value = v; + } + PUTBACK; + } + } + + FREETMPS; + LEAVE; + + if(error.length() > 0) + { + std::string errmsg = "Perl runtime error: "; errmsg += SvPVX(ERRSV); throw errmsg.c_str(); } + + return ret_value; } //evaluate an expression. throw error on fail -void Embperl::eval(const char * code) +int Embperl::eval(const char * code) { std::vector arg; arg.push_back(code); -// MYRA - added EVAL & KEEPERR to eval per Eglin's recommendation - dosub("main::my_eval", &arg, G_SCALAR|G_DISCARD|G_EVAL|G_KEEPERR); -//end Myra + return dosub("main::my_eval", &arg, G_SCALAR|G_EVAL|G_KEEPERR); } bool Embperl::SubExists(const char *package, const char *sub) { diff --git a/zone/embperl.h b/zone/embperl.h index 668755c25..016676769 100644 --- a/zone/embperl.h +++ b/zone/embperl.h @@ -89,9 +89,9 @@ public: //return the last error msg std::string lasterr(void) const { return errmsg;}; //evaluate an expression. throws string errors on fail - void eval(const char * code); + int eval(const char * code); //execute a subroutine. throws lasterr on failure - void dosub(const char * subname, const std::vector * args = nullptr, int mode = G_SCALAR|G_DISCARD|G_EVAL); + int dosub(const char * subname, const std::vector * args = nullptr, int mode = G_SCALAR|G_EVAL); //Access to perl variables //all varnames here should be of the form package::name @@ -145,7 +145,7 @@ public: //loads a file and compiles it into our interpreter (assuming it hasn't already been read in) //idea borrowed from perlembed - void eval_file(const char * packagename, const char * filename); + int eval_file(const char * packagename, const char * filename); inline bool InUse() const { return(in_use); }