Perl will now capture return values (lua style), yeah I said I wouldn't be improving much of perl from here on but I said if I found a way I'd do it.

This commit is contained in:
KimLS 2013-07-05 02:56:53 -07:00
parent b11ed32bcf
commit 3c8d83f2a8
4 changed files with 65 additions and 53 deletions

View File

@ -152,14 +152,14 @@ void PerlembParser::ReloadQuests() {
spell_quest_status_.clear(); 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<void*> *extra_pointers) uint32 extradata, bool global, std::vector<void*> *extra_pointers)
{ {
if(!perl) if(!perl)
return; return 0;
if(event >= _LargestEventID) if(event >= _LargestEventID)
return; return 0;
bool isPlayerQuest = false; bool isPlayerQuest = false;
bool isGlobalPlayerQuest = false; bool isGlobalPlayerQuest = false;
@ -175,7 +175,7 @@ void PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * d
const char *sub_name = QuestEventSubroutines[event]; const char *sub_name = QuestEventSubroutines[event];
if(!perl->SubExists(package_name.c_str(), sub_name)) { if(!perl->SubExists(package_name.c_str(), sub_name)) {
return; return 0;
} }
int char_id = 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); ExportEventVariables(package_name, event, objid, data, npcmob, iteminst, mob, extradata, extra_pointers);
if(isPlayerQuest || isGlobalPlayerQuest){ 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) { 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) else if(isSpellQuest)
{ {
if(mob) { 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 { } 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 { 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, int PerlembParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { std::vector<void*> *extra_pointers) {
EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, false, extra_pointers); return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, false, extra_pointers);
return 0;
} }
int PerlembParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, int PerlembParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { std::vector<void*> *extra_pointers) {
EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, true, extra_pointers); return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, true, extra_pointers);
return 0;
} }
int PerlembParser::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, int PerlembParser::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { std::vector<void*> *extra_pointers) {
EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, false, extra_pointers); return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, false, extra_pointers);
return 0;
} }
int PerlembParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, int PerlembParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { std::vector<void*> *extra_pointers) {
EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, true, extra_pointers); return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, true, extra_pointers);
return 0;
} }
int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { std::vector<void*> *extra_pointers) {
EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, extra_pointers); return EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, extra_pointers);
return 0;
} }
int PerlembParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, int PerlembParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) { std::vector<void*> *extra_pointers) {
EventCommon(evt, 0, itoa(spell_id), npc, nullptr, client, extra_data, false, extra_pointers); return EventCommon(evt, 0, itoa(spell_id), npc, nullptr, client, extra_data, false, extra_pointers);
return 0;
} }
bool PerlembParser::HasQuestSub(uint32 npcid, QuestEventID evt) { 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) if(!perl)
return; return 0;
int ret_value = 0;
if(mob && mob->IsClient()) if(mob && mob->IsClient())
quest_manager.StartQuest(other, mob->CastToClient(), iteminst); quest_manager.StartQuest(other, mob->CastToClient(), iteminst);
else else
@ -671,7 +666,7 @@ void PerlembParser::SendCommands(const char *pkgprefix, const char *event, uint3
#endif #endif
//now call the requested sub //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 #ifdef EMBPERL_XS_CLASSES
std::string eval_str = (std::string)"$" + (std::string)pkgprefix + (std::string)"::client = undef;"; 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(); quest_manager.EndQuest();
return ret_value;
} }
void PerlembParser::MapFunctions() { void PerlembParser::MapFunctions() {

View File

@ -85,9 +85,9 @@ private:
void ExportVar(const char *pkgprefix, const char *varname, float value); void ExportVar(const char *pkgprefix, const char *varname, float value);
void ExportVarComplex(const char *pkgprefix, const char *varname, const char *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<void*> *extra_pointers); uint32 extradata, bool global, std::vector<void*> *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 MapFunctions();
void GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, void GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest,

View File

@ -250,56 +250,72 @@ void Embperl::init_eval_file(void)
,FALSE); ,FALSE);
} }
void Embperl::eval_file(const char * packagename, const char * filename) int Embperl::eval_file(const char * packagename, const char * filename)
{ {
std::vector<std::string> args; std::vector<std::string> args;
args.push_back(packagename); args.push_back(packagename);
args.push_back(filename); args.push_back(filename);
dosub("main::eval_file", &args); return dosub("main::eval_file", &args);
} }
void Embperl::dosub(const char * subname, const std::vector<std::string> * args, int mode) int Embperl::dosub(const char * subname, const std::vector<std::string> * args, int mode)
{ {
in_use = true; dSP;
bool err = false; int ret_value = 0;
dSP; /* initialize stack pointer */ int count;
ENTER; /* everything created after here */ std::string error;
SAVETMPS; /* ...is a temporary variable. */
PUSHMARK(SP); /* remember the stack pointer */ ENTER;
SAVETMPS;
PUSHMARK(SP);
if(args && args->size()) if(args && args->size())
{ {
for(std::vector<std::string>::const_iterator i = args->begin(); i != args->end(); ++i) for(std::vector<std::string>::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()))); XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length())));
} }
} }
PUTBACK; /* make local stack pointer global */ PUTBACK;
call_pv(subname, mode); /*eval our code*/
SPAGAIN; /* refresh stack pointer */ count = call_pv(subname, mode);
SPAGAIN;
if(SvTRUE(ERRSV)) if(SvTRUE(ERRSV))
{ {
err = true; error = SvPV_nolen(ERRSV);
POPs;
} }
FREETMPS; /* free temp values */ else
LEAVE; /* ...and the XPUSHed "mortal" args.*/
in_use = false;
if(err)
{ {
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); errmsg += SvPVX(ERRSV);
throw errmsg.c_str(); throw errmsg.c_str();
} }
return ret_value;
} }
//evaluate an expression. throw error on fail //evaluate an expression. throw error on fail
void Embperl::eval(const char * code) int Embperl::eval(const char * code)
{ {
std::vector<std::string> arg; std::vector<std::string> arg;
arg.push_back(code); arg.push_back(code);
// MYRA - added EVAL & KEEPERR to eval per Eglin's recommendation return dosub("main::my_eval", &arg, G_SCALAR|G_EVAL|G_KEEPERR);
dosub("main::my_eval", &arg, G_SCALAR|G_DISCARD|G_EVAL|G_KEEPERR);
//end Myra
} }
bool Embperl::SubExists(const char *package, const char *sub) { bool Embperl::SubExists(const char *package, const char *sub) {

View File

@ -89,9 +89,9 @@ public:
//return the last error msg //return the last error msg
std::string lasterr(void) const { return errmsg;}; std::string lasterr(void) const { return errmsg;};
//evaluate an expression. throws string errors on fail //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 //execute a subroutine. throws lasterr on failure
void dosub(const char * subname, const std::vector<std::string> * args = nullptr, int mode = G_SCALAR|G_DISCARD|G_EVAL); int dosub(const char * subname, const std::vector<std::string> * args = nullptr, int mode = G_SCALAR|G_EVAL);
//Access to perl variables //Access to perl variables
//all varnames here should be of the form package::name //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) //loads a file and compiles it into our interpreter (assuming it hasn't already been read in)
//idea borrowed from perlembed //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); } inline bool InUse() const { return(in_use); }