diff --git a/MultiTheftAuto b/MultiTheftAuto index 1396174..fe32901 160000 --- a/MultiTheftAuto +++ b/MultiTheftAuto @@ -1 +1 @@ -Subproject commit 13961748c6550de5674644eb0048f20460fa46c8 +Subproject commit fe32901717e73b39b133449512e9ca7230ef37c4 diff --git a/Test/Program.cs b/Test/Program.cs index 576ec5f..061e06e 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -9,18 +9,32 @@ namespace Test { static void Main( string[] args ) { - Element.Root.OnElementDestroy += Root_ElementDestroy; + Element.Root.OnElementDestroy += ( Element sender, ElementEventArgs e ) => + { + Debug.Info( "lambda " + sender.GetType() + " " + e.This.GetType() ); + }; Vehicle vehicle = new Vehicle( VehicleModel.ADMIRAL, Vector3.Zero, Vector3.Zero ); vehicle.OnElementDestroy += Root_ElementDestroy; - vehicle.Destroy(); + Event.Add( "onTest", true ); + + Event.AddHandler( "onTest", vehicle, new Action( testEvent_OnTrigger ) ); + + Event.Trigger( "onTest", vehicle, "test", 'a', true, false, 123, 456.7f, 1337.01d, null, vehicle ); + + //vehicle.Destroy(); } - public static void Root_ElementDestroy( Element sender, ElementEventArgs e ) + static void testEvent_OnTrigger( Element sender, string a, char b, bool c ) { - Debug.Info( "Root_ElementDestroy {0} {1}", sender.GetType(), e.This.GetType() ); + Debug.Info( "testEvent_OnTrigger " + sender.GetType() + " " + a + " " + b + " " + c ); + } + + static void Root_ElementDestroy( Element sender, ElementEventArgs e ) + { + Debug.Info( "Root_ElementDestroy " + sender.GetType() + " " + e.This.GetType() ); } } } diff --git a/mta-mono/mta-mono.vcxproj b/mta-mono/mta-mono.vcxproj index e2d49ee..8cd49a6 100644 --- a/mta-mono/mta-mono.vcxproj +++ b/mta-mono/mta-mono.vcxproj @@ -142,6 +142,8 @@ + + @@ -187,6 +189,8 @@ + + diff --git a/mta-mono/mta-mono.vcxproj.filters b/mta-mono/mta-mono.vcxproj.filters index 3a45a85..e321a1e 100644 --- a/mta-mono/mta-mono.vcxproj.filters +++ b/mta-mono/mta-mono.vcxproj.filters @@ -115,6 +115,12 @@ Lua + + ResourceInterface + + + ResourceInterface + @@ -266,6 +272,12 @@ Lua + + ResourceInterface + + + ResourceInterface + diff --git a/mta-mono/src/CEvent.cpp b/mta-mono/src/CEvent.cpp new file mode 100644 index 0000000..78716a6 --- /dev/null +++ b/mta-mono/src/CEvent.cpp @@ -0,0 +1,51 @@ +/********************************************************* +* +* 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 "CEvent.h" + +CEvent::CEvent( CEventManager* pEventManager, string strName, DWORD pElement, MonoObject* pMonoDelegate, bool bPropagated, string strPriority ) +{ + this->m_pEventManager = pEventManager; + + this->m_strName = strName; + this->m_pElement = pElement; + this->m_pMonoDelegate = pMonoDelegate; + this->m_bPropagated = bPropagated; + this->m_strPriority = strPriority; +} + +CEvent::~CEvent( void ) +{ + this->m_pMonoDelegate = nullptr; + this->m_bPropagated = nullptr; + + this->m_pEventManager = nullptr; +} + +bool CEvent::Call( DWORD pThis, void** params ) +{ + CResource* pResource = this->m_pEventManager->GetResource(); + + assert( pResource ); + + CMonoMTALib* pMTALib = pResource->GetDomain()->GetMTALib(); + + assert( pMTALib ); + + MonoObject* pException = nullptr; + + mono_runtime_delegate_invoke( this->m_pMonoDelegate, params, &pException ); + + pResource->GetDomain()->HandleException( pException ); + + return pException == nullptr; +} diff --git a/mta-mono/src/CEvent.h b/mta-mono/src/CEvent.h new file mode 100644 index 0000000..3a57ecb --- /dev/null +++ b/mta-mono/src/CEvent.h @@ -0,0 +1,49 @@ +/********************************************************* +* +* 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 CEvent; + +#ifndef __CEVENT_H +#define __CEVENT_H + +#include "extra/CLuaArgument.h" +#include "extra/CLuaArguments.h" + +#include "CResource.h" +#include "CEventManager.h" + +class CEvent +{ +private: + string m_strName; + DWORD m_pElement; + MonoObject* m_pMonoDelegate; + bool m_bPropagated; + string m_strPriority; + + + CEventManager* m_pEventManager; + +public: + CEvent ( CEventManager* pEventManager, string strName, DWORD pElement, MonoObject* pMonoDelegate, bool bPropagated, string strPriority ); + ~CEvent ( void ); + + bool Call ( DWORD pThis, void** params ); + + string GetName ( void ) { return this->m_strName; } + DWORD GetElement ( void ) { return this->m_pElement; } + MonoObject* GetDelegate ( void ) { return this->m_pMonoDelegate; } + bool IsPropagated ( void ) { return this->m_bPropagated; } + string GetPriority ( void ) { return this->m_strPriority; } +}; + +#endif \ No newline at end of file diff --git a/mta-mono/src/CEventManager.cpp b/mta-mono/src/CEventManager.cpp new file mode 100644 index 0000000..81ba902 --- /dev/null +++ b/mta-mono/src/CEventManager.cpp @@ -0,0 +1,196 @@ +/********************************************************* +* +* 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 "CEventManager.h" + +CEventManager::CEventManager( CResource* pResource ) +{ + this->m_pResource = pResource; +} + +CEventManager::~CEventManager( void ) +{ + this->DeleteAll(); + + this->m_pResource = nullptr; +} + +bool CEventManager::Add( string strName, DWORD pUserData, MonoObject* pMonoDelegate, bool bPropagated, string strPriority ) +{ + if( !pUserData ) + { + return false; + } + + CEvent* pEvent = new CEvent( this, strName, pUserData, pMonoDelegate, bPropagated, strPriority ); + + this->m_Events.insert( pair< string, CEvent* >( pEvent->GetName(), pEvent ) ); + + return true; +} + +bool CEventManager::Delete( string strName, DWORD pUserData, MonoObject* pMonoDelegate ) +{ + bool bFind = false; + + for( auto iter = this->m_Events.begin(); iter != this->m_Events.end(); iter++ ) + { + CEvent* pEvent = iter->second; + + if( pEvent->GetName() == strName && ( pMonoDelegate == nullptr || pEvent->GetDelegate() == pMonoDelegate ) ) + { + delete pEvent; + + this->m_Events.erase( iter ); + + bFind = true; + } + } + + return bFind; +} + +void CEventManager::DeleteAll( void ) +{ + multimap< string, CEvent* >::iterator iter = this->m_Events.begin(); + + while( iter != this->m_Events.end() ) + { + CEvent* pEvent = iter->second; + + delete pEvent; + + this->m_Events.erase( iter++ ); + } +} + +bool CEventManager::Call( string strName, void* pThis, list< CLuaArgument* > Arguments ) +{ + CMonoMTALib* pMTALib = this->GetResource()->GetDomain()->GetMTALib(); + + MonoObject* pThisObj = pMTALib->RegisterElement( pThis ); + + if( !pThisObj ) + { + return false; + } + + DWORD pSource = 0; + + auto *iter = *Arguments.begin(); + + if( iter->GetType() == LUA_TLIGHTUSERDATA ) + { + pSource = (DWORD)iter->GetLightUserData(); + } + + void** params = new void*[ Arguments.size() ]; + + this->ReadArgumens( Arguments, params ); + + for( auto iter : this->m_Events ) + { + CEvent* pEvent = iter.second; + + DWORD pElement = pEvent->GetElement(); + + if( pEvent->GetName() == strName && ( pElement == (DWORD)pThis || ( pEvent->IsPropagated() && pElement == pSource ) ) ) + { + pEvent->Call( (DWORD)pThis, params ); + } + } + + delete[] params; + + CMonoClass* pClass = pMTALib->GetClass( "Element" ); + + assert( pClass ); + + strName[ 0 ] = toupper( strName[ 0 ] ); + + CMonoEvent* pEvent = pClass->GetEvent( strName ); + + if( pEvent ) + { + return pEvent->Call( pThisObj, Arguments ); + } + + return true; +} + +void CEventManager::ReadArgumens( list< CLuaArgument* > Arguments, void** params ) +{ + CMonoDomain* pDomain = this->GetResource()->GetDomain(); + + CMonoMTALib* pMTALib = pDomain->GetMTALib(); + CMonoCorlib* pCorlib = pDomain->GetCorlib(); + + uint argc = 0; + + for( auto iter : Arguments ) + { + int iLuaType = iter->GetType(); + + switch( iLuaType ) + { + case LUA_TBOOLEAN: + { + bool bValue = iter->GetBoolean(); + + params[ argc++ ] = &bValue; + + break; + } + case LUA_TNUMBER: + { + double value = iter->GetNumber< double >(); + + MonoObject* pObj = pCorlib->Class[ "double" ]->Box( &value ); + + params[ argc++ ] = pObj; + + break; + } + case LUA_TSTRING: + { + const char* szValue = iter->GetString(); + + MonoString* pString = pDomain->NewString( szValue ); + + params[ argc++ ] = pString; + + break; + } + case LUA_TLIGHTUSERDATA: + { + void* pUserData = iter->GetLightUserData(); + + MonoObject* pValue = pMTALib->RegisterElement( pUserData ); + + if( pValue ) + { + params[ argc++ ] = pValue; + } + else + { + params[ argc++ ] = pUserData; + } + + break; + } + default: + { + break; + } + } + } +} diff --git a/mta-mono/src/CEventManager.h b/mta-mono/src/CEventManager.h new file mode 100644 index 0000000..438dece --- /dev/null +++ b/mta-mono/src/CEventManager.h @@ -0,0 +1,46 @@ +/********************************************************* +* +* 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 CEventManager; + +#ifndef __CEVENTMANAGER_H +#define __CEVENTMANAGER_H + +#include "CResource.h" +#include "CMonoDomain.h" +#include "CEvent.h" + +#include "extra/CLuaArgument.h" +#include "extra/CLuaArguments.h" + +class CEventManager +{ +private: + CResource* m_pResource; + multimap< string, CEvent* > m_Events; + +public: + CEventManager ( CResource* pResource ); + ~CEventManager ( void ); + + bool Add ( string strName, DWORD pUserData, MonoObject* pMonoDelegate, bool bPropagated, string strPriority ); + bool Delete ( string strName, DWORD pUserData, MonoObject* pMonoDelegate = nullptr ); + void DeleteAll ( void ); + + bool Call ( string strName, void* pThis, list< CLuaArgument* > Arguments ); + + void ReadArgumens ( list< CLuaArgument* > Arguments, void** params ); + + CResource* GetResource( void ) { return this->m_pResource; } +}; + +#endif diff --git a/mta-mono/src/CFunctions.cpp b/mta-mono/src/CFunctions.cpp index c6dd0fa..4b33bb8 100644 --- a/mta-mono/src/CFunctions.cpp +++ b/mta-mono/src/CFunctions.cpp @@ -21,8 +21,6 @@ int CFunctions::monoInit( lua_State *pLuaVM ) if( pResource == nullptr ) { - //if( g_pModuleManager->GetResourceName( luaVM, strName ) ) - CLuaArgument pLuaArgument( pLuaVM, -1 ); string strName = pLuaArgument.GetString(); @@ -78,8 +76,6 @@ int CFunctions::monoEventHandler( lua_State *pLuaVM ) { strEventName = iter->GetString(); - strEventName[ 0 ] = toupper( strEventName[ 0 ] ); - break; } case 2: diff --git a/mta-mono/src/CFunctions.h b/mta-mono/src/CFunctions.h index 53ac837..b7a90f5 100644 --- a/mta-mono/src/CFunctions.h +++ b/mta-mono/src/CFunctions.h @@ -27,8 +27,8 @@ extern ILuaModuleManager10 *g_pModuleManager; class CFunctions { public: - static int monoInit ( lua_State *pLuaVM ); - static int monoEventHandler ( lua_State *pLuaVM ); + static int monoInit ( lua_State *pLuaVM ); + static int monoEventHandler ( lua_State *pLuaVM ); }; #endif diff --git a/mta-mono/src/CMonoClass.cpp b/mta-mono/src/CMonoClass.cpp index 9bb8ea0..fa47b41 100644 --- a/mta-mono/src/CMonoClass.cpp +++ b/mta-mono/src/CMonoClass.cpp @@ -221,10 +221,10 @@ list< CMonoMethod* > CMonoClass::GetMethods( string strMethodName ) CMonoEvent* CMonoClass::GetEvent( string strEventName ) { - return this->m_Events[ strEventName ]; + return this->m_Events.count( strEventName ) ? this->m_Events[ strEventName ] : nullptr; } MonoClassField* CMonoClass::GetField( string strFieldName ) { - return this->m_Fields[ strFieldName ]; + return this->m_Fields.count( strFieldName ) ? this->m_Fields[ strFieldName ] : nullptr; } \ No newline at end of file diff --git a/mta-mono/src/CMonoFunctions.cpp b/mta-mono/src/CMonoFunctions.cpp index a642f69..2178bb2 100644 --- a/mta-mono/src/CMonoFunctions.cpp +++ b/mta-mono/src/CMonoFunctions.cpp @@ -37,7 +37,14 @@ void CMonoFunctions::AddInternals( void ) MONO_DECLARE( Game, SetRuleValue ); MONO_DECLARE( Game, RemoveRuleValue ); + MONO_DECLARE( Event, Add ); MONO_DECLARE( Event, AddHandler ); + MONO_DECLARE( Event, RemoveHandler ); + MONO_DECLARE( Event, Trigger ); + MONO_DECLARE( Event, Cancel ); + MONO_DECLARE( Event, WasCancelled ); + MONO_DECLARE( Event, GetCancelReason ); + MONO_DECLARE( Event, TriggerClient ); // Element create/destroy MONO_DECLARE( Element, Create ); diff --git a/mta-mono/src/CMonoFunctions.h b/mta-mono/src/CMonoFunctions.h index bf33d66..1040bb4 100644 --- a/mta-mono/src/CMonoFunctions.h +++ b/mta-mono/src/CMonoFunctions.h @@ -80,7 +80,15 @@ public: class Event { public: - static bool AddHandler ( MonoString* msName, DWORD pUserData, lua_CFunction iLuaFunction, bool bPropagated, MonoString* msEventPriority ); + static bool Add ( MonoString* msName, bool bAllowRemoteTrigger ); + static bool AddHandler ( MonoString* msName, DWORD pUserData, MonoObject* pDelegate, bool bPropagated, MonoString* msEventPriority ); + static bool RemoveHandler ( MonoString* msName, DWORD pUserData, MonoObject* pDelegate ); + static bool Trigger ( MonoString* msName, DWORD pUserData, MonoArray* mpArguments ); + static bool Cancel ( bool bCancel, MonoString* msReason ); + static bool WasCancelled ( void ); + static string GetCancelReason ( void ); + + static bool TriggerClient ( DWORD pSendTo, MonoString* msName, DWORD pSource, MonoArray* mpArguments ); }; class Element diff --git a/mta-mono/src/CMonoFunctions_Event.cpp b/mta-mono/src/CMonoFunctions_Event.cpp index bafe312..72c2f56 100644 --- a/mta-mono/src/CMonoFunctions_Event.cpp +++ b/mta-mono/src/CMonoFunctions_Event.cpp @@ -12,9 +12,145 @@ #include "CMonoFunctions.h" -bool CMonoFunctions::Event::AddHandler( MonoString* msName, DWORD pUserData, lua_CFunction iLuaFunction, bool bPropagated, MonoString* msEventPriority ) +bool CMonoFunctions::Event::Add( MonoString* msName, bool bAllowRemoteTrigger ) { - + if( RESOURCE ) + { + const char* szName = mono_string_to_utf8( msName ); + + if( CLuaFunctionDefinitions::AddEvent( RESOURCE->GetLua(), szName, bAllowRemoteTrigger ) ) + { + return RESOURCE->AddEvent( szName, "root" ); + } + } + + return false; +} + +bool CMonoFunctions::Event::AddHandler( MonoString* msName, DWORD pUserData, MonoObject* pDelegate, bool bPropagated, MonoString* msEventPriority ) +{ + if( RESOURCE ) + { + if( !pUserData ) + { + g_pModuleManager->ErrorPrintf( "Invalid argument #2 in method 'Event::AddHandler'\n" ); + + return false; + } + + if( !pDelegate ) + { + g_pModuleManager->ErrorPrintf( "Invalid argument #3 in method 'Event::AddHandler'\n" ); + + return false; + } + + string strEventName = mono_string_to_utf8( msName ); + + if( strEventName.length() == 0 ) + { + g_pModuleManager->ErrorPrintf( "Invalid argument #1 in method 'Event::AddHandler'\n" ); + + return false; + } + + string strEventPriority = mono_string_to_utf8( msEventPriority ); + + return RESOURCE->GetEventManager()->Add( strEventName, pUserData, pDelegate, bPropagated, strEventPriority ); + } + + return false; +} + +bool CMonoFunctions::Event::RemoveHandler( MonoString* msName, DWORD pUserData, MonoObject* pDelegate ) +{ + if( RESOURCE ) + { + if( !pUserData ) + { + g_pModuleManager->ErrorPrintf( "Invalid argument #2 in method 'Event::AddHandler'\n" ); + + return false; + } + + if( !pDelegate ) + { + g_pModuleManager->ErrorPrintf( "Invalid argument #3 in method 'Event::AddHandler'\n" ); + + return false; + } + + string strEventName = mono_string_to_utf8( msName ); + + if( strEventName.length() == 0 ) + { + g_pModuleManager->ErrorPrintf( "Invalid argument #1 in method 'Event::RemoveEvent'\n" ); + + return false; + } + + return RESOURCE->GetEventManager()->Delete( strEventName, pUserData, pDelegate ); + } + + return false; +} + +bool CMonoFunctions::Event::Trigger( MonoString* msName, DWORD pUserData, MonoArray* mpArguments ) +{ + if( RESOURCE ) + { + const char* szEventName = mono_string_to_utf8( msName ); + + CLuaArguments Arguments = CMonoInterface::MonoArrayToLuaArguments( mpArguments ); + + return CLuaFunctionDefinitions::TriggerEvent( RESOURCE->GetLua(), szEventName, (void*)pUserData, Arguments ); + } + + return false; +} + +bool CMonoFunctions::Event::Cancel( bool bCancel, MonoString* msReason ) +{ + if( RESOURCE ) + { + const char* szReason = mono_string_to_utf8( msReason ); + + return CLuaFunctionDefinitions::CancelEvent( RESOURCE->GetLua(), bCancel, szReason ); + } + + return false; +} + +bool CMonoFunctions::Event::WasCancelled( void ) +{ + if( RESOURCE ) + { + return CLuaFunctionDefinitions::WasEventCancelled( RESOURCE->GetLua() ); + } + + return false; +} + +string CMonoFunctions::Event::GetCancelReason( void ) +{ + if( RESOURCE ) + { + return CLuaFunctionDefinitions::GetCancelReason( RESOURCE->GetLua() ); + } + + return string(); +} + +bool CMonoFunctions::Event::TriggerClient( DWORD pSendTo, MonoString* msName, DWORD pSource, MonoArray* mpArguments ) +{ + if( RESOURCE ) + { + const char* szEventName = mono_string_to_utf8( msName ); + + CLuaArguments Arguments = CMonoInterface::MonoArrayToLuaArguments( mpArguments ); + + return CLuaFunctionDefinitions::TriggerClientEvent( RESOURCE->GetLua(), (void*)pSendTo, szEventName, (void*)pSource, Arguments ); + } return false; } diff --git a/mta-mono/src/CMonoInterface.cpp b/mta-mono/src/CMonoInterface.cpp index d98fb1a..ae9ebf0 100644 --- a/mta-mono/src/CMonoInterface.cpp +++ b/mta-mono/src/CMonoInterface.cpp @@ -53,3 +53,174 @@ void CMonoInterface::SetDomain( MonoDomain* pDomain, bool bForce ) { mono_domain_set( pDomain != nullptr ? pDomain : this->m_pMonoDomain, bForce ); } + +CLuaArguments CMonoInterface::MonoArrayToLuaArguments( MonoArray* pArray ) +{ + CLuaArguments pLuaArguments; + + unsigned int uiLength = mono_array_length( pArray ); + + for( unsigned int i = 0; i < uiLength; i++ ) + { + int iType = 0; + + MonoObject* pObj = mono_array_get( pArray, MonoObject*, i ); + MonoType* pType = nullptr; + + if( pObj ) + { + MonoClass* pClass = mono_object_get_class( pObj ); + + if( pClass ) + { + pType = mono_class_get_type( pClass ); + + if( pType ) + { + iType = mono_type_get_type( pType ); + } + } + } + + switch( iType ) + { + case NULL: + { + pLuaArguments.PushNil(); + + break; + } + case MONO_TYPE_BOOLEAN: // System.Boolean + { + bool bValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushBoolean( bValue ); + + break; + } + case MONO_TYPE_CHAR: // System.Char + { + wchar_t iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_STRING: // System.String + { + const char* szValue = mono_string_to_utf8( reinterpret_cast( pObj ) ); + + pLuaArguments.PushString( szValue ); + + break; + } + case MONO_TYPE_I1: // System.SByte + { + int8_t iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_U1: // System.Byte + { + uint8_t iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_I2: // System.Int16 + { + int16_t iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_U2: // System.UInt16 + { + uint16_t iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_I4: // System.Int32 + { + int32_t iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_U4: // System.UInt32 + { + uint32 iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_I8: // System.Int64 + { + int64_t iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_U8: // System.UInt64 + { + uint64_t iValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( iValue ); + + break; + } + case MONO_TYPE_R4: // System.Single + { + float fValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( fValue ); + + break; + } + case MONO_TYPE_R8: // System.Double + { + double dValue = *( reinterpret_cast( mono_object_unbox( pObj ) ) ); + + pLuaArguments.PushNumber( dValue ); + + break; + } + case MONO_TYPE_OBJECT: // System.Object + case MONO_TYPE_CLASS: + { + void* pValue = CMonoObject::GetPropertyValue( pObj, "userdata" ); + + if( pValue ) + { + pLuaArguments.PushUserData( pValue ); + + break; + } + + // do not break; + } + case MONO_TYPE_I: + case MONO_TYPE_U: + default: + { + g_pModuleManager->ErrorPrintf( "Unsupported type: %s (0x%i)\n", pType ? mono_type_get_name( pType ) : "(unknown type)", iType ); + + break; + } + } + + iType = 0; + pType = nullptr; + } + + return pLuaArguments; +} \ No newline at end of file diff --git a/mta-mono/src/CMonoInterface.h b/mta-mono/src/CMonoInterface.h index 1016636..e95d74e 100644 --- a/mta-mono/src/CMonoInterface.h +++ b/mta-mono/src/CMonoInterface.h @@ -19,6 +19,8 @@ class CMonoInterface; #include "CMonoDomain.h" #include "CResource.h" +#include "extra/CLuaArguments.h" + class CMonoInterface { private: @@ -38,11 +40,13 @@ public: #pragma region Static methods - static string GetBinariesDirectory( void ) + static string GetBinariesDirectory( void ) { return "mods/deathmatch/resources/[ire]"; } + static CLuaArguments MonoArrayToLuaArguments( MonoArray* pArray ); + #pragma endregion }; diff --git a/mta-mono/src/CResource.cpp b/mta-mono/src/CResource.cpp index 6c2779e..c5da67b 100644 --- a/mta-mono/src/CResource.cpp +++ b/mta-mono/src/CResource.cpp @@ -19,6 +19,8 @@ CResource::CResource( CMonoInterface* pMono, lua_State *pLuaVM, string sName ) this->m_sName = sName; this->m_pMonoDomain = nullptr; + + this->m_pEventManager = new CEventManager( this ); } CResource::~CResource( void ) @@ -27,10 +29,9 @@ CResource::~CResource( void ) this->GetMono()->GetGC()->Collect( this->GetMono()->GetGC()->GetMaxGeneration() ); - //this->GetMono()->SetDomain( nullptr, true ); - g_pResourceManager->RemoveFromList( this ); + SAFE_DELETE( this->m_pEventManager ); SAFE_DELETE( this->m_pMonoDomain ); this->GetMono()->SetDomain( nullptr, true ); @@ -46,26 +47,7 @@ bool CResource::CallEvent( string strEventName, void* pThis, list< CLuaArgument* return false; } - CMonoMTALib* pMTALib = this->GetDomain()->GetMTALib(); - - CMonoClass* pClass = pMTALib->GetClass( "Element" ); - CMonoEvent* pEvent = pClass->GetEvent( strEventName ); - - if( !pEvent ) - { - 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 ); + return this->m_pEventManager->Call( strEventName, pThis, argv ); } bool CResource::AddEvent( const char* szName, const char* szHandleElement ) diff --git a/mta-mono/src/CResource.h b/mta-mono/src/CResource.h index 4c41116..1301aa9 100644 --- a/mta-mono/src/CResource.h +++ b/mta-mono/src/CResource.h @@ -21,6 +21,7 @@ class CResource; #include "CMonoInterface.h" #include "CResourceManager.h" +#include "CEventManager.h" #include "CFunctions.h" #include "extra/CLuaArgument.h" @@ -41,6 +42,8 @@ private: CMonoInterface* m_pMono; CMonoDomain* m_pMonoDomain; + CEventManager* m_pEventManager; + public: CResource ( CMonoInterface* m_pMono, lua_State *pLuaVM, string sName ); ~CResource ( void ); @@ -64,6 +67,7 @@ public: lua_State* GetLua ( void ) { return this->m_pLuaVM; } CMonoInterface* GetMono ( void ) { return this->m_pMono; } CMonoDomain* GetDomain ( void ) { return this->m_pMonoDomain; } + CEventManager* GetEventManager ( void ) { return this->m_pEventManager; } private: diff --git a/mta-mono/src/lua/CLuaFunctionDefinitions.cpp b/mta-mono/src/lua/CLuaFunctionDefinitions.cpp index 7b02fa1..5c23da4 100644 --- a/mta-mono/src/lua/CLuaFunctionDefinitions.cpp +++ b/mta-mono/src/lua/CLuaFunctionDefinitions.cpp @@ -200,6 +200,26 @@ bool CLuaFunctionDefinitions::SetPlayerAnnounceValue( lua_State* pLuaVM, void* p return false; } +bool CLuaFunctionDefinitions::AddEvent( lua_State* pLuaVM, const char* szName, bool bAllowRemoteTrigger ) +{ + CLuaArguments pLuaArguments; + + pLuaArguments.PushString( szName ); + pLuaArguments.PushBoolean( bAllowRemoteTrigger ); + + if( pLuaArguments.Call( pLuaVM, "addEvent", 1 ) ) + { + CLuaArgument pLuaArgument( pLuaVM, -1 ); + + if( pLuaArgument.GetType() == LUA_TBOOLEAN ) + { + return pLuaArgument.GetBoolean(); + } + } + + return false; +} + bool CLuaFunctionDefinitions::AddEventHandler( lua_State* pLuaVM, const char* szName, void* pUserData, lua_CFunction iLuaFunction, bool bPropagated, const char* szEventPriority ) { CLuaArguments pLuaArguments; @@ -223,6 +243,127 @@ bool CLuaFunctionDefinitions::AddEventHandler( lua_State* pLuaVM, const char* sz return false; } +bool CLuaFunctionDefinitions::RemoveEventHandler( lua_State* pLuaVM, const char* szName, void* pUserData, lua_CFunction iLuaFunction ) +{ + CLuaArguments pLuaArguments; + + pLuaArguments.PushString( szName ); + pLuaArguments.PushUserData( pUserData ); + pLuaArguments.PushFunction( iLuaFunction ); + + if( pLuaArguments.Call( pLuaVM, "removeEventHandler", 1 ) ) + { + CLuaArgument pLuaArgument( pLuaVM, -1 ); + + if( pLuaArgument.GetType() == LUA_TBOOLEAN ) + { + return pLuaArgument.GetBoolean(); + } + } + + return false; +} + +bool CLuaFunctionDefinitions::TriggerEvent( lua_State* pLuaVM, const char* szName, void* pUserData, CLuaArguments& Arguments ) +{ + CLuaArguments pLuaArguments; + + pLuaArguments.PushString( szName ); + pLuaArguments.PushUserData( pUserData ); + pLuaArguments.PushArguments( Arguments ); + + if( pLuaArguments.Call( pLuaVM, "triggerEvent", 1 ) ) + { + CLuaArgument pLuaArgument( pLuaVM, -1 ); + + if( pLuaArgument.GetType() == LUA_TBOOLEAN ) + { + return pLuaArgument.GetBoolean(); + } + } + + return false; +} + +bool CLuaFunctionDefinitions::CancelEvent( lua_State* pLuaVM, bool bCancel, const char* szReason ) +{ + CLuaArguments pLuaArguments; + + pLuaArguments.PushBoolean( bCancel ); + pLuaArguments.PushString( szReason ); + + if( pLuaArguments.Call( pLuaVM, "cancelEvent", 1 ) ) + { + CLuaArgument pLuaArgument( pLuaVM, -1 ); + + if( pLuaArgument.GetType() == LUA_TBOOLEAN ) + { + return pLuaArgument.GetBoolean(); + } + } + + return false; +} + +bool CLuaFunctionDefinitions::WasEventCancelled( lua_State* pLuaVM ) +{ + CLuaArguments pLuaArguments; + + if( pLuaArguments.Call( pLuaVM, "wasEventCancelled", 1 ) ) + { + CLuaArgument pLuaArgument( pLuaVM, -1 ); + + if( pLuaArgument.GetType() == LUA_TBOOLEAN ) + { + return pLuaArgument.GetBoolean(); + } + } + + return false; +} + +string CLuaFunctionDefinitions::GetCancelReason( lua_State* pLuaVM ) +{ + CLuaArguments pLuaArguments; + + if( pLuaArguments.Call( pLuaVM, "getCancelReason", 1 ) ) + { + CLuaArgument pLuaArgument( pLuaVM, -1 ); + + if( pLuaArgument.GetType() == LUA_TSTRING ) + { + return pLuaArgument.GetString(); + } + } + + return string(); +} + +bool CLuaFunctionDefinitions::TriggerClientEvent( lua_State* pLuaVM, void* pSendTo, const char* szName, void* pSource, CLuaArguments& Arguments ) +{ + CLuaArguments pLuaArguments; + + if( pSendTo ) + { + pLuaArguments.PushUserData( pSendTo ); + } + + pLuaArguments.PushString( szName ); + pLuaArguments.PushUserData( pSource ); + pLuaArguments.PushArguments( Arguments ); + + if( pLuaArguments.Call( pLuaVM, "triggerClientEvent", 1 ) ) + { + CLuaArgument pLuaArgument( pLuaVM, -1 ); + + if( pLuaArgument.GetType() == LUA_TBOOLEAN ) + { + return pLuaArgument.GetBoolean(); + } + } + + return false; +} // Element create/destroy diff --git a/mta-mono/src/lua/CLuaFunctionDefinitions.h b/mta-mono/src/lua/CLuaFunctionDefinitions.h index 50b5c89..f58cd7c 100644 --- a/mta-mono/src/lua/CLuaFunctionDefinitions.h +++ b/mta-mono/src/lua/CLuaFunctionDefinitions.h @@ -41,20 +41,20 @@ public: // static int FetchRemote ( lua_State* luaVM ); // Event functions -// static bool AddEvent ( lua_State* pLuaVM, const char* szName, bool bAllowRemoteTrigger ); + static bool AddEvent ( lua_State* pLuaVM, const char* szName, bool bAllowRemoteTrigger ); static bool AddEventHandler ( lua_State* pLuaVM, const char* szName, void* pUserData, lua_CFunction iLuaFunction, bool bPropagated, const char* szEventPriority ); -// static bool RemoveEventHandler ( lua_State* pLuaVM, const char* szName, void* pUserData, const CLuaFunctionRef& iLuaFunction ); + static bool RemoveEventHandler ( lua_State* pLuaVM, const char* szName, void* pUserData, lua_CFunction iLuaFunction ); // static bool GetEventHandlers ( lua_State* pLuaVM, const char* szName ); -// static bool TriggerEvent ( lua_State* pLuaVM, const char* szName, void* pUserData, const CLuaArguments& Arguments, bool& bWasCancelled ); -// static bool CancelEvent ( lua_State* pLuaVM, bool bCancel ); -// static bool WasEventCancelled ( lua_State* pLuaVM ); + static bool TriggerEvent ( lua_State* pLuaVM, const char* szName, void* pUserData, CLuaArguments& Arguments ); + static bool CancelEvent ( lua_State* pLuaVM, bool bCancel, const char* szReason ); + static bool WasEventCancelled ( lua_State* pLuaVM ); + static string GetCancelReason ( lua_State* pLuaVM ); -// static int TriggerClientEvent ( lua_State* luaVM ); -// static int GetCancelReason ( lua_State* luaVM ); -// static int TriggerLatentClientEvent ( lua_State* luaVM ); -// static int GetLatentEventHandles ( lua_State* luaVM ); -// static int GetLatentEventStatus ( lua_State* luaVM ); -// static int CancelLatentEvent ( lua_State* luaVM ); + static bool TriggerClientEvent ( lua_State* pLuaVM, void* pSendTo, const char* szName, void* pSource, CLuaArguments& Arguments ); +// static int TriggerLatentClientEvent ( lua_State* pLuaVM ); +// static int GetLatentEventHandles ( lua_State* pLuaVM ); +// static int GetLatentEventStatus ( lua_State* pLuaVM ); +// static int CancelLatentEvent ( lua_State* pLuaVM ); // Element create/destroy static void* CreateElement ( lua_State* pLuaVM, const char* szTypeName, const char* szID );