float CMonoActor::GetMaxHealth() const { IMonoObject *pResult = *m_pScript->GetPropertyValue("MaxHealth"); float health = pResult->Unbox<float>(); pResult->Release(); return health; }
void CCryScriptInstance::SetManagedObject(MonoObject *newObject, bool allowGC) { CScriptObject::SetManagedObject(newObject, allowGC); IMonoObject *pScriptIdResult = *GetPropertyValue("ScriptId"); m_scriptId = pScriptIdResult->Unbox<int>(); pScriptIdResult->Release(); }
void CMonoActor::OnScriptInstanceInitialized(ICryScriptInstance *pScriptInstance) { mono::object pIdResult = pScriptInstance->GetPropertyValue("Id", false); if(pIdResult) { IMonoObject *pObject = *pIdResult; EntityId id = pObject->Unbox<EntityId>(); pObject->Release(); if(id == GetEntityId()) m_pScript = pScriptInstance; } }
bool CFlowNode::CreatedNode(TFlowNodeId id, const char *name, TFlowNodeTypeId typeId, IFlowNodePtr pNode) { if(pNode==this) { IMonoObject *pScript = g_pScriptSystem->InstantiateScript(gEnv->pFlowSystem->GetTypeName(typeId), eScriptFlag_FlowNode); IMonoClass *pNodeInfo = g_pScriptSystem->GetCryBraryAssembly()->GetClass("NodeInfo", "CryEngine.FlowSystem.Native"); pScript->CallMethod("InternalInitialize", pNodeInfo->BoxObject(&SMonoNodeInfo(this, id, m_pActInfo->pGraph->GetGraphId()))); m_pScript = pScript; return pScript != nullptr; } return true; }
void CMonoEntityExtension::RMIParams::SerializeWith(TSerialize ser) { IMonoArray *pArgs; int length; if(args != nullptr) { pArgs = *args; length = pArgs->GetSize(); } else length = 0; ser.Value("length", length); ser.Value("methodName", methodName); ser.Value("targetId", targetId, 'eid'); if(length > 0) { if(ser.IsWriting()) { for(int i = 0; i < length; i++) { IMonoObject *pItem = *pArgs->GetItem(i); pItem->GetAnyValue().SerializeWith(ser); SAFE_RELEASE(pItem); } } else { pArgs = g_pScriptSystem->GetScriptDomain()->CreateArray(length); for(int i = 0; i < length; i++) { MonoAnyValue value; value.SerializeWith(ser); pArgs->InsertAny(value, i); } args = pArgs->GetManagedObject(); } pArgs->Release(); } }
bool CScriptSystem::CompleteInit() { CryLogAlways(" Initializing CryMono ..."); // Create root domain and determine the runtime version we'll be using. m_pRootDomain = new CScriptDomain(eRV_4_30319); m_domains.push_back(m_pRootDomain); CScriptArray::m_pDefaultElementClass = mono_get_object_class(); #ifndef _RELEASE m_pPdb2MdbAssembly = m_pRootDomain->LoadAssembly(PathUtils::GetMonoPath() + "bin\\pdb2mdb.dll"); #endif RegisterPriorityBindings(); m_bFirstReload = true; if(Reload()) { m_bFirstReload = false; RegisterSecondaryBindings(); gEnv->pGameFramework->RegisterListener(this, "CryMono", eFLPriority_Game); gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(&g_systemEventListener_CryMono); CryModuleMemoryInfo memInfo; CryModuleGetMemoryInfo(&memInfo); IMonoClass *pCryStats = m_pCryBraryAssembly->GetClass("CryStats", "CryEngine.Utilities"); IMonoObject *pMemoryUsage = *pCryStats->GetPropertyValue(NULL, "MemoryUsage"); CryLogAlways(" Initializing CryMono done, MemUsage=%iKb", (memInfo.allocated + pMemoryUsage->Unbox<long>()) / 1024); pMemoryUsage->Release(); } else { CryLogAlways(" Initializing CryMono failed!"); return false; } return true; }
void CCryScriptInstance::OnReloadComplete() { if(m_scriptId == 0) return; IMonoObject *pScriptManager = g_pScriptSystem->GetScriptManager(); IMonoArray *pArgs = CreateMonoArray(2); pArgs->Insert(m_scriptId); pArgs->Insert(m_flags); if(mono::object result = pScriptManager->GetClass()->InvokeArray(pScriptManager->GetManagedObject(), "GetScriptInstanceById", pArgs)) { SetManagedObject((MonoObject *)result, true); } else MonoWarning("Failed to locate script instance %i after reload!", m_scriptId); pArgs->Release(); }
void CActorSystem::OnSpawn(IEntity *pEntity,SEntitySpawnParams ¶ms) { EMonoActorType actorType = GetMonoActorType(pEntity->GetClass()->GetName()); if(actorType != EMonoActorType_None) { if(IActor *pActor = gEnv->pGameFramework->GetIActorSystem()->GetActor(pEntity->GetId())) { IMonoObject *pScript = g_pScriptSystem->InstantiateScript(pEntity->GetClass()->GetName(), eScriptFlag_Actor); IMonoClass *pActorInfoClass = g_pScriptSystem->GetCryBraryAssembly()->GetClass("ActorInfo"); SMonoActorInfo actorInfo(pActor); pScript->CallMethod("InternalSpawn", pActorInfoClass->BoxObject(&actorInfo)); if(actorType == EMonoActorType_Managed) static_cast<CActor *>(pActor)->SetScript(pScript); } } }
CScriptSystem::CScriptSystem(IGameFramework *pGameFramework) : m_pRootDomain(nullptr) , m_pCryBraryAssembly(nullptr) , m_pPdb2MdbAssembly(nullptr) , m_pScriptManager(nullptr) , m_pScriptDomain(nullptr) , m_bReloading(false) , m_bDetectedChanges(false) , m_bQuitting(false) , m_pConverter(nullptr) , m_bFirstReload(true) , m_pGameFramework(pGameFramework) { CryLogAlways("Initializing Mono Script System"); g_pThis = this; m_pCVars = new SCVars(); g_pMonoCVars = m_pCVars; // We should look into storing mono binaries, configuration as well as scripts via CryPak. mono_set_dirs(PathUtils::GetMonoLibPath(), PathUtils::GetMonoConfigPath()); #ifndef _RELEASE // Enable Mono signal handling // Makes sure that Mono sends back exceptions it tries to handle, for CE crash handling. mono_set_signal_chaining(true); #endif string monoCmdOptions = ""; if(auto *pArg = gEnv->pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "monoArgs")) monoCmdOptions.append(pArg->GetValue()); // Commandline switch -DEBUG makes the process connect to the debugging server. Warning: Failure to connect to a debugging server WILL result in a crash. // This is currently a WIP feature which requires custom MonoDevelop extensions and other irritating things. const ICmdLineArg* arg = gEnv->pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "DEBUG"); if (arg != nullptr) monoCmdOptions.append("--debugger-agent=transport=dt_socket,address=127.0.0.1:65432,embedding=1"); #ifndef _RELEASE else if(g_pMonoCVars->mono_softBreakpoints) // Soft breakpoints not compatible with debugging server { CryLogAlways(" [Performance Warning] Mono soft breakpoints are enabled!"); // Prevents managed null reference exceptions causing crashes in unmanaged code // See: https://bugzilla.xamarin.com/show_bug.cgi?id=5963 monoCmdOptions.append("--soft-breakpoints"); } #endif char *options = new char[monoCmdOptions.size() + 1]; strcpy(options, monoCmdOptions.c_str()); // Note: iPhone requires AOT compilation, this can be enforced via mono options. TODO: Get Crytek to add CryMobile support to the Free SDK. mono_jit_parse_options(1, &options); #ifndef _RELEASE // Required for mdb's to load for detailed stack traces etc. mono_debug_init(MONO_DEBUG_FORMAT_MONO); #endif m_pConverter = new CConverter(); if(!CompleteInit()) { CryLogAlways("CryMono initialization failed!"); return; } RegisterSecondaryBindings(); pGameFramework->RegisterListener(this, "CryMono", FRAMEWORKLISTENERPRIORITY_GAME); gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(&g_systemEventListener_CryMono); if(IFileChangeMonitor *pFileChangeMonitor = gEnv->pFileChangeMonitor) pFileChangeMonitor->RegisterListener(this, "scripts\\"); CryModuleMemoryInfo memInfo; CryModuleGetMemoryInfo(&memInfo); IMonoClass *pCryStats = m_pCryBraryAssembly->GetClass("CryStats", "CryEngine.Utilities"); IMonoObject *pMemoryUsage = *pCryStats->GetPropertyValue(NULL, "MemoryUsage"); CryLogAlways(" Initializing CryMono done, MemUsage=%iKb", (memInfo.allocated + pMemoryUsage->Unbox<long>()) / 1024); pMemoryUsage->Release(); }
bool CScriptSystem::Reload() { if((!m_bFirstReload && g_pMonoCVars->mono_realtimeScripting == 0) || m_bReloading) return false; m_bReloading = true; if(!m_bFirstReload) { for each(auto listener in m_listeners) listener->OnReloadStart(); m_pScriptManager->CallMethod("Serialize"); } IMonoDomain *pScriptDomain = CreateDomain("ScriptDomain", nullptr, true); IMonoAssembly *pCryBraryAssembly = pScriptDomain->LoadAssembly(PathUtils::GetBinaryPath() + "CryBrary.dll"); IMonoArray *pCtorParams = CreateMonoArray(2); pCtorParams->InsertAny(m_bFirstReload); pCtorParams->InsertMonoString(ToMonoString(PathUtils::GetConfigPath())); IMonoObject *pScriptManager = *pCryBraryAssembly->GetClass("ScriptManager", "CryEngine.Initialization")->CreateInstance(pCtorParams); SAFE_RELEASE(pCtorParams); auto result = pScriptManager->CallMethod("Initialize", m_bFirstReload); if(result == nullptr) return false; IMonoObject *pResult = *result; auto reloadResult = pResult->Unbox<EScriptReloadResult>(); SAFE_RELEASE(pResult); switch(reloadResult) { case EScriptReloadResult_Success: { // revert previous domain if(!m_bFirstReload) m_pScriptDomain->Release(); m_pScriptDomain = pScriptDomain; m_pScriptManager = pScriptManager; m_pCryBraryAssembly = pCryBraryAssembly; CacheManagedResources(); if(!m_bFirstReload) m_pScriptManager->CallMethod("Deserialize"); // Set Network.Editor etc. IMonoClass *pClass = m_pCryBraryAssembly->GetClass("Game"); IMonoArray *pArgs = CreateMonoArray(2); pArgs->Insert(gEnv->IsEditor()); pArgs->Insert(gEnv->IsDedicated()); pClass->GetMethod("InitializeGameStatics", 2)->InvokeArray(nullptr, pArgs); SAFE_RELEASE(pArgs); m_pScriptManager->CallMethod("ProcessWaitingScripts", m_bFirstReload); for each(auto listener in m_listeners) listener->OnReloadComplete(); if(!m_bFirstReload && gEnv->IsEditor()) gEnv->pFlowSystem->ReloadAllNodeTypes(); m_bReloading = false; m_bDetectedChanges = false; return true; } break; case EScriptReloadResult_Retry: { m_bReloading = false; return Reload(); } case EScriptReloadResult_Revert: { pScriptDomain->Release(); m_pScriptDomain->SetActive(); m_bReloading = false; m_bDetectedChanges = false; return false; } break; case EScriptReloadResult_Abort: { gEnv->pSystem->Quit(); m_bReloading = false; } break; } return false; }