Beispiel #1
0
IMonoObject *CScriptSystem::InstantiateScript(const char *scriptName, EMonoScriptFlags scriptFlags, IMonoArray *pConstructorParameters, bool throwOnFail)
{
	auto *pInstance = new CCryScriptInstance(scriptFlags);

	IMonoArray *pScriptCreationArgs = CreateMonoArray(5);
	pScriptCreationArgs->Insert(scriptName);
	pScriptCreationArgs->Insert(scriptFlags);
	pScriptCreationArgs->InsertNativePointer(pInstance);
	pScriptCreationArgs->InsertMonoObject((pConstructorParameters != nullptr ? pConstructorParameters->GetManagedObject() : nullptr));
	pScriptCreationArgs->Insert(throwOnFail);

	mono::object result = m_pScriptManager->GetClass()->InvokeArray(m_pScriptManager->GetManagedObject(), "CreateScriptInstance", pScriptCreationArgs);
	SAFE_RELEASE(pScriptCreationArgs);

	if(!result)
		return nullptr;
	
	pInstance->SetManagedObject((MonoObject *)result, true);

	if(scriptFlags & eScriptFlag_GameRules)
	{
		IMonoClass *pGameRulesInitParamsClass = g_pScriptSystem->GetCryBraryAssembly()->GetClass("GameRulesInitializationParams");

		IMonoArray *pArgs = CreateMonoArray(1);

		SGameRulesInitializationParams params;
		pArgs->InsertMonoObject(pGameRulesInitParamsClass->BoxObject(&params));

		InitializeScriptInstance(pInstance, pArgs);
		SAFE_RELEASE(pArgs);
	}

	for each(auto listener in m_listeners)
		listener->OnScriptInstanceCreated(scriptName, scriptFlags, pInstance);

	return pInstance;
}
Beispiel #2
0
bool CMonoFlowNode::CreatedNode(TFlowNodeId id, const char *name, TFlowNodeTypeId typeId, IFlowNodePtr pNode) 
{ 
	if(pNode==this)
	{
		m_id = id;
		m_graphId = m_pActInfo->pGraph->GetGraphId();

		const char *typeName = gEnv->pFlowSystem->GetTypeName(typeId);

		ICryScriptInstance *pScript = GetMonoScriptSystem()->InstantiateScript(gEnv->pFlowSystem->GetTypeName(typeId), eScriptFlag_FlowNode);

		IMonoClass *pNodeInfo = GetMonoScriptSystem()->GetCryBraryAssembly()->GetClass("NodeInitializationParams", "CryEngine.Flowgraph.Native");
		
		IMonoArray *pArgs = CreateMonoArray(1);
		pArgs->InsertMonoObject(pNodeInfo->BoxObject(&SMonoNodeInfo(this, id, m_graphId)));

		mono::object result = static_cast<CScriptSystem *>(GetMonoScriptSystem())->InitializeScriptInstance(pScript, pArgs);
		pArgs->Release();
		
		m_pScript = pScript;
		m_scriptId = pScript->GetId();

		if(result)
		{
			IMonoObject *pResult = *result;
			bool bResult = pResult->Unbox<bool>();
			SAFE_RELEASE(pResult);

			return bResult;
		}

		CryLogAlways("Failed to create node %s", gEnv->pFlowSystem->GetTypeName(typeId));
		return false;
	}

	return true; 
}
Beispiel #3
0
mono::object CScriptbind_Entity::GetEntitiesByClasses(mono::object classes)
{
	IMonoArray *pClassArray = *classes;

	int numClasses = pClassArray->GetSize();
	IEntityClass **pClasses = new IEntityClass *[numClasses];
	for(int i = 0; i < numClasses; i++)
		pClasses[i] = gEnv->pEntitySystem->GetClassRegistry()->FindClass(ToCryString((mono::string)pClassArray->GetManagedObject()));

	IEntityItPtr pIt = gEnv->pEntitySystem->GetEntityIterator();

	IMonoClass *pEntityIdClass = GetMonoScriptSystem()->GetCryBraryAssembly()->GetClass("EntityId");
	IMonoArray *pEntities = CreateDynamicMonoArray();
	
	pIt->MoveFirst();
	while(!pIt->IsEnd())
	{
		if(IEntity *pEntity = pIt->Next())
		{
			IEntityClass *pEntityClass = pEntity->GetClass();
			for(int i = 0; i < numClasses; i++)
			{
				if(pEntityClass == pClasses[i])
				{
					pEntities->InsertMonoObject(pEntityIdClass->BoxObject(&mono::entityId(pEntity->GetId())));
					break;
				}
			}
		}
	}

	auto result = pEntities->GetManagedObject();
	pEntities->Release();

	return result;
}
Beispiel #4
0
mono::object CScriptbind_Entity::GetEntitiesByClass(mono::string _class)
{
	IEntityClass *pDesiredClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(ToCryString(_class));

	IEntityItPtr pIt = gEnv->pEntitySystem->GetEntityIterator();

	IMonoClass *pEntityIdClass = GetMonoScriptSystem()->GetCryBraryAssembly()->GetClass("EntityId");
	IMonoArray *pEntities = CreateDynamicMonoArray();

	pIt->MoveFirst();
	while(!pIt->IsEnd())
	{
		if(IEntity *pEntity = pIt->Next())
		{
			if(pEntity->GetClass() == pDesiredClass)
				pEntities->InsertMonoObject(pEntityIdClass->BoxObject(&mono::entityId(pEntity->GetId())));
		}
	}

	auto result = pEntities->GetManagedObject();
	pEntities->Release();

	return result;
}
Beispiel #5
0
mono::object CScriptbind_Entity::QueryProximity(AABB box, mono::string className, uint32 nEntityFlags)
{
	SEntityProximityQuery query;

	if(className != nullptr)
		query.pEntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(ToCryString(className));

	query.box = box;
	query.nEntityFlags = nEntityFlags;

	gEnv->pEntitySystem->QueryProximity(query);

	IMonoClass *pEntityIdClass = g_pScriptSystem->GetCryBraryAssembly()->GetClass("EntityId");
	if(query.nCount > 0)
	{
		IMonoArray *pEntities = CreateMonoArray(query.nCount);
		for(int i = 0; i < query.nCount; i++)
			pEntities->Insert(pEntityIdClass->BoxObject(&mono::entityId(query.pEntities[i]->GetId())));

		return pEntities->GetManagedObject();
	}

	return nullptr;
}
Beispiel #6
0
CMonoFlowNode::~CMonoFlowNode()
{
	IMonoClass *pFlowNodeClass = GetMonoScriptSystem()->GetCryBraryAssembly()->GetClass("FlowNode", "CryEngine.Flowgraph");

	pFlowNodeClass->CallMethod("InternalRemove", m_scriptId);
}
Beispiel #7
0
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();
}
Beispiel #8
0
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;
}
void CEntityEventHandler::HandleEntityEvent(EEntityType type, SEntityEvent &event, IEntity *pEntity, mono::object managedObject)
{
	switch(event.event)
	{
	case ENTITY_EVENT_RESET:
		{
			bool enterGamemode = event.nParam[0]==1;

			if(!enterGamemode && pEntity->GetFlags() & ENTITY_FLAG_NO_SAVE)
			{
				gEnv->pEntitySystem->RemoveEntity(pEntity->GetId());
				return;
			}

			IMonoArray *pParams = CreateMonoArray(1);
			pParams->Insert(enterGamemode);
			m_pClass[type]->GetMethod("OnEditorReset", 1)->InvokeArray(managedObject, pParams);

			SAFE_RELEASE(pParams);
		}
		break;
	case ENTITY_EVENT_COLLISION:
		{
			EventPhysCollision *pCollision = (EventPhysCollision *)event.nParam[0];

			SMonoColliderInfo source = SMonoColliderInfo(pCollision, 0);
			SMonoColliderInfo target = SMonoColliderInfo(pCollision, 1);

			IMonoClass *pColliderInfoClass = g_pScriptSystem->GetCryBraryAssembly()->GetClass("ColliderInfo");

			IMonoArray *pArgs = CreateMonoArray(6);

			pArgs->InsertMonoObject(pColliderInfoClass->BoxObject(&source));
			pArgs->InsertMonoObject(pColliderInfoClass->BoxObject(&target));

			pArgs->Insert(pCollision->pt);
			pArgs->Insert(pCollision->n);

			pArgs->Insert(pCollision->penetration);
			pArgs->Insert(pCollision->radius);

			m_pClass[type]->GetMethod("OnCollision", 6)->InvokeArray(managedObject, pArgs);
			SAFE_RELEASE(pArgs);
		}
		break;
	case ENTITY_EVENT_START_GAME:
		m_pClass[type]->GetMethod("OnStartGame")->Invoke(managedObject);
		break;
	case ENTITY_EVENT_START_LEVEL:
		m_pClass[type]->GetMethod("OnStartLevel")->Invoke(managedObject);
		break;
	case ENTITY_EVENT_LEVEL_LOADED:
		m_pClass[type]->GetMethod("OnLevelLoaded")->Invoke(managedObject);
		break;
	case ENTITY_EVENT_ENTERAREA:
		m_pClass[type]->GetMethod("OnEnterArea", 3)->Call(managedObject, (EntityId)event.nParam[0], (int)event.nParam[1], (EntityId)event.nParam[2]);
		break;
	case ENTITY_EVENT_MOVEINSIDEAREA:
		m_pClass[type]->GetMethod("OnMoveInsideArea", 3)->Call(managedObject, (EntityId)event.nParam[0], (int)event.nParam[1], (EntityId)event.nParam[2]);
		break;
	case ENTITY_EVENT_LEAVEAREA:
		m_pClass[type]->GetMethod("OnLeaveArea", 3)->Call(managedObject, (EntityId)event.nParam[0], (int)event.nParam[1], (EntityId)event.nParam[2]);
		break;
	case ENTITY_EVENT_ENTERNEARAREA:
		m_pClass[type]->GetMethod("OnEnterNearArea", 3)->Call(managedObject, (EntityId)event.nParam[0], (int)event.nParam[1], (EntityId)event.nParam[2]);
		break;
	case ENTITY_EVENT_MOVENEARAREA:
		m_pClass[type]->GetMethod("OnMoveNearArea", 4)->Call(managedObject, (EntityId)event.nParam[0], (int)event.nParam[1], (EntityId)event.nParam[2], event.fParam[0]);
		break;
	case ENTITY_EVENT_LEAVENEARAREA:
		m_pClass[type]->GetMethod("OnLeaveNearArea", 3)->Call(managedObject, (EntityId)event.nParam[0], (int)event.nParam[1], (EntityId)event.nParam[2]);
		break;
	case ENTITY_EVENT_XFORM:
		m_pClass[type]->GetMethod("OnMove", 1)->Call(managedObject, (EEntityXFormFlags)event.nParam[0]);
		break;
	case ENTITY_EVENT_ATTACH:
		m_pClass[type]->GetMethod("OnAttach", 1)->Call(managedObject, (EntityId)event.nParam[0]);
		break;
	case ENTITY_EVENT_DETACH:
		m_pClass[type]->GetMethod("OnDetach", 1)->Call(managedObject, (EntityId)event.nParam[0]);
		break;
	case ENTITY_EVENT_DETACH_THIS:
		m_pClass[type]->GetMethod("OnDetachThis", 1)->Call(managedObject, (EntityId)event.nParam[0]);
		break;
	case ENTITY_EVENT_ANIM_EVENT:
		{
			const AnimEventInstance* pAnimEvent = reinterpret_cast<const AnimEventInstance*>(event.nParam[0]);
			ICharacterInstance* pCharacter = reinterpret_cast<ICharacterInstance*>(event.nParam[1]);

			IMonoClass *pAnimationEventClass = g_pScriptSystem->GetCryBraryAssembly()->GetClass("AnimationEvent");

			SMonoAnimationEvent animEvent(pAnimEvent);

			IMonoArray *pArgs = CreateMonoArray(1);

			pArgs->InsertMonoObject(pAnimationEventClass->BoxObject(&animEvent));

			m_pClass[type]->GetMethod("OnAnimEvent", 1)->InvokeArray(managedObject, pArgs);
			SAFE_RELEASE(pArgs);
		}
		break;
	case ENTITY_EVENT_PREPHYSICSUPDATE:
		{
			m_pClass[type]->GetMethod("OnPrePhysicsUpdate")->Invoke(managedObject);
		}
		break;
	}
}