From 07e2feba72b0a3147d6220e1dd03fa9a98894fc9 Mon Sep 17 00:00:00 2001 From: Kernell Date: Tue, 1 Dec 2015 12:26:55 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA?= =?UTF-8?q?=D0=B0=20=D1=81=D0=BE=D0=B1=D1=8B=D1=82=D0=B8=D0=B9=20MTA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mta-mono/mta-mono.vcxproj | 4 + mta-mono/src/CFunctions.cpp | 65 +++++-- mta-mono/src/CMonoClass.cpp | 36 +++- mta-mono/src/CMonoClass.h | 15 +- mta-mono/src/CMonoCorlib.h | 2 +- mta-mono/src/CMonoEvent.cpp | 331 +++++++++++++++++++++++++++++++++++ mta-mono/src/CMonoEvent.h | 52 ++++++ mta-mono/src/CMonoMTALib.cpp | 43 +++-- mta-mono/src/CMonoMTALib.h | 4 +- mta-mono/src/CMonoMethod.cpp | 65 +++++++ mta-mono/src/CMonoMethod.h | 58 ++++++ mta-mono/src/CResource.cpp | 129 +++++++++----- mta-mono/src/CResource.h | 19 +- 13 files changed, 743 insertions(+), 80 deletions(-) create mode 100644 mta-mono/src/CMonoEvent.cpp create mode 100644 mta-mono/src/CMonoEvent.h create mode 100644 mta-mono/src/CMonoMethod.cpp create mode 100644 mta-mono/src/CMonoMethod.h diff --git a/mta-mono/mta-mono.vcxproj b/mta-mono/mta-mono.vcxproj index 8eecc67..e2d49ee 100644 --- a/mta-mono/mta-mono.vcxproj +++ b/mta-mono/mta-mono.vcxproj @@ -145,6 +145,7 @@ + @@ -167,6 +168,7 @@ + @@ -188,9 +190,11 @@ + + diff --git a/mta-mono/src/CFunctions.cpp b/mta-mono/src/CFunctions.cpp index 4da7b85..c6dd0fa 100644 --- a/mta-mono/src/CFunctions.cpp +++ b/mta-mono/src/CFunctions.cpp @@ -10,7 +10,6 @@ * *********************************************************/ -#include "StdInc.h" #include "CFunctions.h" #include "extra/CLuaArguments.h" @@ -53,20 +52,66 @@ int CFunctions::monoEventHandler( lua_State *pLuaVM ) if( pResource ) { - // eventName, this, source, client, ... + string strEventName; + void* pThis = nullptr; - string strEventName = CLuaArgument( pLuaVM, -4 ).GetString(); - void* pThis = CLuaArgument( pLuaVM, -3 ).GetLightUserData(); - void* pSource = CLuaArgument( pLuaVM, -2 ).GetLightUserData(); - void* pClient = CLuaArgument( pLuaVM, -1 ).GetLightUserData(); + CLuaArguments pLuaArgs; - //void *args[] = { &vecVector.fX, &vecVector.fY }; + pLuaArgs.ReadArguments( pLuaVM ); + + if( pLuaArgs.Count() == 0 ) + { + return 0; + } - g_pModuleManager->DebugPrintf( pLuaVM, "event: %s", strEventName.c_str() ); + uint i = 0; - pResource->CallEvent( strEventName, pThis, pSource, pClient, nullptr ); + list< CLuaArgument* > argv; - return 1; + for( auto iter : pLuaArgs.GetArguments() ) + { + int iLuaType = iter->GetType(); + + switch( i ) + { + case 0: + { + strEventName = iter->GetString(); + + strEventName[ 0 ] = toupper( strEventName[ 0 ] ); + + break; + } + case 2: + { + pThis = iter->GetLightUserData(); + + break; + } + case 3: + { + if( iLuaType == LUA_TNIL ) + { + break; + } + + // dot not break + } + default: + { + argv.push_back( iter ); + + break; + } + } + + i++; + } + + if( pResource->CallEvent( strEventName, pThis, argv ) ) + { + return 1; + } } } diff --git a/mta-mono/src/CMonoClass.cpp b/mta-mono/src/CMonoClass.cpp index 2968013..7a9c490 100644 --- a/mta-mono/src/CMonoClass.cpp +++ b/mta-mono/src/CMonoClass.cpp @@ -25,9 +25,9 @@ CMonoClass::CMonoClass( MonoClass* pMonoClass, CMonoDomain* pDomain ) while( MonoMethod* pMonoMethod = mono_class_get_methods( pMonoBaseClass, &iter ) ) { - const char* szName = mono_method_get_name( pMonoMethod ); + CMonoMethod* pMethod = new CMonoMethod( this, pMonoMethod ); - this->m_Methods[ szName ].push_back( pMonoMethod ); + this->m_Methods[ pMethod->GetName() ].push_back( pMethod ); } iter = nullptr; @@ -45,7 +45,7 @@ CMonoClass::CMonoClass( MonoClass* pMonoClass, CMonoDomain* pDomain ) { const char* szName = mono_event_get_name( pMonoEvent ); - this->m_Events[ szName ] = pMonoEvent; + this->m_Events[ szName ] = new CMonoEvent( this, pMonoEvent ); } iter = nullptr; @@ -69,6 +69,12 @@ CMonoClass::~CMonoClass( void ) this->m_pClass = nullptr; this->m_Fields.clear(); + + for( auto iter : this->m_Events ) + { + delete iter.second; + } + this->m_Events.clear(); for( auto iter : this->m_Properties ) @@ -80,6 +86,11 @@ CMonoClass::~CMonoClass( void ) for( auto iter : this->m_Methods ) { + for( auto method : iter.second ) + { + delete method; + } + iter.second.clear(); } @@ -130,18 +141,22 @@ MonoObject* CMonoClass::New( void** args, int argc ) return nullptr; } - MonoMethod* pMonoMethod = this->GetMethod( ".ctor", argc ); + CMonoMethod* pMethod = this->GetMethod( ".ctor", argc ); - if( !pMonoMethod ) + if( !pMethod ) { return nullptr; } - mono_runtime_invoke( pMonoMethod, pObject, args, nullptr ); + pMethod->Invoke( pObject, args, nullptr ); return pObject; } +MonoObject* CMonoClass::Box( void* value ) +{ + return mono_value_box( this->m_pDomain->GetMonoPtr(), this->m_pClass, value ); +} const char* CMonoClass::GetName( void ) { @@ -174,7 +189,7 @@ MonoMethod* CMonoClass::GetMethod( string strMethodName ) return nullptr; } -MonoMethod* CMonoClass::GetMethod( string strMethodName, uint uiIndex ) +CMonoMethod* CMonoClass::GetMethod( string strMethodName, uint uiIndex ) { if( this->m_Methods[ strMethodName ].size() > 0 ) { @@ -192,7 +207,12 @@ MonoMethod* CMonoClass::GetMethod( string strMethodName, uint uiIndex ) return nullptr; } -MonoEvent* CMonoClass::GetEvent( string strEventName ) +list< CMonoMethod* > CMonoClass::GetMethods( string strMethodName ) +{ + return this->m_Methods[ strMethodName ]; +} + +CMonoEvent* CMonoClass::GetEvent( string strEventName ) { return this->m_Events[ strEventName ]; } diff --git a/mta-mono/src/CMonoClass.h b/mta-mono/src/CMonoClass.h index 8cea3b2..6266b09 100644 --- a/mta-mono/src/CMonoClass.h +++ b/mta-mono/src/CMonoClass.h @@ -16,10 +16,12 @@ class CMonoClass; #define _C_MONOCLASS_H #include "CMonoDomain.h" +#include "CMonoEvent.h" +#include "CMonoMethod.h" -typedef map< string, list< MonoMethod* > > MonoMethodMap; +typedef map< string, list< CMonoMethod* > > MonoMethodMap; typedef map< string, list< MonoProperty* > > MonoPropertyMap; -typedef map< string, MonoEvent* > MonoEventMap; +typedef map< string, CMonoEvent* > MonoEventMap; typedef map< string, MonoClassField* > MonoClassFieldMap; class CMonoClass @@ -44,16 +46,21 @@ public: MonoObject* New ( Vector3& vecVector ); MonoObject* New ( void** args, int argc ); + MonoObject* Box ( void* value ); + const char* GetName ( void ); const char* GetNameSpace ( void ); MonoMethod* GetMethodFromName ( string strMethodName, int iParamCount ); MonoMethod* GetMethod ( string strMethodName ); - MonoMethod* GetMethod ( string strMethodName, uint uiIndex ); + CMonoMethod* GetMethod ( string strMethodName, uint uiIndex ); + list< CMonoMethod* > GetMethods ( string strMethodName ); - MonoEvent* GetEvent ( string strEventName ); + CMonoEvent* GetEvent ( string strEventName ); MonoClassField* GetField ( string strFieldName ); + MonoEventMap GetAllEvents ( void ) { return this->m_Events; } + MonoClass* GetMonoPtr ( void ) { return this->m_pClass; } CMonoDomain* GetDomain ( void ) { return this->m_pDomain; } }; diff --git a/mta-mono/src/CMonoCorlib.h b/mta-mono/src/CMonoCorlib.h index f39d2aa..a661f13 100644 --- a/mta-mono/src/CMonoCorlib.h +++ b/mta-mono/src/CMonoCorlib.h @@ -25,7 +25,7 @@ private: MonoImage* m_pImage; CMonoDomain* m_pDomain; -protected: +public: map< const char*, CMonoClass* > Class; public: diff --git a/mta-mono/src/CMonoEvent.cpp b/mta-mono/src/CMonoEvent.cpp new file mode 100644 index 0000000..1d6a070 --- /dev/null +++ b/mta-mono/src/CMonoEvent.cpp @@ -0,0 +1,331 @@ +/********************************************************* +* +* Copyright © 2013, Innovation Roleplay Engine. +* +* All Rights Reserved. +* +* Redistribution and use in source and binary forms, +* with or without modification, +* is permitted only for authors. +* +*********************************************************/ + +#include "CMonoEvent.h" + +CMonoEvent::CMonoEvent( CMonoClass* pClass, MonoEvent* pEvent ) +{ + this->m_pClass = pClass; + this->m_pEvent = pEvent; + this->m_pAddMethod = nullptr; + this->m_pRemoveMethod = nullptr; + this->m_pRaiseMethod = nullptr; + + this->m_strName = mono_event_get_name( pEvent ); +} + +CMonoEvent::~CMonoEvent( void ) +{ + this->m_pClass = nullptr; + this->m_pEvent = nullptr; + this->m_pAddMethod = nullptr; + this->m_pRemoveMethod = nullptr; + this->m_pRaiseMethod = nullptr; +} + +bool CMonoEvent::Call( MonoObject* pThis, list< CLuaArgument* > argv ) +{ + CMonoMethod* pMethod = this->GetRaiseMethod(); + + if( !pMethod ) + { + return false; + } + + void** pArguments = this->ParseArguments( argv ); + + if( !pArguments ) + { + this->GetClass()->GetDomain()->GetResource()->ErrorPrintf( "Raise method for event '%s' not found\n", this->GetName().c_str() ); + + return false; + } + + MonoObject* pException = nullptr; + + pMethod->Invoke( pThis, pArguments, pException ); + + if( !pException ) + { + auto iter = argv.begin(); + + if( (*iter)->GetType() == LUA_TLIGHTUSERDATA ) + { + pMethod->Invoke( pArguments[ 0 ], pArguments, pException ); + } + } + + delete [] pArguments; + + if( pException ) + { + this->GetClass()->GetDomain()->GetResource()->ErrorPrintf( "%s\n", mono_string_to_utf8( mono_object_to_string( pException, nullptr ) ) ); + + return false; + } + + return false; +} + +void** CMonoEvent::ParseArguments( list< CLuaArgument* > argv ) +{ + CMonoMTALib* pMTALib = this->GetClass()->GetDomain()->GetMTALib(); + CMonoCorlib* pCorlib = this->GetClass()->GetDomain()->GetCorlib(); + + gpointer *pArguments = new gpointer[ argv.size() ]; + + uint argc = 0; + + auto pMethods = this->m_pClass->GetMethods( "raise_" + this->GetName() ); + + for( auto pMethod : pMethods ) + { + vector< SMonoType > pArgList = pMethod->GetArguments(); + + if( pArgList.size() != argv.size() ) + { + continue; + } + + auto iter = argv.begin(); + auto pType = pArgList.begin(); + + for( ; ; iter++ ) + { + if( iter == argv.end() || pType == pArgList.end() ) + { + return pArguments; + } + + int iLuaType = (*iter)->GetType(); + + switch( pType->iType ) + { + case MONO_TYPE_BOOLEAN: // System.Boolean + { + if( iLuaType == LUA_TBOOLEAN ) + { + bool bValue = (*iter)->GetBoolean(); + + pArguments[ argc++ ] = &bValue; + } + + break; + } + case MONO_TYPE_CHAR: // System.Char + { + if( iLuaType == LUA_TNUMBER ) + { + wchar_t iValue = (*iter)->GetNumber< wchar_t >(); + + MonoObject* pObj = pCorlib->Class[ "char" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_I1: // System.SByte + { + if( iLuaType == LUA_TNUMBER ) + { + int8_t iValue = (*iter)->GetNumber< int8_t >(); + + MonoObject* pObj = pCorlib->Class[ "sbyte" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_U1: // System.Byte + { + if( iLuaType == LUA_TNUMBER ) + { + uint8_t iValue = (*iter)->GetNumber< uint8_t >(); + + MonoObject* pObj = pCorlib->Class[ "byte" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_I2: // System.Int16 + { + if( iLuaType == LUA_TNUMBER ) + { + int16_t iValue = (*iter)->GetNumber< int16_t >(); + + MonoObject* pObj = pCorlib->Class[ "int16" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_U2: // System.UInt16 + { + if( iLuaType == LUA_TNUMBER ) + { + uint16_t iValue = (*iter)->GetNumber< uint16_t >(); + + MonoObject* pObj = pCorlib->Class[ "uint16" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_I4: // System.Int32 + { + if( iLuaType == LUA_TNUMBER ) + { + int32_t iValue = (*iter)->GetNumber< int32_t >(); + + MonoObject* pObj = pCorlib->Class[ "int32" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_U4: // System.UInt32 + { + if( iLuaType == LUA_TNUMBER ) + { + uint32_t iValue = (*iter)->GetNumber< uint32_t >(); + + MonoObject* pObj = pCorlib->Class[ "uint32" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_I8: // System.Int64 + { + if( iLuaType == LUA_TNUMBER ) + { + int64_t iValue = (*iter)->GetNumber< int64_t >(); + + MonoObject* pObj = pCorlib->Class[ "int64" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_U8: // System.UInt64 + { + if( iLuaType == LUA_TNUMBER ) + { + uint64_t iValue = (*iter)->GetNumber< uint64_t >(); + + MonoObject* pObj = pCorlib->Class[ "uint64" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_R4: // System.Single + { + if( iLuaType == LUA_TNUMBER ) + { + float iValue = (*iter)->GetNumber< float >(); + + MonoObject* pObj = pCorlib->Class[ "float" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_R8: // System.Double + { + if( iLuaType == LUA_TNUMBER ) + { + double iValue = (*iter)->GetNumber< double >(); + + MonoObject* pObj = pCorlib->Class[ "double" ]->Box( &iValue ); + + pArguments[ argc++ ] = pObj; + } + + break; + } + case MONO_TYPE_STRING: // System.String + { + if( iLuaType == LUA_TSTRING ) + { + const char* szValue = (*iter)->GetString(); + + MonoString* pString = this->GetClass()->GetDomain()->NewString( szValue ); + + pArguments[ argc++ ] = pString; + } + + break; + } + case MONO_TYPE_OBJECT: // System.Object + case MONO_TYPE_CLASS: + { + if( iLuaType == LUA_TLIGHTUSERDATA ) + { + void* pUserData = (*iter)->GetLightUserData(); + + MonoObject* pValue = pMTALib->RegisterElement( pUserData ); + + if( pValue ) + { + pArguments[ argc++ ] = pValue; + } + else + { + pArguments[ argc++ ] = pUserData; + } + } + + break; + } + case MONO_TYPE_I: + case MONO_TYPE_U: + default: + { + this->GetClass()->GetDomain()->GetResource()->ErrorPrintf( "Unsupported type '%s (0x%i)' for '%s'\n", pType->strName.c_str(), pType->iType, this->GetName().c_str() ); + + break; + } + } + } + } + + delete [] pArguments; + + return nullptr; +} + +CMonoMethod* CMonoEvent::GetAddMethod( void ) +{ + return this->m_pClass->GetMethod( "add_" + this->GetName(), 0 ); +} + +CMonoMethod* CMonoEvent::GetRemoveMethod( void ) +{ + return this->m_pClass->GetMethod( "remove_" + this->GetName(), 0 ); +} + +CMonoMethod* CMonoEvent::GetRaiseMethod( void ) +{ + return this->m_pClass->GetMethod( "raise_" + this->GetName(), 0 ); +} diff --git a/mta-mono/src/CMonoEvent.h b/mta-mono/src/CMonoEvent.h new file mode 100644 index 0000000..72077bd --- /dev/null +++ b/mta-mono/src/CMonoEvent.h @@ -0,0 +1,52 @@ +/********************************************************* +* +* Copyright © 2013, Innovation Roleplay Engine. +* +* All Rights Reserved. +* +* Redistribution and use in source and binary forms, +* with or without modification, +* is permitted only for authors. +* +*********************************************************/ + +class CMonoEvent; + +#ifndef __CMONOEVENT_H +#define __CMONOEVENT_H + +#include "CMonoClass.h" +#include "CMonoMethod.h" + +#include "extra/CLuaArgument.h" + +class CMonoEvent +{ +private: + CMonoClass* m_pClass; + + MonoEvent* m_pEvent; + MonoMethod* m_pAddMethod; + MonoMethod* m_pRemoveMethod; + MonoMethod* m_pRaiseMethod; + + string m_strName; + +public: + CMonoEvent ( CMonoClass* pClass, MonoEvent* pEvent ); + ~CMonoEvent ( void ); + + bool Call ( MonoObject* pThis, list< CLuaArgument* > argv ); + void** ParseArguments ( list< CLuaArgument* > argv ); + + CMonoMethod* GetAddMethod ( void ); + CMonoMethod* GetRemoveMethod ( void ); + CMonoMethod* GetRaiseMethod ( void ); + + CMonoClass* GetClass ( void ) { return this->m_pClass; } + MonoEvent* GetMonoPtr ( void ) { return this->m_pEvent; } + + string GetName ( void ) { return this->m_strName; } +}; + +#endif \ No newline at end of file diff --git a/mta-mono/src/CMonoMTALib.cpp b/mta-mono/src/CMonoMTALib.cpp index 4e7480c..4182c36 100644 --- a/mta-mono/src/CMonoMTALib.cpp +++ b/mta-mono/src/CMonoMTALib.cpp @@ -21,8 +21,6 @@ CMonoMTALib::CMonoMTALib( CMonoDomain* pDomain ) this->m_pImage = nullptr; this->m_pDomain = pDomain; - this->m_uiGCHandle = 0; - string strPath( CMonoInterface::GetBinariesDirectory() + "/" + pDomain->GetResource()->GetName() + "/MultiTheftAuto.dll" ); this->m_pAssembly = pDomain->OpenAssembly( strPath.c_str() ); @@ -42,8 +40,6 @@ CMonoMTALib::CMonoMTALib( CMonoDomain* pDomain ) if( this->m_pClass ) { this->m_pObject = this->m_pClass->New(); - - //this->m_uiGCHandle = mono_gchandle_new( this->m_pObject, true ); } } } @@ -51,13 +47,6 @@ CMonoMTALib::CMonoMTALib( CMonoDomain* pDomain ) CMonoMTALib::~CMonoMTALib( void ) { - if( this->m_uiGCHandle ) - { - mono_gchandle_free( this->m_uiGCHandle ); - - this->m_uiGCHandle = 0; - } - SAFE_DELETE( this->Color ); SAFE_DELETE( this->Vector2 ); SAFE_DELETE( this->Vector3 ); @@ -81,4 +70,36 @@ CMonoClass* CMonoMTALib::GetClass( const char* szNameSpace, const char* szName ) sprintf( szBuffer, "MultiTheftAuto.%s", szNameSpace ); return this->GetDomain()->FindOrAdd( mono_class_from_name( this->m_pImage, szBuffer, szName ) ); +} + +MonoObject* CMonoMTALib::RegisterElement( void* pUseData ) +{ + CMonoClass* pClass = this->GetClass( "Element" ); + + if( !pClass ) + { + return false; + } + + CMonoMethod* pMethod = pClass->GetMethod( "FindOrCreate", 0 ); + + if( !pMethod ) + { + return nullptr; + } + + void *Args[] = { &pUseData }; + + MonoObject* pException = nullptr; + + MonoObject* pObject = pMethod->Invoke( nullptr, Args, pException ); + + if( pException ) + { + this->GetDomain()->GetResource()->ErrorPrintf( "%s\n", mono_string_to_utf8( mono_object_to_string( pException, nullptr ) ) ); + + return nullptr; + } + + return pObject; } \ No newline at end of file diff --git a/mta-mono/src/CMonoMTALib.h b/mta-mono/src/CMonoMTALib.h index 4b79639..cdf77c7 100644 --- a/mta-mono/src/CMonoMTALib.h +++ b/mta-mono/src/CMonoMTALib.h @@ -27,8 +27,6 @@ private: CMonoClass* m_pClass; CMonoDomain* m_pDomain; - uint32_t m_uiGCHandle; - public: CMonoClass* Color; CMonoClass* Vector2; @@ -41,6 +39,8 @@ public: CMonoClass* GetClass ( const char* szName ); CMonoClass* GetClass ( const char* szNameSpace, const char* szName ); + MonoObject* RegisterElement ( void* pUserData ); + CMonoDomain* GetDomain ( void ) { return this->m_pDomain; } }; diff --git a/mta-mono/src/CMonoMethod.cpp b/mta-mono/src/CMonoMethod.cpp new file mode 100644 index 0000000..520b4e1 --- /dev/null +++ b/mta-mono/src/CMonoMethod.cpp @@ -0,0 +1,65 @@ +/********************************************************* +* +* Copyright © 2013, Innovation Roleplay Engine. +* +* All Rights Reserved. +* +* Redistribution and use in source and binary forms, +* with or without modification, +* is permitted only for authors. +* +*********************************************************/ + +#include "CMonoMethod.h" + +CMonoMethod::CMonoMethod( CMonoClass* pClass, MonoMethod* pMethod ) +{ + this->m_pClass = pClass; + this->m_pMethod = pMethod; + + this->m_strName = mono_method_get_name( pMethod ); + + this->ParseSignature(); +} + +CMonoMethod::~CMonoMethod( void ) +{ + this->m_pClass = nullptr; + this->m_pMethod = nullptr; +} + +void CMonoMethod::ParseSignature( void ) +{ + this->m_strSignature = ""; + + MonoMethodSignature* pSignature = mono_method_signature( this->m_pMethod ); + + if( pSignature ) + { + gpointer iter = nullptr; + + this->m_strSignature += this->GetName() + "("; + + while( MonoType* pType = mono_signature_get_params( pSignature, &iter ) ) + { + string strTypeName = mono_type_get_name( pType ); + int iType = mono_type_get_type( pType ); + + this->m_ArgList.push_back( { strTypeName, iType } ); + + if( this->m_ArgList.size() > 0 ) + { + this->m_strSignature += ", "; + } + + this->m_strSignature += strTypeName; + } + + this->m_strSignature += ")"; + } +} + +MonoObject* CMonoMethod::Invoke( void* pObject, void** params, MonoObject* pException ) +{ + return mono_runtime_invoke( this->m_pMethod, pObject, params, &pException ); +} \ No newline at end of file diff --git a/mta-mono/src/CMonoMethod.h b/mta-mono/src/CMonoMethod.h new file mode 100644 index 0000000..a28b1ee --- /dev/null +++ b/mta-mono/src/CMonoMethod.h @@ -0,0 +1,58 @@ +/********************************************************* +* +* Copyright © 2013, Innovation Roleplay Engine. +* +* All Rights Reserved. +* +* Redistribution and use in source and binary forms, +* with or without modification, +* is permitted only for authors. +* +*********************************************************/ + +class CMonoMethod; + +struct SMonoType; + +#ifndef __CMONOMETHOD_H +#define __CMONOMETHOD_H + +#include "CMonoClass.h" + +struct SMonoType +{ + string strName; + int iType; +}; + +class CMonoMethod +{ +private: + MonoMethod* m_pMethod; + + CMonoClass* m_pClass; + + vector< SMonoType > m_ArgList; + + string m_strName; + string m_strSignature; + +private: + void ParseSignature ( void ); + +public: + CMonoMethod ( CMonoClass* pClass, MonoMethod* pMethod ); + ~CMonoMethod ( void ); + + MonoObject* Invoke ( void* pObject, void** params, MonoObject* pException ); + + string GetSignature ( void ) { return this->m_strSignature; } + vector< SMonoType > GetArguments ( void ) { return this->m_ArgList; } + + MonoMethod* GetMonoPtr ( void ) { return this->m_pMethod; } + CMonoClass* GetMonoClass ( void ) { return this->m_pClass; } + + string GetName ( void ) { return this->m_strName; } +}; + +#endif \ No newline at end of file diff --git a/mta-mono/src/CResource.cpp b/mta-mono/src/CResource.cpp index a7cdde6..0046e4f 100644 --- a/mta-mono/src/CResource.cpp +++ b/mta-mono/src/CResource.cpp @@ -10,15 +10,7 @@ * *********************************************************/ -#include "StdInc.h" #include "CResource.h" -#include "CResourceManager.h" -#include "CFunctions.h" -#include "include/ILuaModuleManager.h" -#include "lua/CLuaFunctionDefinitions.h" - -extern ILuaModuleManager10 *g_pModuleManager; -extern CResourceManager *g_pResourceManager; CResource::CResource( CMonoInterface* pMono, lua_State *pLuaVM, string sName ) { @@ -36,6 +28,8 @@ CResource::CResource( CMonoInterface* pMono, lua_State *pLuaVM, string sName ) CResource::~CResource( void ) { + this->RemoveEvents(); + if( this->m_uiGCHandle ) { mono_gchandle_free( this->m_uiGCHandle ); @@ -58,43 +52,62 @@ CResource::~CResource( void ) this->m_pLuaVM = nullptr; } -bool CResource::CallEvent( string strEventName, void* pThis, void* pSource, void* pClient, void **args ) +bool CResource::CallEvent( string strEventName, void* pThis, list< CLuaArgument* > argv ) { - MonoEvent* pEvent = nullptr; - MonoMethod* method = nullptr; - CMonoClass* pClass = this->GetDomain()->GetMTALib()->GetClass( "Element" ); - MonoClass* klass = pClass->GetMonoPtr(); - - g_pModuleManager->DebugPrintf( this->GetLua(), "[%s] CResource::CallEvent::%s", this->m_sName.c_str(), strEventName.substr( 2 ).c_str() ); - - gpointer iter; - - while( klass ) + if( !pThis ) { - iter = nullptr; - - while( pEvent = mono_class_get_events( klass, &iter ) ) - { - if( !strcmp( strEventName.substr( 2 ).c_str(), mono_event_get_name( pEvent ) ) ) - { - method = mono_event_get_raise_method( pEvent ); - - break; - } - } - - klass = mono_class_get_parent( klass ); + return false; } - if( method ) + CMonoMTALib* pMTALib = this->GetDomain()->GetMTALib(); + + CMonoClass* pClass = pMTALib->GetClass( "Element" ); + CMonoEvent* pEvent = pClass->GetEvent( strEventName ); + + if( !pEvent ) { - mono_runtime_invoke( method, pThis, args, nullptr ); - + g_pModuleManager->ErrorPrintf( "[%s] event '%s' is class '%s' not found", this->m_sName.c_str(), strEventName.c_str(), pClass->GetName() ); + + return false; + } + + MonoObject* pThisObj = pMTALib->RegisterElement( pThis ); + + if( !pThisObj ) + { + return false; + } + + return pEvent->Call( pThisObj, argv ); +} + +bool CResource::AddEvent( const char* szName, const char* szHandleElement ) +{ + if( this->m_pLuaVM ) + { + char szBuffer[ 128 ]; + + sprintf( szBuffer, "addEventHandler( '%s', %s, _mono_event_handler, true, 'normal' );", szName, szHandleElement ); + + luaL_dostring( this->m_pLuaVM, szBuffer ); + return true; } - else + + return false; +} + +bool CResource::RemoveEvent( const char* szName, const char* szHandleElement ) +{ + if( this->m_pLuaVM ) { - g_pModuleManager->ErrorPrintf( "mono: method not found\n" ); + char szBuffer[ 128 ]; + + sprintf( szBuffer, "removeEventHandler( '%s', %s, _mono_event_handler );", szName, szHandleElement ); + + luaL_dostring( this->m_pLuaVM, szBuffer ); + + return true; } return false; @@ -106,12 +119,41 @@ void CResource::RegisterEvents( void ) { if( g_pModuleManager->RegisterFunction( this->m_pLuaVM, "mono_event_handler", CFunctions::monoEventHandler ) ) { - luaL_dostring( this->m_pLuaVM, "addEventHandler( 'onElementDestroy', resourceRoot, \ -function( ... ) \ - mono_event_handler( eventName, this, source, client, ... );\ -end \ -)" - ); + luaL_dostring( this->m_pLuaVM, "function _mono_event_handler( ... ) mono_event_handler( eventName, source, this, client, ... ); end" ); + + CMonoClass* pClass = this->GetDomain()->GetMTALib()->GetClass( "Element" ); + + if( pClass ) + { + for( auto iter : pClass->GetAllEvents() ) + { + string strEventName = iter.second->GetName(); + + strEventName[ 0 ] = tolower( strEventName[ 0 ] ); + + this->AddEvent( strEventName.c_str(), "root" ); + } + } + } + } +} + +void CResource::RemoveEvents( void ) +{ + if( this->m_pLuaVM ) + { + CMonoClass* pClass = this->GetDomain()->GetMTALib()->GetClass( "Element" ); + + if( pClass ) + { + for( auto iter : pClass->GetAllEvents() ) + { + string strEventName = iter.second->GetName(); + + strEventName[ 0 ] = tolower( strEventName[ 0 ] ); + + this->RemoveEvent( strEventName.c_str(), "root" ); + } } } } @@ -166,6 +208,7 @@ bool CResource::Init( void ) void CResource::OnStopping( void ) { + } void CResource::DoPulse( void ) diff --git a/mta-mono/src/CResource.h b/mta-mono/src/CResource.h index 8ca2251..94bccb4 100644 --- a/mta-mono/src/CResource.h +++ b/mta-mono/src/CResource.h @@ -17,9 +17,20 @@ class CResource; #include "Common.h" #include "CMonoClass.h" +#include "CMonoEvent.h" #include "CMonoInterface.h" + +#include "CResourceManager.h" +#include "CFunctions.h" + +#include "extra/CLuaArgument.h" #include "extra/CLuaArguments.h" +#include "include/ILuaModuleManager.h" +#include "lua/CLuaFunctionDefinitions.h" + +extern ILuaModuleManager10 *g_pModuleManager; + class CResource { private: @@ -40,9 +51,12 @@ public: CResource ( CMonoInterface* m_pMono, lua_State *pLuaVM, string sName ); ~CResource ( void ); - bool CallEvent ( string strEventName, void* pThis, void* pSource, void* pClient, void **args ); + bool CallEvent ( string strEventName, void* pThis, list< CLuaArgument* > argv ); + bool AddEvent ( const char* szName, const char* szHandleElement ); + bool RemoveEvent ( const char* szName, const char* szHandleElement ); void RegisterEvents ( void ); + void RemoveEvents ( void ); bool Init ( void ); void OnStopping ( void ); void DoPulse ( void ); @@ -56,6 +70,9 @@ public: lua_State* GetLua ( void ) { return this->m_pLuaVM; } CMonoInterface* GetMono ( void ) { return this->m_pMono; } CMonoDomain* GetDomain ( void ) { return this->m_pMonoDomain; } + +private: + }; #endif \ No newline at end of file