Leviathan  0.8.0.0
Leviathan game engine
ScriptModule.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "ScriptModule.h"
3 
6 #include "Events/Event.h"
7 #include "FileSystem.h"
10 #include "ScriptExecutor.h"
11 #include "add_on/serializer/serializer.h"
12 
13 #include <boost/filesystem.hpp>
14 using namespace Leviathan;
15 // ------------------------------------ //
17  asIScriptEngine* engine, const std::string& name, int id, const std::string& source) :
18  Name(name),
19  Source(source), ID(id), ScriptBuilder(new CScriptBuilder())
20 {
21  {
22  Lock lock(ModuleBuildingMutex);
23  ModuleName = std::string(source + "_;" + Convert::ToString<int>(LatestAssigned));
24  LatestAssigned++;
25  }
26 
27  // module will always be started //
28  ScriptBuilder->StartNewModule(engine, ModuleName.c_str());
29 
30  // setup include resolver //
31  ScriptBuilder->SetIncludeCallback(ScriptModuleIncludeCallback, this);
32 
33  // Apply the default mask //
34  ScriptBuilder->GetModule()->SetAccessMask(AccessMask);
35 
36  ListenerDataBuilt = false;
37 }
38 
40 
42 {
43  GUARD_LOCK();
44 
45  // Leave from the bridge //
46  if(ArgsBridge)
47  ArgsBridge->LeaveModule();
48 
49 
50 #ifdef SCRIPTMODULE_LISTENFORFILECHANGES
51 
52  _StopFileMonitoring(guard);
53 
54 #endif // SCRIPTMODULE_LISTENFORFILECHANGES
55 
56  // We'll need to destroy the module from the engine //
57  ASModule = NULL;
58  ScriptExecutor::Get()->GetASEngine()->DiscardModule(ModuleName.c_str());
59 
60  // And then delete the builder //
61  SAFE_DELETE(ScriptBuilder);
62  ListenerDataBuilt = false;
63 }
64 
65 int Leviathan::ScriptModule::LatestAssigned = 0;
66 
67 const std::map<std::string, int> Leviathan::ScriptModule::ListenerNameType = {
78 
79 // ------------------------------------ //
81 {
82 
83  // we need to check build state //
84  if(ScriptState == SCRIPTBUILDSTATE_READYTOBUILD) {
85 
86  _BuildTheModule(guard);
87 
88 #ifdef SCRIPTMODULE_LISTENFORFILECHANGES
89 
90  _StartMonitoringFiles(guard);
91 
92 #endif // SCRIPTMODULE_LISTENFORFILECHANGES
93 
94  if(ScriptState != SCRIPTBUILDSTATE_BUILT) {
95 
96  return NULL;
97  }
98 
99  } else if(ScriptState == SCRIPTBUILDSTATE_FAILED ||
100  ScriptState == SCRIPTBUILDSTATE_DISCARDED) {
101 
102  return NULL;
103  }
104 
105  // Return the saved pointer or fetch the pointer //
106  if(!ASModule) {
107 
108  // Get module from the engine //
109  ASModule = ScriptExecutor::Get()->GetASEngine()->GetModule(
110  ModuleName.c_str(), asGM_ONLY_IF_EXISTS);
111 
112  if(!ASModule) {
113 
114  // The module is invalid //
115  LOG_ERROR("ScriptModule: GetModule: module is no longer anywhere "
116  "to be found in the AS engine");
117 
118  ScriptState = SCRIPTBUILDSTATE_DISCARDED;
119  return NULL;
120  }
121  }
122 
123  return ASModule;
124 }
125 // ------------------------------------ //
127 {
128 
129  return std::make_shared<ScriptScript>(ID, ScriptExecutor::Get()->GetModule(ID));
130 }
131 // ------------------------------------ //
133  const std::string& listenername, const std::string* generictype /*= NULL*/)
134 {
135  GUARD_LOCK();
136  // find from the map //
137  auto itr = _GetIteratorOfListener(guard, listenername, generictype);
138 
139  if(itr != FoundListenerFunctions.end()) {
140 
141  // it exists //
142  return true;
143  }
144  // no matching listener //
145  return false;
146 }
147 
149  std::vector<std::shared_ptr<ValidListenerData>>& receiver)
150 {
151  GUARD_LOCK();
152  // build info if not built //
153  if(!ListenerDataBuilt)
154  _BuildListenerList(guard);
155  // reserve space to be more efficient //
156  receiver.reserve(FoundListenerFunctions.size());
157 
158 
159  for(auto iter = FoundListenerFunctions.begin(); iter != FoundListenerFunctions.end();
160  ++iter) {
161  receiver.push_back(iter->second);
162  }
163 }
164 
166  const std::string& listenername, const std::string* generictype /*= NULL*/)
167 {
168  GUARD_LOCK();
169 
170  // Call search function and check if it found anything //
171  auto itr = _GetIteratorOfListener(guard, listenername, generictype);
172 
173 
174  if(itr != FoundListenerFunctions.end()) {
175  // Get name from pointer //
176  return std::string(itr->second->FuncPtr->GetName());
177  }
178 
179  // Nothing found //
180  return "";
181 }
182 // ------------------------------------ //
184 {
185 
186  return "ScriptModule(" + Convert::ToString(ID) + ") " + Name + ", from: " + Source;
187 }
188 
190 {
191 
192  // Tell script interface to unload this //
194 }
195 // ------------------------------------ //
196 void Leviathan::ScriptModule::_BuildListenerList(Lock& guard)
197 {
198 
199  // We need to find functions with metadata specifying which listener it is //
200  asIScriptModule* mod = GetModule(guard);
201 
202  if(!mod) {
203  // Module failed to build //
204  return;
205  }
206 
207  asUINT funccount = mod->GetFunctionCount();
208  // Loop all and check the ones with promising names //
209  for(asUINT i = 0; i < funccount; i++) {
210 
211  asIScriptFunction* tmpfunc = mod->GetFunctionByIndex(i);
212 
213 
214  // Get metadata for this and process it //
215  _ProcessMetadataForFunc(tmpfunc, mod);
216  }
217 
218  // Data is now built //
219  ListenerDataBuilt = true;
220 }
221 
222 void Leviathan::ScriptModule::_ProcessMetadataForFunc(
223  asIScriptFunction* func, asIScriptModule* mod)
224 {
225  // Start of by getting metadata string //
226  const auto& metaEntries = ScriptBuilder->GetMetadataForFunc(func);
227 
228  if(metaEntries.empty())
229  return;
230 
231  std::string meta = metaEntries.front();
233 
234  if(meta.size() < 1) {
235  // Too short for anything //
236  return;
237  }
238 
239  // Do all kinds of checks on the metadata //
240  if(meta[0] == '@') {
241  // Some specific special function, check which //
242 
243  // We need some iterating here //
244  StringIterator itr(meta);
245 
246  // need to skip first character don't want @ to be in the name //
247  itr.MoveToNext();
248 
249  // get until assignment //
250  auto metaname =
251  itr.GetUntilEqualityAssignment<std::string>(EQUALITYCHARACTER_TYPE_EQUALITY);
252 
253  // check name //
254  if(*metaname == "Listener") {
255  // it's a listener function //
256 
257  // get string in quotes to find out what it is //
258  auto listenername = itr.GetStringInQuotes<std::string>(QUOTETYPE_BOTH);
259 
260  std::string localname = *listenername;
261 
262  // if it is generic listener we need to get it's type //
263  if(*listenername == "Generic") {
264 
265  auto generictype = itr.GetStringInQuotes<std::string>(QUOTETYPE_BOTH);
266 
267  if(generictype->size() == 0) {
268 
269  LOG_WARNING("ScriptModule: ProcessMetadata: Generic listener has "
270  "no type defined (expected declaration like \""
271  "[@Listener=\"Generic\", @Type=\"ScoreUpdated\"]\"");
272  return;
273  }
274 
275  // mash together a name //
276  std::string mangledname = "Generic:" + *generictype + ";";
277  auto restofmeta = itr.GetUntilEnd<std::string>();
278 
279  FoundListenerFunctions[mangledname] =
280  std::shared_ptr<ValidListenerData>(new ValidListenerData(func,
281  listenername.release(), restofmeta.release(), generictype.release()));
282 
283  return;
284  }
285 
286 
287  // make iterator to skip spaces //
288  itr.SkipWhiteSpace();
289 
290  // match listener's name with OnFunction type //
291  auto positerator = ListenerNameType.find(*listenername);
292 
293  if(positerator != ListenerNameType.end()) {
294  // found a match, store info //
295  auto restofmeta = itr.GetUntilEnd<std::string>();
296  FoundListenerFunctions[localname] = std::shared_ptr<ValidListenerData>(
297  new ValidListenerData(func, listenername.release(), restofmeta.release()));
298 
299  return;
300  }
301  // we shouldn't have gotten here, error //
302  Logger::Get()->Error(
303  "ScriptModule: ProcessMetadata: invalid Listener name, " + *listenername);
304  }
305 
306 
307  } else {
308 
309  LOG_WARNING("ScriptModule: unknown metadata: " + meta);
310  }
311 }
312 
313 
314 std::map<std::string, std::shared_ptr<ValidListenerData>>::iterator
315  Leviathan::ScriptModule::_GetIteratorOfListener(Lock& guard,
316  const std::string& listenername, const std::string* generictype /*= NULL*/)
317 {
318  // build info if not built //
319  if(!ListenerDataBuilt)
320  _BuildListenerList(guard);
321 
322  // find from the map //
323  auto itr = FoundListenerFunctions.end();
324 
325  // different implementations for generic finding, because the name isn't usable as is //
326  if(!generictype) {
327  // default find is fine for known types //
328  itr = FoundListenerFunctions.find(listenername);
329 
330  } else {
331  // we need to find the right one by comparing strings inside the objects //
332  for(auto iter = FoundListenerFunctions.begin(); iter != FoundListenerFunctions.end();
333  ++iter) {
334  // strings are sorted alphabetically so we can skip until "Generic" //
335  if(iter->first.at(0) != 'G')
336  continue;
337  // check for matching generic name //
338  if(*iter->second->GenericTypeName == *generictype) {
339  // found right one, copy iterator and return //
340  itr = iter;
341  break;
342  }
343  }
344  }
345  // return whatever we might have found at this point //
346  return itr;
347 }
348 
350 {
351  GUARD_LOCK();
352 
353  // list consoles' global variables //
354  Logger::Get()->Info(Name + " instance functions: ");
355 
356  // List the user functions in the module
357  asIScriptModule* mod = GetModule(guard);
358 
359  const asUINT FuncCount = mod->GetFunctionCount();
360 
361  for(asUINT n = 0; n < FuncCount; n++) {
362  // get function //
363  asIScriptFunction* func = mod->GetFunctionByIndex(n);
364  // print the function //
365  Logger::Get()->Write(
366  std::string("> ") + func->GetName() + "(" + func->GetDeclaration() + ")");
367  }
368 
369  Logger::Get()->Write("[END]");
370 }
371 
373  const char* include, const char* from, CScriptBuilder* builder, void* userParam)
374 {
375  std::string file(include);
376  std::string infile(from);
377 
378  ScriptModule* module = reinterpret_cast<ScriptModule*>(userParam);
379  // The module has to be locked during this call
380 
381  // Resolve it to an usable path //
382  const auto resolved = ResolvePathToScriptFile(file, infile);
383 
384  if(resolved.empty() || !boost::filesystem::exists(resolved)) {
385 
386  Logger::Get()->Error("ScriptModule: IncludeCallback: couldn't resolve include "
387  "(even with full search), file: " +
388  file + " included in: " + infile + ", while compiling " +
389  module->GetInfoString());
390 
391  // Including failed
392  return -1;
393  }
394 
395 #ifdef SCRIPTMODULE_LISTENFORFILECHANGES
396 
397  module->_AddFileToMonitorIfNotAlready(resolved);
398 #endif // SCRIPTMODULE_LISTENFORFILECHANGES
399 
400  return builder->AddSectionFromFile(resolved.c_str());
401 }
402 // ------------------------------------ //
404 {
405  return ScriptSourceSegments.size();
406 }
407 
408 DLLEXPORT std::shared_ptr<ScriptSourceFileData> Leviathan::ScriptModule::GetScriptSegment(
409  size_t index) const
410 {
411  if(index >= ScriptSourceSegments.size())
412  return NULL;
413 
414  return ScriptSourceSegments[index];
415 }
416 
418  std::shared_ptr<ScriptSourceFileData> data)
419 {
420  GUARD_LOCK();
421  // Check is it already there //
422  for(size_t i = 0; i < ScriptSourceSegments.size(); i++) {
423 
424  if(ScriptSourceSegments[i]->SourceFile == data->SourceFile &&
425  (abs(ScriptSourceSegments[i]->StartLine - data->StartLine) <= 2)) {
426 
427  return false;
428  }
429  }
430 
431  ScriptSourceSegments.push_back(data);
432 
433  // Needs to be built next //
434  ScriptState = SCRIPTBUILDSTATE_READYTOBUILD;
435  return true;
436 }
437 
439 {
440  GUARD_LOCK();
441 
442  std::string expanded;
443 
444  try {
445  expanded = boost::filesystem::canonical(file).generic_string();
446  } catch(const boost::filesystem::filesystem_error&) {
447  // Doesn't exist //
448  return false;
449  }
450 
451  // Check is it already there //
452  for(size_t i = 0; i < ScriptSourceSegments.size(); i++) {
453 
454  if(ScriptSourceSegments[i]->SourceFile == file) {
455 
456  return false;
457  }
458  }
459 
460  // Load the source code from the file //
461  std::string scriptdata;
462  FileSystem::ReadFileEntirely(expanded, scriptdata);
463 
464  ScriptSourceSegments.push_back(
465  std::make_shared<ScriptSourceFileData>(expanded, 1, scriptdata));
466 
467  // Needs to be built next //
468  ScriptState = SCRIPTBUILDSTATE_READYTOBUILD;
469  return true;
470 }
471 
473 {
474  return ModuleName;
475 }
476 // ------------------------------------ //
478 {
479  GUARD_LOCK();
480 
481  ScriptState = SCRIPTBUILDSTATE_DISCARDED;
482 }
483 // ------------------------------------ //
485 {
486  GUARD_LOCK();
487 
488  // The module must be still valid //
489  if(ScriptState == SCRIPTBUILDSTATE_DISCARDED ||
490  (!GetModule() && ScriptState != SCRIPTBUILDSTATE_FAILED))
491  return false;
492 
493 
494  Logger::Get()->Info("Reloading " + GetInfoString());
495 
496  if(ArgsBridge) {
497 
498  // Do a OnRelease event call //
499  const std::string& listenername =
501 
502  // check does the script contain right listeners //
503  if(DoesListenersContainSpecificListener(listenername)) {
504 
505  // Get the parameters //
506  auto sargs = ArgsBridge->GetProvider()->GetParametersForRelease();
507  // sargs.Parameters need to be somehow translated to the new style
508  DEBUG_BREAK;
509  sargs->SetEntrypoint(GetListeningFunctionName(listenername));
510 
511  // Run the script //
512  auto result = ScriptExecutor::Get()->RunScript<void>(shared_from_this(), *sargs);
513 
514  if(result.Result != SCRIPT_RUN_RESULT::Success) {
515 
516  LOG_ERROR("ScriptModule: failed to run auto release, skipping reload");
517  return false;
518  } else {
519 
520  Logger::Get()->Info("ScriptModule: ran auto release");
521  }
522  }
523  }
524 
525 
526  // Store the old values //
527  // CSerializer backup;
528  // backup.Store(ASModule);
529 
530  // Discard the old module //
531  ASModule = NULL;
532  if(GetModule())
533  ScriptExecutor::Get()->GetASEngine()->DiscardModule(ModuleName.c_str());
534 
535  // The builder must be created again //
536  SAFE_DELETE(ScriptBuilder);
537 
538  // Setup the new builder //
539  ScriptBuilder = new CScriptBuilder();
540 
541  asIScriptEngine* engine = ScriptExecutor::Get()->GetASEngine();
542 
543  // Add 'R' to the module name to mark reload //
544  ModuleName += "R";
545 
546  ScriptBuilder->StartNewModule(engine, ModuleName.c_str());
547  ScriptBuilder->SetIncludeCallback(ScriptModuleIncludeCallback, this);
548  ListenerDataBuilt = false;
549 
550  // Build the module //
551  _BuildTheModule(guard);
552 
553  if(ScriptState != SCRIPTBUILDSTATE_BUILT || !GetModule()) {
554 
555  // Failed to build //
556  return false;
557  }
558 
559  // Restore the data //
560  // backup.Restore(GetModule());
561 
562  // Logger::Get()->Info("Successfully restored "+GetInfoStd::String());
563 
564  if(ArgsBridge) {
565 
566  // Do a OnRelease event call //
567  const std::string& listenername =
569 
570  // check does the script contain right listeners //
571  if(DoesListenersContainSpecificListener(listenername)) {
572 
573  // Get the parameters //
574  auto sargs = ArgsBridge->GetProvider()->GetParametersForInit();
575  // sargs.Parameters need to be somehow translated to the new style
576  DEBUG_BREAK;
577  sargs->SetEntrypoint(GetListeningFunctionName(listenername));
578 
579 
580  // Run the script //
581  auto result = ScriptExecutor::Get()->RunScript<void>(shared_from_this(), *sargs);
582 
583  if(result.Result != SCRIPT_RUN_RESULT::Success) {
584 
585  LOG_ERROR("ScriptModule: failed to run auto init after restore");
586  // We don't want to signal failure as we have already overwritten our old stuff
587  } else {
588 
589  Logger::Get()->Info("ScriptModule: ran auto init after restore");
590  }
591  }
592  }
593 
594  // Succeeded //
595  return true;
596 }
597 
598 #ifdef SCRIPTMODULE_LISTENFORFILECHANGES
599 
600 void Leviathan::ScriptModule::_StartMonitoringFiles(Lock& guard)
601 {
602 
603  // First add all the known source files //
604  auto end = ScriptSourceSegments.end();
605  for(auto iter = ScriptSourceSegments.begin(); iter != end; ++iter) {
606 
607 
608  _AddFileToMonitorIfNotAlready((*iter)->SourceFile);
609  }
610 
611  // The others should already have been included //
612  // Create listeners and we are good to go //
613  auto tmphandler = ResourceRefreshHandler::Get();
614 
615  if(!tmphandler) {
616 
617  return;
618  }
619 
620 
621  auto end2 = AlreadyMonitoredFiles.end();
622  for(auto iter = AlreadyMonitoredFiles.begin(); iter != end2; ++iter) {
623 
624  // Skip if already added //
625  if((*iter)->Added)
626  continue;
627 
628  std::vector<const std::string*> targetfiles;
629 
630  // Add our file //
631  targetfiles.push_back((*iter)->File.get());
632 
633  // Set this as added to avoid duplicates //
634  (*iter)->Added = true;
635 
636  // Find all files that are in the same folder //
637  std::string basepath = StringOperations::GetPath<std::string>(*(*iter)->File);
638 
639  for(auto iter2 = iter + 1; iter2 != end2; ++iter2) {
640 
641  if(basepath == StringOperations::GetPath<std::string>(*(*iter2)->File) &&
642  !(*iter2)->Added) {
643 
644  // This is in the same folder and thus can be monitored by the same listener //
645  targetfiles.push_back((*iter2)->File.get());
646 
647  // This, too, is now added //
648  (*iter2)->Added = true;
649  }
650  }
651 
652  // Start monitoring for them //
653  int listenerid;
654  tmphandler->ListenForFileChanges(targetfiles,
655  std::bind(&ScriptModule::_FileChanged, this, std::placeholders::_1,
656  std::placeholders::_2),
657  listenerid);
658 
659  FileListeners.push_back(listenerid);
660  }
661 }
662 
663 void Leviathan::ScriptModule::_StopFileMonitoring(Lock& guard)
664 {
665 
666  auto tmphandler = ResourceRefreshHandler::Get();
667 
668  if(tmphandler) {
669 
670  // Stop listening for all the files at once //
671  auto end = FileListeners.end();
672  for(auto iter = FileListeners.begin(); iter != end; ++iter) {
673 
674  tmphandler->StopListeningForFileChanges(*iter);
675  }
676 
677  FileListeners.clear();
678  }
679 
680  AlreadyMonitoredFiles.clear();
681 
682 
683  // Everything should be cleared now //
684 }
685 
686 void Leviathan::ScriptModule::_AddFileToMonitorIfNotAlready(const std::string& file)
687 {
688 
689  // Look for a matching string //
690  auto end = AlreadyMonitoredFiles.end();
691  for(auto iter = AlreadyMonitoredFiles.begin(); iter != end; ++iter) {
692 
693  if(*(*iter)->File == file)
694  return;
695  }
696 
697 
698  // Add it as it isn't there yet //
699  AlreadyMonitoredFiles.push_back(std::make_unique<AutomonitoredFile>(file));
700 }
701 
702 void Leviathan::ScriptModule::_FileChanged(
703  const std::string& file, ResourceFolderListener& caller)
704 {
705 
706  GUARD_LOCK();
707 
708  // This ignores multiple messages //
709  if(!caller.IsAFileStillUpdated())
710  return;
711 
712  // Mark everything as not updated //
713  auto tmphandler = ResourceRefreshHandler::Get();
714 
715  if(tmphandler) {
716 
717  tmphandler->MarkListenersAsNotUpdated(FileListeners);
718  }
719 
720  // Reload the module //
721  if(!ReLoadModuleCode()) {
722 
723  Logger::Get()->Error(
724  "ScriptModule: FileChanged: failed to reload the module, " + GetInfoString());
725  }
726 }
727 
728 #endif // SCRIPTMODULE_LISTENFORFILECHANGES
729 // ------------------------------------ //
730 void Leviathan::ScriptModule::_BuildTheModule(Lock& guard)
731 {
732  // Apply the (possibly) updated access mask first //
733  ScriptBuilder->GetModule()->SetAccessMask(AccessMask);
734 
735  // Add the source files before building //
736  for(size_t i = 0; i < ScriptSourceSegments.size(); i++) {
737  if(ScriptBuilder->AddSectionFromMemory(ScriptSourceSegments[i]->SourceFile.c_str(),
738  ScriptSourceSegments[i]->SourceCode->c_str(), 0,
739  ScriptSourceSegments[i]->StartLine - 1) < 0) {
740  Logger::Get()->Error("ScriptModule: GetModule: failed to build unbuilt module "
741  "(adding source file '" +
742  ScriptSourceSegments[i]->SourceFile + "' failed), " +
743  GetInfoString());
744 
745  ScriptState = SCRIPTBUILDSTATE_FAILED;
746  return;
747  }
748  }
749 
750  // Build it //
751  int result;
752  {
753  // Only one script can be built at a time so a lock is required //
754  Lock lock(ModuleBuildingMutex);
755  result = ScriptBuilder->BuildModule();
756  }
757 
758  if(result < 0) {
759  // failed to build //
760  Logger::Get()->Error(
761  "ScriptModule: GetModule: failed to build unbuilt module, " + GetInfoString());
762 
763  ScriptState = SCRIPTBUILDSTATE_FAILED;
764  return;
765  }
766 
767  ASModule = ScriptBuilder->GetModule();
768  ScriptState = SCRIPTBUILDSTATE_BUILT;
769 }
770 // ------------------------------------ //
772  std::shared_ptr<ScriptArgumentsProviderBridge> bridge)
773 {
774  LEVIATHAN_ASSERT(this == bridge->GetModule(), "OnAddedToBridge it's not ours!");
775 
776  if(ArgsBridge) {
777 
778  return false;
779  }
780 
781  ArgsBridge = bridge;
782  return true;
783 }
784 // ------------------------------------ //
785 DLLEXPORT std::string ScriptModule::ResolvePathToScriptFile(const std::string& inputfilename,
786  const std::string& relativepath, bool checkworkdirrelative /*= true*/)
787 {
788  // The canonical calls here are probably not needed as the as
789  // script builder makes all paths absolute
790 
791  // Check first relative, absolute, and then search //
792  const auto asRelative = boost::filesystem::path(relativepath) / inputfilename;
793  if(boost::filesystem::is_regular_file(asRelative)) {
794  return boost::filesystem::canonical(asRelative).generic_string();
795 
796  } else if(checkworkdirrelative && boost::filesystem::is_regular_file(inputfilename)) {
797 
798  return boost::filesystem::canonical(inputfilename).generic_string();
799 
800  } else {
801 
802  // This returns an empty string for us //
803  std::string searched = FileSystem::Get()->SearchForFile(FILEGROUP_SCRIPT,
804  StringOperations::RemoveExtension<std::string>(inputfilename),
805  StringOperations::GetExtension<std::string>(inputfilename), false);
806 
807  if(searched.empty())
808  return searched;
809 
810  return boost::filesystem::canonical(searched).generic_string();
811  }
812 }
813 
814 // ------------------------------------ //
815 Mutex Leviathan::ScriptModule::ModuleBuildingMutex;
816 
817 // ------------------ ValidListenerData ------------------ //
819  asIScriptFunction* funcptr, std::string* name, std::string* metadataend) :
820  FuncPtr(funcptr),
821  ListenerName(name), RestOfMeta(metadataend)
822 {
823  // increase references //
824  FuncPtr->AddRef();
825 }
826 
827 Leviathan::ValidListenerData::ValidListenerData(asIScriptFunction* funcptr, std::string* name,
828  std::string* metadataend, std::string* generictypename) :
829  FuncPtr(funcptr),
830  ListenerName(name), RestOfMeta(metadataend), GenericTypeName(generictypename)
831 {
832  // increase references //
833  FuncPtr->AddRef();
834 }
835 
837 {
838  // decrease reference //
839  FuncPtr->Release();
840 }
841 // ------------------ ScriptSourceFileData ------------------ //
843  const std::string& file, int line, const std::string& code) :
844  SourceFile(file),
845  StartLine(line), SourceCode(std::make_shared<std::string>(code))
846 {}
#define LISTENERNAME_ONVALUECHANGE
Definition: Event.h:47
#define LISTENERVALUE_ONSUBMIT
Definition: Event.h:60
#define LISTENERNAME_ONCLOSECLICKED
Definition: Event.h:50
#define LISTENERNAME_ONSHOW
Definition: Event.h:41
#define LISTENERVALUE_ONTICK
Definition: Event.h:61
ScriptRunResult< ReturnT > RunScript(const std::shared_ptr< ScriptModule > &module, ScriptRunningSetup &parameters, Args &&... args)
Runs a function in a script.
some data that is stored when a listener is found
Definition: ScriptModule.h:33
DLLEXPORT void Write(const std::string &data) override
Definition: Logger.cpp:113
DLLEXPORT ScriptSourceFileData(const std::string &file, int line, const std::string &code)
#define LISTENERVALUE_ONCLOSECLICKED
Definition: Event.h:62
#define LISTENERVALUE_ONVALUECHANGE
Definition: Event.h:59
static const std::map< std::string, int > ListenerNameType
Definition: ScriptModule.h:187
DLLEXPORT asIScriptEngine * GetASEngine()
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
#define LOG_ERROR(x)
Definition: Define.h:92
DLLEXPORT FORCE_INLINE bool AddScriptSegment(const std::string &file, int line, const std::string &code)
Adds a new script section.
Definition: ScriptModule.h:159
#define LISTENERNAME_ONINIT
Definition: Event.h:45
static DLLEXPORT std::string GetListenerNameFromType(EVENT_TYPE type)
#define LISTENERNAME_ONCLICK
Definition: Event.h:44
#define LISTENERNAME_LISTSELECTIONACCEPTED
Definition: Event.h:51
asIScriptFunction * FuncPtr
Definition: ScriptModule.h:39
#define LISTENERVALUE_ONINIT
Definition: Event.h:57
#define LOG_WARNING(x)
Definition: Define.h:91
DLLEXPORT void PrintFunctionsInModule()
static DLLEXPORT ScriptExecutor * Get()
DLLEXPORT bool ReLoadModuleCode()
Rebuilds the module and tries to restore data.
#define LISTENERVALUE_LISTSELECTIONACCEPTED
Definition: Event.h:63
#define LISTENERVALUE_ONHIDE
Definition: Event.h:54
DLLEXPORT size_t GetScriptSegmentCount() const
Gets the number of code segments.
#define LISTENERNAME_ONLISTENUPDATE
Definition: Event.h:43
static DLLEXPORT int ScriptModuleIncludeCallback(const char *include, const char *from, CScriptBuilder *builder, void *userParam)
#define LISTENERNAME_ONHIDE
Definition: Event.h:42
DLLEXPORT void Release()
Releases the internal resources.
Iterator class for getting parts of a string.
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT void SetAsInvalid()
Sets the module as invalid to avoid usage.
ValidListenerData(asIScriptFunction *funcptr, std::string *name, std::string *metadataend)
#define LISTENERNAME_ONSUBMIT
Definition: Event.h:48
DLLEXPORT void GetListOfListeners(std::vector< std::shared_ptr< ValidListenerData >> &receiver)
std::mutex Mutex
Definition: ThreadSafe.h:16
DLLEXPORT std::shared_ptr< ScriptSourceFileData > GetScriptSegment(size_t index) const
Gets the data associated with a code segment.
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100
DLLEXPORT std::shared_ptr< ScriptScript > GetScriptInstance()
DLLEXPORT bool OnAddedToBridge(std::shared_ptr< ScriptArgumentsProviderBridge > bridge)
Call when this module is added to a bridge.
static std::string ToString(const T &val)
Definition: Convert.h:72
static DLLEXPORT std::string ResolvePathToScriptFile(const std::string &inputfilename, const std::string &relativepath, bool checkworkdirrelative=true)
Finds a path to source file or returns an empty string.
DLLEXPORT const std::string & GetModuleName() const
Gets the name of the internal AngelScript module.
#define LISTENERVALUE_ONSHOW
Definition: Event.h:53
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
A file listener instance which listens for file changes in a folder.
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666
DLLEXPORT std::string GetListeningFunctionName(const std::string &listenername, const std::string *generictype=NULL)
static void RemovePreceedingTrailingSpaces(StringTypeN &str)
static DLLEXPORT bool ReadFileEntirely(const std::string &file, std::string &resultreceiver)
Definition: FileSystem.cpp:538
#define LISTENERNAME_ONTICK
Definition: Event.h:49
DLLEXPORT ScriptModule(asIScriptEngine *engine, const std::string &name, int id, const std::string &source)
#define LISTENERVALUE_ONCLICK
Definition: Event.h:56
#define DLLEXPORT
Definition: Include.h:84
DLLEXPORT void DeleteThisModule()
DLLEXPORT void DeleteModule(ScriptModule *ptrtomatch)
DLLEXPORT bool DoesListenersContainSpecificListener(const std::string &listenername, const std::string *generictype=NULL)
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
DLLEXPORT bool IsAFileStillUpdated() const
Checks whether a file is still marked as updated.
#define SAFE_DELETE(x)
Definition: Define.h:149
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
static DLLEXPORT ResourceRefreshHandler * Get()
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
DLLEXPORT asIScriptModule * GetModule()
Definition: ScriptModule.h:90
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
#define LISTENERNAME_ONRELEASE
Definition: Event.h:46
#define LISTENERVALUE_ONRELEASE
Definition: Event.h:58
DLLEXPORT std::string GetInfoString()
DLLEXPORT bool AddScriptSegmentFromFile(const std::string &file)
Adds an entire file as a script segment.