8 #include "../../bscript/berror.h" 9 #include "../../bscript/bobject.h" 10 #include "../../bscript/bstruct.h" 11 #include "../../bscript/impstr.h" 12 #include "../../clib/logfacility.h" 13 #include "../../clib/rawtypes.h" 14 #include "../../clib/refptr.h" 15 #include "../../clib/sckutil.h" 16 #include "../../clib/threadhelp.h" 17 #include "../../clib/weakptr.h" 18 #include "../../plib/systemstate.h" 19 #include "../exscrobj.h" 20 #include "../globals/script_internals.h" 21 #include "../globals/state.h" 22 #include "../item/item.h" 23 #include "../mobile/attribute.h" 24 #include "../mobile/charactr.h" 25 #include "../mobile/npc.h" 26 #include "../network/auxclient.h" 27 #include "../network/packethelper.h" 28 #include "../network/packets.h" 29 #include "../pktdef.h" 30 #include "../polcfg.h" 31 #include "../poldbg.h" 32 #include "../polsem.h" 33 #include "../profile.h" 34 #include "../schedule.h" 35 #include "../scrdef.h" 36 #include "../scrsched.h" 37 #include "../scrstore.h" 38 #include "../skills.h" 40 #include "../uoexec.h" 45 #pragma comment( lib, "crypt32.lib" ) 47 #include <curl/curl.h> 51 #include <unordered_map> 57 using namespace Module;
91 using namespace Bscript;
106 warn_on_runaway( true ),
108 sleep_until_clock_( 0 ),
109 in_hold_list_( NO_LIST ),
112 wait_type( WAIT_UNKNOWN ),
113 max_eventqueue_size( MAX_EVENTQUEUE_SIZE ),
145 return new BLong( 1 );
148 return new BError(
"Could not find UOExecutor for current process." );
162 return new BError(
"Process not found" );
191 return new BLong( 0 );
202 return new BLong( 0 );
223 return new BLong( 0 );
234 const String* scriptname_str;
243 return new BError(
"Error in script name" );
247 return new BError(
"Script " + sd.
name() +
" does not exist." );
250 if ( new_uoemod ==
nullptr )
252 return new BError(
"Unable to start script" );
255 if ( new_uoemod !=
nullptr && this_uoemod !=
nullptr )
264 return new BError(
"Invalid parameter type" );
277 return new BLong( 0 );
280 const String* script_name;
287 return new BError(
"Error in script name" );
291 return new BError(
"Script " + script.
name() +
" does not exist." );
299 return new BError(
"No script defined for attribute " + attr->
name +
"." );
306 if ( prog.
get() != nullptr )
332 std::string msg =
"Unable to start skill script:";
333 msg += script.
c_str();
336 return new BLong( 0 );
338 return new BLong( 1 );
343 return new BError(
"Invalid parameter type" );
353 return new BLong( 1 );
357 return new BError(
"Invalid parameter type" );
364 return new BLong( 1 );
366 return new BLong( 0 );
372 if ( scriptname ==
nullptr )
373 return new BLong( 0 );
379 return new BError(
"Script descriptor error" );
382 return new BError(
"Script does not exist" );
392 if ( this_uoexec->
pChild ==
nullptr )
394 const String* scriptname_str;
403 return new BError(
"Error in script name" );
407 return new BError(
"Script " + sd.
name() +
" does not exist." );
410 if ( new_uoemod ==
nullptr )
412 return new BError(
"Unable to run script" );
416 new_uoemod->controller_ = this_uoemod->
controller_;
420 new_uoexec->
pParent = this_uoexec;
421 this_uoexec->
pChild = new_uoexec;
432 return new BLong( 0 );
436 return new BError(
"Invalid parameter type" );
444 ret =
new BLong( 1 );
449 this_uoexec->
pChild =
nullptr;
461 return new BLong( 1 );
465 return new BError(
"Invalid parameter type" );
477 return new BLong( 1 );
484 return new BLong( 1 );
496 if (
getParam( 0, newpri, 1, 255 ) )
499 priority =
static_cast<unsigned char>( newpri );
500 return new BLong( oldpri );
504 return new BError(
"Invalid parameter type" );
519 return new BLong( n );
523 return new BError(
"Invalid parameter type" );
534 return new BLong( 1 );
539 unsigned short param;
544 return new BLong( oldsize );
547 return new BError(
"Invalid parameter type" );
560 const char* url = str->
data();
562 urllen =
static_cast<unsigned int>( strlen( url ) );
566 msg->WriteFlipped<
u16>( urllen + 4u );
567 msg->Write( url, static_cast<u16>( urllen + 1 ) );
569 return new BLong( 1 );
573 return new BError(
"No client attached" );
578 return new BError(
"Invalid parameter type" );
588 if ( this_uoexec->
pChild ==
nullptr )
591 const String* scriptname_str;
594 int assume_string_int;
602 return new BError(
"Error in script name" );
606 return new BError(
"Script " + sd.
name() +
" does not exist." );
612 <<
"\tThe execution of this script can't be blocked!\n";
617 std::string hostname( host->
value() );
618 bool assume_string = assume_string_int != 0;
620 [uoexec_w, sd, hostname, port, scriptparam, assume_string]() {
622 bool success_open = s.
open( hostname.c_str(), port );
627 DEBUGLOG <<
"OpenConnection Script has been destroyed\n";
642 std::unique_ptr<Network::AuxClientThread> client(
647 return new BLong( 0 );
651 return new BError(
"Invalid parameter type" );
655 return new BError(
"Invalid parameter type" );
660 (
static_cast<std::string*
>( userp ) )->append( static_cast<char*>( contents ), size * nmemb );
669 if ( this_uoexec->
pChild ==
nullptr )
671 const String *url, *method;
679 <<
"\tThe execution of this script can't be blocked!\n";
685 std::shared_ptr<CURL> curl_sp( curl_easy_init(), curl_easy_cleanup );
686 CURL* curl = curl_sp.get();
689 curl_easy_setopt( curl, CURLOPT_URL, url->
data() );
690 curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, method->
data() );
693 struct curl_slist* chunk =
nullptr;
698 if ( data !=
nullptr )
700 curl_easy_setopt( curl, CURLOPT_COPYPOSTFIELDS, data->
getStringRep().c_str() );
709 for (
const auto& content : headers->
contents() )
712 std::string header = content.first +
": " + ref->
getStringRep();
713 chunk = curl_slist_append( chunk, header.c_str() );
715 curl_easy_setopt( curl, CURLOPT_HTTPHEADER, chunk );
720 CURL* curl = curl_sp.get();
722 std::string readBuffer;
723 curl_easy_setopt( curl, CURLOPT_WRITEDATA, &readBuffer );
726 res = curl_easy_perform( curl );
727 if ( chunk !=
nullptr )
728 curl_slist_free_all( chunk );
734 DEBUGLOG <<
"OpenConnection Script has been destroyed\n";
738 if ( res != CURLE_OK )
754 return new BError(
"curl_easy_init() failed" );
759 return new BError(
"Invalid parameter type" );
763 return new BError(
"Invalid parameter type" );
811 << npcemod->
npc.
x <<
" " << npcemod->
npc.
y <<
" " << npcemod->
npc.
z <<
")\n";
894 case SCRIPTOPT_NO_INTERRUPT:
898 case SCRIPTOPT_DEBUG:
905 case SCRIPTOPT_NO_RUNAWAY:
909 case SCRIPTOPT_CAN_ACCESS_OFFLINE_MOBILES:
916 case SCRIPTOPT_AUXSVC_ASSUME_STRING:
924 return new BError(
"Unknown Script Option" );
926 return new BLong( oldval );
930 return new BError(
"Invalid parameter type" );
941 struct ScriptDiffData
946 ScriptDiffData( Core::UOExecutor* ex )
947 : name( ex->
scriptname() ), instructions( ex->instr_cycles ), pid( ex->os_module->pid() )
950 ScriptDiffData( Core::UOExecutor* ex,
u64 instr ) : ScriptDiffData( ex )
952 instructions -= instr;
953 auto uoemod =
static_cast<Module::UOExecutorModule*
>( ex->findModule(
"uo" ) );
954 if ( uoemod->attached_chr_ !=
nullptr )
955 name +=
" (" + uoemod->attached_chr_->name() +
")";
956 else if ( uoemod->attached_npc_ !=
nullptr )
957 name +=
" (" +
static_cast<Mobile::NPC*
>( uoemod->attached_npc_ )->templatename() +
")";
958 else if ( uoemod->attached_item_ )
959 name +=
" (" + uoemod->attached_item_->name() +
")";
962 bool operator>(
const ScriptDiffData& other )
const {
return instructions > other.instructions; }
966 std::unordered_map<u64, ScriptDiffData>
data;
970 : data(), uoexec_w( weak_ex ), max_scripts( max_count )
973 static void collect_perf( PerfData* data_ptr )
975 std::unique_ptr<PerfData>
data( data_ptr );
976 std::vector<ScriptDiffData> res;
977 if ( !data->uoexec_w.exists() )
979 DEBUGLOG <<
"PerformanceMeasure Script has been destroyed\n";
982 double sum_instr( 0 );
987 auto collect = [&]( Core::UOExecutor* scr ) {
988 auto itr = data->data.find( scr->os_module->pid() );
989 if ( itr == data->data.end() )
991 res.emplace_back( scr, itr->second.instructions );
992 sum_instr += res.back().instructions;
994 for (
const auto& scr : runlist )
996 for (
const auto& scr : ranlist )
998 for (
const auto& scr : holdlist )
999 collect( scr.second );
1000 for (
const auto& scr : notimeoutholdlist )
1002 std::sort( res.begin(), res.end(), std::greater<ScriptDiffData>() );
1004 std::unique_ptr<ObjArray> arr(
new ObjArray );
1005 for (
size_t i = 0; i < res.size() && i < data->max_scripts; ++i )
1007 std::unique_ptr<BStruct> elem(
new BStruct );
1008 elem->addMember(
"name",
new String( res[i].
name ) );
1009 elem->addMember(
"instructions",
new Double( static_cast<double>( res[i].
instructions ) ) );
1010 elem->addMember(
"pid",
new BLong( static_cast<int>( res[i].
pid ) ) );
1011 elem->addMember(
"percent",
new Double( res[i].instructions / sum_instr * 100.0 ) );
1012 arr->addElement( elem.release() );
1014 std::unique_ptr<BStruct> result(
new BStruct );
1015 result->addMember(
"scripts", arr.release() );
1016 result->addMember(
"total_number_observed",
new BLong( static_cast<int>( res.size() ) ) );
1017 result->addMember(
"total_instructions",
new Double( sum_instr ) );
1018 data->uoexec_w.get_weakptr()->ValueStack.back().set(
new BObject( result.release() ) );
1020 data->uoexec_w.get_weakptr()->os_module->revive();
1030 return new BError(
"Invalid parameter type" );
1035 if ( !this_uoexec->suspend() )
1037 DEBUGLOG <<
"Script Error in '" << this_uoexec->scriptname() <<
"' PC=" << this_uoexec->PC
1039 <<
"\tThe execution of this script can't be blocked!\n";
1048 std::unique_ptr<PerfData> perf(
new PerfData( this_uoexec->weakptr, max_scripts ) );
1049 for (
const auto& scr : runlist )
1050 perf->data.insert( std::make_pair( scr->os_module->pid(), ScriptDiffData( scr ) ) );
1051 for (
const auto& scr : ranlist )
1052 perf->data.insert( std::make_pair( scr->os_module->pid(), ScriptDiffData( scr ) ) );
1053 for (
const auto& scr : holdlist )
1055 std::make_pair( scr.second->os_module->pid(), ScriptDiffData( scr.second ) ) );
1056 for (
const auto& scr : notimeoutholdlist )
1057 perf->data.insert( std::make_pair( scr->os_module->pid(), ScriptDiffData( scr ) ) );
1061 PerfData::collect_perf, perf.release() );
1063 return new BLong( 0 );
size_t curlWriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
bool operator>(T *ptr, const ref_ptr< T > &rptr)
bool can_access_offline_mobiles
unsigned short max_eventqueue_size
bool auxsvc_assume_string
const ExecList & getRanlist()
virtual std::string getStringRep() const =0
const EScriptProgram * prog() const
ref_ptr< Bscript::EScriptProgram > find_script2(const ScriptDef &script, bool complain_if_not_found, bool cache_script)
Bscript::BObjectImp * mf_debugger()
const std::string & value() const
std::vector< FunctionDef > FunctionTable
bool in_debugger_holdlist() const
void setDebugLevel(DEBUG_LEVEL level)
ValueStackCont ValueStack
bool config_nodie(const std::string &name, const Plib::Package *pkg, const char *mainpfx)
const int SCRIPTOPT_AUXSVC_ASSUME_STRING
bool isa(BObjectType type) const
Bscript::BObjectImp * mf_unload_scripts()
Bscript::BObjectImp * is_critical()
bool find_uoexec(unsigned int pid, UOExecutor **pp_uoexec)
Bscript::BObjectImp * mf_set_script_option()
const HoldList & getHoldlist()
bool getParam(unsigned param, int &value)
bool signal_event(Bscript::BObjectImp *eventimp)
bool has_active_client() const
Bscript::BObjectImp * mf_Log()
const Contents & contents() const
virtual BObjectImp * copy() const =0
BObjectImp * getParamImp(unsigned param)
Core::CharacterRef controller_
bool open(const char *ipaddr, unsigned short port)
const ExecList & getRunlist()
Bscript::BObjectImp * mf_clear_event_queue()
int paramAsLong(unsigned param)
Bscript::BObjectImp * set_critical()
Bscript::BObjectImp * mf_system_rpm()
const char * paramAsString(unsigned param)
const int SCRIPTOPT_DEBUG
OSExecutorModule(Bscript::Executor &exec)
enum Pol::Module::OSExecutorModule::@9 in_hold_list_
int unload_script(const std::string &name_in)
Bscript::BObjectImp * events_waiting()
bool getAttributeParam(Executor &exec, unsigned param, const Mobile::Attribute *&attr)
const std::string & name() const
const int SCRIPTOPT_NO_INTERRUPT
std::unique_ptr< threadhelp::DynTaskThreadPool > auxthreadpool
void revive_timeout(UOExecutor *exec, TimeoutHandle hold_itr)
bool getCharacterParam(unsigned param, Mobile::Character *&chrptr)
Core::TimeoutHandle hold_itr_
NetworkManager networkManager
ExecutorModule * findModule(const std::string &name)
Bscript::BObjectImp * mf_set_event_queue_size()
Bscript::BObjectImp * getpid()
void Send(Client *client, int len=-1) const
void revive_notimeout(UOExecutor *exec)
Bscript::BObjectImp * start_script()
unsigned int getnewpid(Core::UOExecutor *uoexec)
std::queue< Bscript::BObjectImp * > events_
static UninitObject * create()
Bscript::BObjectImp * sleepms()
const int SCRIPTOPT_CAN_ACCESS_OFFLINE_MOBILES
weak_ptr< Core::UOExecutor > uoexec_w
Core::polclock_t sleep_until_clock_
const std::string & scriptname() const
const int SCRIPTOPT_NO_RUNAWAY
weak_ptr_owner< UOExecutor > weakptr
const String * getStringParam(unsigned param)
std::unordered_map< u64, ScriptDiffData > data
Bscript::BObjectImp * run_script_to_completion()
StateManager stateManager
BObjectImp * create_debug_context()
ScriptScheduler scriptScheduler
Bscript::BObjectImp * mf_OpenConnection()
bool CanUseSkill(Network::Client *client)
unsigned int get_new_pid(UOExecutor *exec)
Bscript::BObjectImp * mf_HTTPRequest()
Plib::Package const * pkg
const std::string & scriptname() const
const char * c_str() const
Bscript::BObjectImp * getprocess()
Bscript::BObjectImp * create_debug_context()
const String * getStringParam(unsigned param)
void revive_debugged(UOExecutor *exec)
Bscript::BObjectImp * mf_performance_diff()
bool run_script_to_completion(const char *filename, Bscript::BObjectImp *parameter)
Bscript::BObjectImp * mf_OpenURL()
bool start_script(Bscript::EScriptProgram *prog, bool start_attached, Bscript::BObjectImp *param2=nullptr, Bscript::BObjectImp *param3=nullptr, Bscript::BObjectImp *param4=nullptr)
const NoTimeoutHoldList & getNoTimeoutHoldlist()
Bscript::BObjectImp * sleep()
enum Pol::Module::OSExecutorModule::WAIT_TYPE wait_type
Bscript::BObjectImp * wait_for_event()
void start_script(const char *filename, Bscript::BObjectImp *param0, Bscript::BObjectImp *param1)
const char * data() const
Bscript::BObjectImp * run_script()
Bscript::BObjectImp * clear_event_queue()
const polclock_t POLCLOCKS_PER_SEC
const BObjectImp * FindMember(const char *name)
Bscript::BObjectImp * start_skill_script()
void freepid(unsigned int pid)
void send_sysmessage(Network::Client *client, const char *text, unsigned short font, unsigned short color)
void free_pid(unsigned int pid)
BObjectImp * getParamImp(unsigned param)
void SleepForMs(int msecs)
bool getParam(unsigned param, int &value)
Bscript::BObjectImp * mf_set_priority()
Bscript::BObjectImp * mf_set_debug()
#define INC_PROFILEVAR(counter)